## Automatically generated incremental diff
## From:   linux-2.5.8-pre1
## To:     linux-2.5.8-pre2
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.5.8-pre1/Documentation/networking/vortex.txt linux-2.5.8-pre2/Documentation/networking/vortex.txt
--- linux-2.5.8-pre1/Documentation/networking/vortex.txt	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/Documentation/networking/vortex.txt	Fri Apr  5 16:59:27 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 -urN linux-2.5.8-pre1/Makefile linux-2.5.8-pre2/Makefile
--- linux-2.5.8-pre1/Makefile	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/Makefile	Fri Apr  5 16:59:28 2002
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 8
-EXTRAVERSION =-pre1
+EXTRAVERSION =-pre2
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.5.8-pre1/Rules.make linux-2.5.8-pre2/Rules.make
--- linux-2.5.8-pre1/Rules.make	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/Rules.make	Fri Apr  5 16:59:28 2002
@@ -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 -urN linux-2.5.8-pre1/arch/alpha/kernel/core_irongate.c linux-2.5.8-pre2/arch/alpha/kernel/core_irongate.c
--- linux-2.5.8-pre1/arch/alpha/kernel/core_irongate.c	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/core_irongate.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_alcor.c linux-2.5.8-pre2/arch/alpha/kernel/sys_alcor.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_alcor.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_alcor.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_cabriolet.c linux-2.5.8-pre2/arch/alpha/kernel/sys_cabriolet.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_cabriolet.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_cabriolet.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_dp264.c linux-2.5.8-pre2/arch/alpha/kernel/sys_dp264.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_dp264.c	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_dp264.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_eb64p.c linux-2.5.8-pre2/arch/alpha/kernel/sys_eb64p.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_eb64p.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_eb64p.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_eiger.c linux-2.5.8-pre2/arch/alpha/kernel/sys_eiger.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_eiger.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_eiger.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_jensen.c linux-2.5.8-pre2/arch/alpha/kernel/sys_jensen.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_jensen.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_jensen.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_miata.c linux-2.5.8-pre2/arch/alpha/kernel/sys_miata.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_miata.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_miata.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_mikasa.c linux-2.5.8-pre2/arch/alpha/kernel/sys_mikasa.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_mikasa.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_mikasa.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_nautilus.c linux-2.5.8-pre2/arch/alpha/kernel/sys_nautilus.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_nautilus.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_nautilus.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_noritake.c linux-2.5.8-pre2/arch/alpha/kernel/sys_noritake.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_noritake.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_noritake.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_rawhide.c linux-2.5.8-pre2/arch/alpha/kernel/sys_rawhide.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_rawhide.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_rawhide.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_ruffian.c linux-2.5.8-pre2/arch/alpha/kernel/sys_ruffian.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_ruffian.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_ruffian.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_rx164.c linux-2.5.8-pre2/arch/alpha/kernel/sys_rx164.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_rx164.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_rx164.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_sable.c linux-2.5.8-pre2/arch/alpha/kernel/sys_sable.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_sable.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_sable.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_sio.c linux-2.5.8-pre2/arch/alpha/kernel/sys_sio.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_sio.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_sio.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_sx164.c linux-2.5.8-pre2/arch/alpha/kernel/sys_sx164.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_sx164.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_sx164.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_takara.c linux-2.5.8-pre2/arch/alpha/kernel/sys_takara.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_takara.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_takara.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_titan.c linux-2.5.8-pre2/arch/alpha/kernel/sys_titan.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_titan.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_titan.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/kernel/sys_wildfire.c linux-2.5.8-pre2/arch/alpha/kernel/sys_wildfire.c
--- linux-2.5.8-pre1/arch/alpha/kernel/sys_wildfire.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/arch/alpha/kernel/sys_wildfire.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/alpha/mm/fault.c linux-2.5.8-pre2/arch/alpha/mm/fault.c
--- linux-2.5.8-pre1/arch/alpha/mm/fault.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/arch/alpha/mm/fault.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/Config.help linux-2.5.8-pre2/arch/arm/Config.help
--- linux-2.5.8-pre1/arch/arm/Config.help	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/arch/arm/Config.help	Fri Apr  5 16:59:28 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.
@@ -711,6 +694,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.
   This is necessary to run most binaries. Linux does not currently
diff -urN linux-2.5.8-pre1/arch/arm/boot/compressed/head.S linux-2.5.8-pre2/arch/arm/boot/compressed/head.S
--- linux-2.5.8-pre1/arch/arm/boot/compressed/head.S	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/arch/arm/boot/compressed/head.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/config.in linux-2.5.8-pre2/arch/arm/config.in
--- linux-2.5.8-pre1/arch/arm/config.in	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/arch/arm/config.in	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/kernel/armksyms.c linux-2.5.8-pre2/arch/arm/kernel/armksyms.c
--- linux-2.5.8-pre1/arch/arm/kernel/armksyms.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/arch/arm/kernel/armksyms.c	Fri Apr  5 16:59:28 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.
@@ -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 -urN linux-2.5.8-pre1/arch/arm/kernel/bios32.c linux-2.5.8-pre2/arch/arm/kernel/bios32.c
--- linux-2.5.8-pre1/arch/arm/kernel/bios32.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/arch/arm/kernel/bios32.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/kernel/debug.S linux-2.5.8-pre2/arch/arm/kernel/debug.S
--- linux-2.5.8-pre1/arch/arm/kernel/debug.S	Mon Mar 18 12:37:11 2002
+++ linux-2.5.8-pre2/arch/arm/kernel/debug.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/kernel/ecard.c linux-2.5.8-pre2/arch/arm/kernel/ecard.c
--- linux-2.5.8-pre1/arch/arm/kernel/ecard.c	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/arch/arm/kernel/ecard.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/kernel/entry-armv.S linux-2.5.8-pre2/arch/arm/kernel/entry-armv.S
--- linux-2.5.8-pre1/arch/arm/kernel/entry-armv.S	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/arch/arm/kernel/entry-armv.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/kernel/entry-header.S linux-2.5.8-pre2/arch/arm/kernel/entry-header.S
--- linux-2.5.8-pre1/arch/arm/kernel/entry-header.S	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/arch/arm/kernel/entry-header.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/kernel/irq.c linux-2.5.8-pre2/arch/arm/kernel/irq.c
--- linux-2.5.8-pre1/arch/arm/kernel/irq.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/arch/arm/kernel/irq.c	Fri Apr  5 16:59:28 2002
@@ -325,9 +325,8 @@
 				   !check_irq_lock(desc, irq, regs)))
 				desc->chip->unmask(irq);
 		}
+		irq_exit(cpu, irq);
 	}
-
-	irq_exit(cpu, irq);
 }
 
 /*
diff -urN linux-2.5.8-pre1/arch/arm/kernel/ptrace.c linux-2.5.8-pre2/arch/arm/kernel/ptrace.c
--- linux-2.5.8-pre1/arch/arm/kernel/ptrace.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/arch/arm/kernel/ptrace.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/kernel/signal.c linux-2.5.8-pre2/arch/arm/kernel/signal.c
--- linux-2.5.8-pre1/arch/arm/kernel/signal.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/arch/arm/kernel/signal.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/kernel/traps.c linux-2.5.8-pre2/arch/arm/kernel/traps.c
--- linux-2.5.8-pre1/arch/arm/kernel/traps.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/arch/arm/kernel/traps.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/lib/findbit.S linux-2.5.8-pre2/arch/arm/lib/findbit.S
--- linux-2.5.8-pre1/arch/arm/lib/findbit.S	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/arch/arm/lib/findbit.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/lib/memchr.S linux-2.5.8-pre2/arch/arm/lib/memchr.S
--- linux-2.5.8-pre1/arch/arm/lib/memchr.S	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/arch/arm/lib/memchr.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/lib/udivdi3.c linux-2.5.8-pre2/arch/arm/lib/udivdi3.c
--- linux-2.5.8-pre1/arch/arm/lib/udivdi3.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/arch/arm/lib/udivdi3.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-footbridge/arch.c linux-2.5.8-pre2/arch/arm/mach-footbridge/arch.c
--- linux-2.5.8-pre1/arch/arm/mach-footbridge/arch.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/arch/arm/mach-footbridge/arch.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-iop310/iq80310-time.c linux-2.5.8-pre2/arch/arm/mach-iop310/iq80310-time.c
--- linux-2.5.8-pre1/arch/arm/mach-iop310/iq80310-time.c	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/arch/arm/mach-iop310/iq80310-time.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-pxa/Makefile linux-2.5.8-pre2/arch/arm/mach-pxa/Makefile
--- linux-2.5.8-pre1/arch/arm/mach-pxa/Makefile	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/arch/arm/mach-pxa/Makefile	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-pxa/dma.c linux-2.5.8-pre2/arch/arm/mach-pxa/dma.c
--- linux-2.5.8-pre1/arch/arm/mach-pxa/dma.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/arch/arm/mach-pxa/dma.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-pxa/generic.c linux-2.5.8-pre2/arch/arm/mach-pxa/generic.c
--- linux-2.5.8-pre1/arch/arm/mach-pxa/generic.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/arch/arm/mach-pxa/generic.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-pxa/generic.h linux-2.5.8-pre2/arch/arm/mach-pxa/generic.h
--- linux-2.5.8-pre1/arch/arm/mach-pxa/generic.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/arch/arm/mach-pxa/generic.h	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-pxa/idp.c linux-2.5.8-pre2/arch/arm/mach-pxa/idp.c
--- linux-2.5.8-pre1/arch/arm/mach-pxa/idp.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/arch/arm/mach-pxa/idp.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-pxa/irq.c linux-2.5.8-pre2/arch/arm/mach-pxa/irq.c
--- linux-2.5.8-pre1/arch/arm/mach-pxa/irq.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/arch/arm/mach-pxa/irq.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-pxa/leds-idp.c linux-2.5.8-pre2/arch/arm/mach-pxa/leds-idp.c
--- linux-2.5.8-pre1/arch/arm/mach-pxa/leds-idp.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/arch/arm/mach-pxa/leds-idp.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-pxa/leds-lubbock.c linux-2.5.8-pre2/arch/arm/mach-pxa/leds-lubbock.c
--- linux-2.5.8-pre1/arch/arm/mach-pxa/leds-lubbock.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/arch/arm/mach-pxa/leds-lubbock.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-pxa/leds.c linux-2.5.8-pre2/arch/arm/mach-pxa/leds.c
--- linux-2.5.8-pre1/arch/arm/mach-pxa/leds.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/arch/arm/mach-pxa/leds.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-pxa/leds.h linux-2.5.8-pre2/arch/arm/mach-pxa/leds.h
--- linux-2.5.8-pre1/arch/arm/mach-pxa/leds.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/arch/arm/mach-pxa/leds.h	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-pxa/lubbock.c linux-2.5.8-pre2/arch/arm/mach-pxa/lubbock.c
--- linux-2.5.8-pre1/arch/arm/mach-pxa/lubbock.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/arch/arm/mach-pxa/lubbock.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-sa1100/badge4.c linux-2.5.8-pre2/arch/arm/mach-sa1100/badge4.c
--- linux-2.5.8-pre1/arch/arm/mach-sa1100/badge4.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/arch/arm/mach-sa1100/badge4.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-sa1100/generic.c linux-2.5.8-pre2/arch/arm/mach-sa1100/generic.c
--- linux-2.5.8-pre1/arch/arm/mach-sa1100/generic.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/arch/arm/mach-sa1100/generic.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-sa1100/generic.h linux-2.5.8-pre2/arch/arm/mach-sa1100/generic.h
--- linux-2.5.8-pre1/arch/arm/mach-sa1100/generic.h	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/arch/arm/mach-sa1100/generic.h	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-sa1100/h3600.c linux-2.5.8-pre2/arch/arm/mach-sa1100/h3600.c
--- linux-2.5.8-pre1/arch/arm/mach-sa1100/h3600.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/arch/arm/mach-sa1100/h3600.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-sa1100/leds.c linux-2.5.8-pre2/arch/arm/mach-sa1100/leds.c
--- linux-2.5.8-pre1/arch/arm/mach-sa1100/leds.c	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/arch/arm/mach-sa1100/leds.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-sa1100/leds.h linux-2.5.8-pre2/arch/arm/mach-sa1100/leds.h
--- linux-2.5.8-pre1/arch/arm/mach-sa1100/leds.h	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/arch/arm/mach-sa1100/leds.h	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-sa1100/sa1111.c linux-2.5.8-pre2/arch/arm/mach-sa1100/sa1111.c
--- linux-2.5.8-pre1/arch/arm/mach-sa1100/sa1111.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/arch/arm/mach-sa1100/sa1111.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mach-sa1100/sa1111.h linux-2.5.8-pre2/arch/arm/mach-sa1100/sa1111.h
--- linux-2.5.8-pre1/arch/arm/mach-sa1100/sa1111.h	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/arch/arm/mach-sa1100/sa1111.h	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/fault-armv.c linux-2.5.8-pre2/arch/arm/mm/fault-armv.c
--- linux-2.5.8-pre1/arch/arm/mm/fault-armv.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/arch/arm/mm/fault-armv.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/init.c linux-2.5.8-pre2/arch/arm/mm/init.c
--- linux-2.5.8-pre1/arch/arm/mm/init.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/arch/arm/mm/init.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/mm-armv.c linux-2.5.8-pre2/arch/arm/mm/mm-armv.c
--- linux-2.5.8-pre1/arch/arm/mm/mm-armv.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/arch/arm/mm/mm-armv.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/proc-arm1020.S linux-2.5.8-pre2/arch/arm/mm/proc-arm1020.S
--- linux-2.5.8-pre1/arch/arm/mm/proc-arm1020.S	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/arch/arm/mm/proc-arm1020.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/proc-arm6,7.S linux-2.5.8-pre2/arch/arm/mm/proc-arm6,7.S
--- linux-2.5.8-pre1/arch/arm/mm/proc-arm6,7.S	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/arch/arm/mm/proc-arm6,7.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/proc-arm720.S linux-2.5.8-pre2/arch/arm/mm/proc-arm720.S
--- linux-2.5.8-pre1/arch/arm/mm/proc-arm720.S	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/arch/arm/mm/proc-arm720.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/proc-arm920.S linux-2.5.8-pre2/arch/arm/mm/proc-arm920.S
--- linux-2.5.8-pre1/arch/arm/mm/proc-arm920.S	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/arch/arm/mm/proc-arm920.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/proc-arm922.S linux-2.5.8-pre2/arch/arm/mm/proc-arm922.S
--- linux-2.5.8-pre1/arch/arm/mm/proc-arm922.S	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/arch/arm/mm/proc-arm922.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/proc-arm926.S linux-2.5.8-pre2/arch/arm/mm/proc-arm926.S
--- linux-2.5.8-pre1/arch/arm/mm/proc-arm926.S	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/arch/arm/mm/proc-arm926.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/proc-macros.S linux-2.5.8-pre2/arch/arm/mm/proc-macros.S
--- linux-2.5.8-pre1/arch/arm/mm/proc-macros.S	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/arch/arm/mm/proc-macros.S	Fri Apr  5 16:59:28 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>
 
 /*
@@ -14,6 +21,11 @@
 	ldr	\rd, [\rn, #VMA_VM_FLAGS]
 	.endm
 
+	.macro	tsk_mm, rd, rn
+	ldr	\rd, [\rn, #TI_TASK]
+	ldr	\rd, [\rd, #TSK_ACTIVE_MM]
+	.endm
+
 /*
  * act_mm - get current->active_mm
  */
diff -urN linux-2.5.8-pre1/arch/arm/mm/proc-sa110.S linux-2.5.8-pre2/arch/arm/mm/proc-sa110.S
--- linux-2.5.8-pre1/arch/arm/mm/proc-sa110.S	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/arch/arm/mm/proc-sa110.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/proc-syms.c linux-2.5.8-pre2/arch/arm/mm/proc-syms.c
--- linux-2.5.8-pre1/arch/arm/mm/proc-syms.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/arch/arm/mm/proc-syms.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/proc-xscale.S linux-2.5.8-pre2/arch/arm/mm/proc-xscale.S
--- linux-2.5.8-pre1/arch/arm/mm/proc-xscale.S	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/arch/arm/mm/proc-xscale.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/tlb-v3.S linux-2.5.8-pre2/arch/arm/mm/tlb-v3.S
--- linux-2.5.8-pre1/arch/arm/mm/tlb-v3.S	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/arch/arm/mm/tlb-v3.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/tlb-v4.S linux-2.5.8-pre2/arch/arm/mm/tlb-v4.S
--- linux-2.5.8-pre1/arch/arm/mm/tlb-v4.S	Mon Mar 18 12:37:11 2002
+++ linux-2.5.8-pre2/arch/arm/mm/tlb-v4.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/mm/tlb-v4wb.S linux-2.5.8-pre2/arch/arm/mm/tlb-v4wb.S
--- linux-2.5.8-pre1/arch/arm/mm/tlb-v4wb.S	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/arch/arm/mm/tlb-v4wb.S	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/arm/tools/mach-types linux-2.5.8-pre2/arch/arm/tools/mach-types
--- linux-2.5.8-pre1/arch/arm/tools/mach-types	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/arch/arm/tools/mach-types	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/cris/drivers/ethernet.c linux-2.5.8-pre2/arch/cris/drivers/ethernet.c
--- linux-2.5.8-pre1/arch/cris/drivers/ethernet.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/arch/cris/drivers/ethernet.c	Fri Apr  5 16:59:28 2002
@@ -1313,7 +1313,7 @@
 static void
 e100_clear_network_leds(unsigned long dummy)
 {
-	if (led_active && jiffies > time_after(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 -urN linux-2.5.8-pre1/arch/i386/boot/setup.S linux-2.5.8-pre2/arch/i386/boot/setup.S
--- linux-2.5.8-pre1/arch/i386/boot/setup.S	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/arch/i386/boot/setup.S	Mon Mar 18 12:37:03 2002
@@ -544,7 +544,7 @@
 	cmpw	$0, %cs:realmode_swtch
 	jz	rmodeswtch_normal
 
-	lcall	%cs:realmode_swtch
+	lcall	*%cs:realmode_swtch
 
 	jmp	rmodeswtch_end
 
diff -urN linux-2.5.8-pre1/arch/i386/defconfig linux-2.5.8-pre2/arch/i386/defconfig
--- linux-2.5.8-pre1/arch/i386/defconfig	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/arch/i386/defconfig	Fri Apr  5 16:59:28 2002
@@ -848,10 +848,16 @@
 #
 # 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
@@ -874,6 +880,7 @@
 # USB Network adaptors
 #
 # CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_CDCETHER is not set
@@ -908,9 +915,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
@@ -920,6 +929,7 @@
 #
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_TIGL is not set
 
 #
 # Kernel hacking
diff -urN linux-2.5.8-pre1/arch/i386/kernel/acpi.c linux-2.5.8-pre2/arch/i386/kernel/acpi.c
--- linux-2.5.8-pre1/arch/i386/kernel/acpi.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/arch/i386/kernel/acpi.c	Fri Apr  5 16:59:28 2002
@@ -43,6 +43,7 @@
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/io_apic.h>
+#include <asm/tlbflush.h>
 
 
 #define PREFIX			"ACPI: "
diff -urN linux-2.5.8-pre1/arch/i386/kernel/bluesmoke.c linux-2.5.8-pre2/arch/i386/kernel/bluesmoke.c
--- linux-2.5.8-pre1/arch/i386/kernel/bluesmoke.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/arch/i386/kernel/bluesmoke.c	Fri Apr  5 16:59:28 2002
@@ -11,6 +11,7 @@
 #include <asm/msr.h>
 #include <asm/apic.h>
 #include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 
 #ifdef CONFIG_X86_MCE
 
diff -urN linux-2.5.8-pre1/arch/i386/kernel/entry.S linux-2.5.8-pre2/arch/i386/kernel/entry.S
--- linux-2.5.8-pre1/arch/i386/kernel/entry.S	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/arch/i386/kernel/entry.S	Fri Apr  5 16:59:28 2002
@@ -238,12 +238,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
diff -urN linux-2.5.8-pre1/arch/i386/kernel/i386_ksyms.c linux-2.5.8-pre2/arch/i386/kernel/i386_ksyms.c
--- linux-2.5.8-pre1/arch/i386/kernel/i386_ksyms.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/arch/i386/kernel/i386_ksyms.c	Fri Apr  5 16:59:28 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;
diff -urN linux-2.5.8-pre1/arch/i386/kernel/ptrace.c linux-2.5.8-pre2/arch/i386/kernel/ptrace.c
--- linux-2.5.8-pre1/arch/i386/kernel/ptrace.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/arch/i386/kernel/ptrace.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/i386/kernel/signal.c linux-2.5.8-pre2/arch/i386/kernel/signal.c
--- linux-2.5.8-pre1/arch/i386/kernel/signal.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/arch/i386/kernel/signal.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/i386/kernel/smp.c linux-2.5.8-pre2/arch/i386/kernel/smp.c
--- linux-2.5.8-pre1/arch/i386/kernel/smp.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/arch/i386/kernel/smp.c	Fri Apr  5 16:59:28 2002
@@ -21,6 +21,7 @@
 
 #include <asm/mtrr.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 #include <asm/smpboot.h>
 
 /*
diff -urN linux-2.5.8-pre1/arch/i386/kernel/smpboot.c linux-2.5.8-pre2/arch/i386/kernel/smpboot.c
--- linux-2.5.8-pre1/arch/i386/kernel/smpboot.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/arch/i386/kernel/smpboot.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/i386/kernel/vm86.c linux-2.5.8-pre2/arch/i386/kernel/vm86.c
--- linux-2.5.8-pre1/arch/i386/kernel/vm86.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/arch/i386/kernel/vm86.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/i386/mm/init.c linux-2.5.8-pre2/arch/i386/mm/init.c
--- linux-2.5.8-pre1/arch/i386/mm/init.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/arch/i386/mm/init.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/i386/mm/ioremap.c linux-2.5.8-pre2/arch/i386/mm/ioremap.c
--- linux-2.5.8-pre1/arch/i386/mm/ioremap.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/arch/i386/mm/ioremap.c	Fri Apr  5 16:59:28 2002
@@ -12,6 +12,9 @@
 #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)
diff -urN linux-2.5.8-pre1/arch/ia64/kernel/efivars.c linux-2.5.8-pre2/arch/ia64/kernel/efivars.c
--- linux-2.5.8-pre1/arch/ia64/kernel/efivars.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/arch/ia64/kernel/efivars.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/ia64/kernel/mca.c linux-2.5.8-pre2/arch/ia64/kernel/mca.c
--- linux-2.5.8-pre1/arch/ia64/kernel/mca.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/arch/ia64/kernel/mca.c	Fri Apr  5 16:59:28 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 -urN linux-2.5.8-pre1/arch/sparc64/kernel/binfmt_elf32.c linux-2.5.8-pre2/arch/sparc64/kernel/binfmt_elf32.c
--- linux-2.5.8-pre1/arch/sparc64/kernel/binfmt_elf32.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/arch/sparc64/kernel/binfmt_elf32.c	Mon Mar 18 12:37:10 2002
@@ -43,7 +43,7 @@
 	dest[34] = (unsigned int) src->tnpc;		\
 	dest[35] = src->y;				\
 	dest[36] = dest[37] = 0; /* XXX */		\
-} while(0)
+} while(0);
 
 typedef struct {
 	union {
diff -urN linux-2.5.8-pre1/arch/sparc64/kernel/process.c linux-2.5.8-pre2/arch/sparc64/kernel/process.c
--- linux-2.5.8-pre1/arch/sparc64/kernel/process.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/arch/sparc64/kernel/process.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/arch/sparc64/kernel/semaphore.c linux-2.5.8-pre2/arch/sparc64/kernel/semaphore.c
--- linux-2.5.8-pre1/arch/sparc64/kernel/semaphore.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/arch/sparc64/kernel/semaphore.c	Fri Apr  5 16:59:29 2002
@@ -7,6 +7,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/errno.h>
 
 /*
  * Atomically update sem->count.
diff -urN linux-2.5.8-pre1/arch/sparc64/math-emu/math.c linux-2.5.8-pre2/arch/sparc64/math-emu/math.c
--- linux-2.5.8-pre1/arch/sparc64/math-emu/math.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/arch/sparc64/math-emu/math.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/acorn/scsi/eesox.c linux-2.5.8-pre2/drivers/acorn/scsi/eesox.c
--- linux-2.5.8-pre1/drivers/acorn/scsi/eesox.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/drivers/acorn/scsi/eesox.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/base/Makefile linux-2.5.8-pre2/drivers/base/Makefile
--- linux-2.5.8-pre1/drivers/base/Makefile	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/drivers/base/Makefile	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/base/base.h linux-2.5.8-pre2/drivers/base/base.h
--- linux-2.5.8-pre1/drivers/base/base.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/base/base.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/base/core.c linux-2.5.8-pre2/drivers/base/core.c
--- linux-2.5.8-pre1/drivers/base/core.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/drivers/base/core.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/base/power.c linux-2.5.8-pre2/drivers/base/power.c
--- linux-2.5.8-pre1/drivers/base/power.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/base/power.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/base/sys.c linux-2.5.8-pre2/drivers/base/sys.c
--- linux-2.5.8-pre1/drivers/base/sys.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/base/sys.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/block/elevator.c linux-2.5.8-pre2/drivers/block/elevator.c
--- linux-2.5.8-pre1/drivers/block/elevator.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/drivers/block/elevator.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/char/ds1620.c linux-2.5.8-pre2/drivers/char/ds1620.c
--- linux-2.5.8-pre1/drivers/char/ds1620.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/drivers/char/ds1620.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/char/nwflash.c linux-2.5.8-pre2/drivers/char/nwflash.c
--- linux-2.5.8-pre1/drivers/char/nwflash.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/drivers/char/nwflash.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/media/video/videodev.c linux-2.5.8-pre2/drivers/media/video/videodev.c
--- linux-2.5.8-pre1/drivers/media/video/videodev.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/media/video/videodev.c	Fri Apr  5 16:59:29 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>
diff -urN linux-2.5.8-pre1/drivers/net/3c59x.c linux-2.5.8-pre2/drivers/net/3c59x.c
--- linux-2.5.8-pre1/drivers/net/3c59x.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/drivers/net/3c59x.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/7990.c linux-2.5.8-pre2/drivers/net/7990.c
--- linux-2.5.8-pre1/drivers/net/7990.c	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/drivers/net/7990.c	Fri Apr  5 16:59:29 2002
@@ -630,3 +630,4 @@
 		netif_start_queue (dev);
 }
 
+MODULE_LICENSE("GPL");
diff -urN linux-2.5.8-pre1/drivers/net/a2065.c linux-2.5.8-pre2/drivers/net/a2065.c
--- linux-2.5.8-pre1/drivers/net/a2065.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/drivers/net/a2065.c	Fri Apr  5 16:59:29 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,15 +495,15 @@
 
 	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 -urN linux-2.5.8-pre1/drivers/net/arcnet/arc-rawmode.c linux-2.5.8-pre2/drivers/net/arcnet/arc-rawmode.c
--- linux-2.5.8-pre1/drivers/net/arcnet/arc-rawmode.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/drivers/net/arcnet/arc-rawmode.c	Fri Apr  5 16:59:29 2002
@@ -83,6 +83,7 @@
 	arcnet_unregister_proto(&rawmode_proto);
 }
 
+MODULE_LICENSE("GPL");
 #endif				/* MODULE */
 
 
diff -urN linux-2.5.8-pre1/drivers/net/arcnet/arc-rimi.c linux-2.5.8-pre2/drivers/net/arcnet/arc-rimi.c
--- linux-2.5.8-pre1/drivers/net/arcnet/arc-rimi.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/arcnet/arc-rimi.c	Fri Apr  5 16:59:29 2002
@@ -295,6 +295,7 @@
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
 MODULE_PARM(device, "s");
+MODULE_LICENSE("GPL");
 
 int init_module(void)
 {
diff -urN linux-2.5.8-pre1/drivers/net/arcnet/arcnet.c linux-2.5.8-pre2/drivers/net/arcnet/arcnet.c
--- linux-2.5.8-pre1/drivers/net/arcnet/arcnet.c	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/drivers/net/arcnet/arcnet.c	Fri Apr  5 16:59:29 2002
@@ -163,6 +163,7 @@
 
 static int debug = ARCNET_DEBUG;
 MODULE_PARM(debug, "i");
+MODULE_LICENSE("GPL");
 
 int __init init_module(void)
 {
diff -urN linux-2.5.8-pre1/drivers/net/arcnet/com20020-isa.c linux-2.5.8-pre2/drivers/net/arcnet/com20020-isa.c
--- linux-2.5.8-pre1/drivers/net/arcnet/com20020-isa.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/drivers/net/arcnet/com20020-isa.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/arcnet/com20020-pci.c linux-2.5.8-pre2/drivers/net/arcnet/com20020-pci.c
--- linux-2.5.8-pre1/drivers/net/arcnet/com20020-pci.c	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/drivers/net/arcnet/com20020-pci.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/arcnet/com20020.c linux-2.5.8-pre2/drivers/net/arcnet/com20020.c
--- linux-2.5.8-pre1/drivers/net/arcnet/com20020.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/net/arcnet/com20020.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/arcnet/com90io.c linux-2.5.8-pre2/drivers/net/arcnet/com90io.c
--- linux-2.5.8-pre1/drivers/net/arcnet/com90io.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/net/arcnet/com90io.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/arcnet/com90xx.c linux-2.5.8-pre2/drivers/net/arcnet/com90xx.c
--- linux-2.5.8-pre1/drivers/net/arcnet/com90xx.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/arcnet/com90xx.c	Fri Apr  5 16:59:29 2002
@@ -617,6 +617,7 @@
 MODULE_PARM(irq, "i");
 MODULE_PARM(shmem, "i");
 MODULE_PARM(device, "s");
+MODULE_LICENSE("GPL");
 
 int init_module(void)
 {
diff -urN linux-2.5.8-pre1/drivers/net/arcnet/rfc1051.c linux-2.5.8-pre2/drivers/net/arcnet/rfc1051.c
--- linux-2.5.8-pre1/drivers/net/arcnet/rfc1051.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/drivers/net/arcnet/rfc1051.c	Fri Apr  5 16:59:29 2002
@@ -68,6 +68,8 @@
 
 #ifdef MODULE
 
+MODULE_LICENSE("GPL");
+
 int __init init_module(void)
 {
 	printk(VERSION);
diff -urN linux-2.5.8-pre1/drivers/net/arcnet/rfc1201.c linux-2.5.8-pre2/drivers/net/arcnet/rfc1201.c
--- linux-2.5.8-pre1/drivers/net/arcnet/rfc1201.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/drivers/net/arcnet/rfc1201.c	Fri Apr  5 16:59:29 2002
@@ -70,6 +70,8 @@
 
 #ifdef MODULE
 
+MODULE_LICENSE("GPL");
+
 int __init init_module(void)
 {
 	printk(VERSION);
diff -urN linux-2.5.8-pre1/drivers/net/ariadne.c linux-2.5.8-pre2/drivers/net/ariadne.c
--- linux-2.5.8-pre1/drivers/net/ariadne.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/drivers/net/ariadne.c	Fri Apr  5 16:59:29 2002
@@ -847,3 +847,5 @@
 
 module_init(ariadne_probe);
 module_exit(ariadne_cleanup);
+
+MODULE_LICENSE("GPL");
diff -urN linux-2.5.8-pre1/drivers/net/ariadne2.c linux-2.5.8-pre2/drivers/net/ariadne2.c
--- linux-2.5.8-pre1/drivers/net/ariadne2.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/drivers/net/ariadne2.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/arlan.c linux-2.5.8-pre2/drivers/net/arlan.c
--- linux-2.5.8-pre1/drivers/net/arlan.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/arlan.c	Fri Apr  5 16:59:29 2002
@@ -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;
diff -urN linux-2.5.8-pre1/drivers/net/au1000_eth.c linux-2.5.8-pre2/drivers/net/au1000_eth.c
--- linux-2.5.8-pre1/drivers/net/au1000_eth.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/drivers/net/au1000_eth.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/au1000_eth.h linux-2.5.8-pre2/drivers/net/au1000_eth.h
--- linux-2.5.8-pre1/drivers/net/au1000_eth.h	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/net/au1000_eth.h	Fri Apr  5 16:59:29 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
@@ -124,6 +126,11 @@
 #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
 #define MII_AUX_100      0x0002
diff -urN linux-2.5.8-pre1/drivers/net/daynaport.c linux-2.5.8-pre2/drivers/net/daynaport.c
--- linux-2.5.8-pre1/drivers/net/daynaport.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/daynaport.c	Fri Apr  5 16:59:29 2002
@@ -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 -urN linux-2.5.8-pre1/drivers/net/e100/e100.h linux-2.5.8-pre2/drivers/net/e100/e100.h
--- linux-2.5.8-pre1/drivers/net/e100/e100.h	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/e100/e100.h	Fri Apr  5 16:59:29 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
diff -urN linux-2.5.8-pre1/drivers/net/e100/e100_main.c linux-2.5.8-pre2/drivers/net/e100/e100_main.c
--- linux-2.5.8-pre1/drivers/net/e100/e100_main.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/e100/e100_main.c	Fri Apr  5 16:59:29 2002
@@ -182,7 +182,7 @@
 /* Global Data structures and variables */
 char e100_copyright[] __devinitdata = "Copyright (c) 2002 Intel Corporation";
 
-#define E100_VERSION  "2.0.25-pre1"
+#define E100_VERSION  "2.0.27-pre3"
 
 #define E100_FULL_DRIVER_NAME 	"Intel(R) PRO/100 Fast Ethernet Adapter - Loadable driver, ver "
 
@@ -427,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 */
 }
 
 /**
@@ -455,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();
@@ -481,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;
 	}
@@ -521,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;
@@ -2372,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);
@@ -2537,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) {
diff -urN linux-2.5.8-pre1/drivers/net/eepro100.c linux-2.5.8-pre2/drivers/net/eepro100.c
--- linux-2.5.8-pre1/drivers/net/eepro100.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/eepro100.c	Fri Apr  5 16:59:29 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;
 	}
 
@@ -2285,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 -urN linux-2.5.8-pre1/drivers/net/gt96100eth.c linux-2.5.8-pre2/drivers/net/gt96100eth.c
--- linux-2.5.8-pre1/drivers/net/gt96100eth.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/drivers/net/gt96100eth.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/gt96100eth.h linux-2.5.8-pre2/drivers/net/gt96100eth.h
--- linux-2.5.8-pre1/drivers/net/gt96100eth.h	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/drivers/net/gt96100eth.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/hamradio/6pack.c linux-2.5.8-pre2/drivers/net/hamradio/6pack.c
--- linux-2.5.8-pre1/drivers/net/hamradio/6pack.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/hamradio/6pack.c	Fri Apr  5 16:59:29 2002
@@ -1063,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 -urN linux-2.5.8-pre1/drivers/net/hamradio/baycom_epp.c linux-2.5.8-pre2/drivers/net/hamradio/baycom_epp.c
--- linux-2.5.8-pre1/drivers/net/hamradio/baycom_epp.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/hamradio/baycom_epp.c	Fri Apr  5 16:59:29 2002
@@ -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 -urN linux-2.5.8-pre1/drivers/net/hamradio/baycom_par.c linux-2.5.8-pre2/drivers/net/hamradio/baycom_par.c
--- linux-2.5.8-pre1/drivers/net/hamradio/baycom_par.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/drivers/net/hamradio/baycom_par.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/hamradio/baycom_ser_fdx.c linux-2.5.8-pre2/drivers/net/hamradio/baycom_ser_fdx.c
--- linux-2.5.8-pre1/drivers/net/hamradio/baycom_ser_fdx.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/hamradio/baycom_ser_fdx.c	Fri Apr  5 16:59:29 2002
@@ -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 -urN linux-2.5.8-pre1/drivers/net/hamradio/baycom_ser_hdx.c linux-2.5.8-pre2/drivers/net/hamradio/baycom_ser_hdx.c
--- linux-2.5.8-pre1/drivers/net/hamradio/baycom_ser_hdx.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/drivers/net/hamradio/baycom_ser_hdx.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/hamradio/bpqether.c linux-2.5.8-pre2/drivers/net/hamradio/bpqether.c
--- linux-2.5.8-pre1/drivers/net/hamradio/bpqether.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/drivers/net/hamradio/bpqether.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/hamradio/dmascc.c linux-2.5.8-pre2/drivers/net/hamradio/dmascc.c
--- linux-2.5.8-pre1/drivers/net/hamradio/dmascc.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/hamradio/dmascc.c	Fri Apr  5 16:59:29 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) {
diff -urN linux-2.5.8-pre1/drivers/net/hamradio/hdlcdrv.c linux-2.5.8-pre2/drivers/net/hamradio/hdlcdrv.c
--- linux-2.5.8-pre1/drivers/net/hamradio/hdlcdrv.c	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/drivers/net/hamradio/hdlcdrv.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/hamradio/mkiss.c linux-2.5.8-pre2/drivers/net/hamradio/mkiss.c
--- linux-2.5.8-pre1/drivers/net/hamradio/mkiss.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/hamradio/mkiss.c	Fri Apr  5 16:59:29 2002
@@ -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 -urN linux-2.5.8-pre1/drivers/net/hamradio/scc.c linux-2.5.8-pre2/drivers/net/hamradio/scc.c
--- linux-2.5.8-pre1/drivers/net/hamradio/scc.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/hamradio/scc.c	Fri Apr  5 16:59:29 2002
@@ -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 -urN linux-2.5.8-pre1/drivers/net/hamradio/yam.c linux-2.5.8-pre2/drivers/net/hamradio/yam.c
--- linux-2.5.8-pre1/drivers/net/hamradio/yam.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/hamradio/yam.c	Fri Apr  5 16:59:29 2002
@@ -1179,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 -urN linux-2.5.8-pre1/drivers/net/hydra.c linux-2.5.8-pre2/drivers/net/hydra.c
--- linux-2.5.8-pre1/drivers/net/hydra.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/drivers/net/hydra.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/ioc3-eth.c linux-2.5.8-pre2/drivers/net/ioc3-eth.c
--- linux-2.5.8-pre1/drivers/net/ioc3-eth.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/drivers/net/ioc3-eth.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/irda/irda-usb.c linux-2.5.8-pre2/drivers/net/irda/irda-usb.c
--- linux-2.5.8-pre1/drivers/net/irda/irda-usb.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/drivers/net/irda/irda-usb.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/irda/irtty.c linux-2.5.8-pre2/drivers/net/irda/irtty.c
--- linux-2.5.8-pre1/drivers/net/irda/irtty.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/drivers/net/irda/irtty.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/irda/nsc-ircc.c linux-2.5.8-pre2/drivers/net/irda/nsc-ircc.c
--- linux-2.5.8-pre1/drivers/net/irda/nsc-ircc.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/drivers/net/irda/nsc-ircc.c	Fri Apr  5 16:59:29 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 }
 };
 
@@ -698,6 +702,9 @@
 	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)) {
 		ERROR("%s, Wrong chip version %02x\n", driver_name, version);
diff -urN linux-2.5.8-pre1/drivers/net/irda/sa1100_ir.c linux-2.5.8-pre2/drivers/net/irda/sa1100_ir.c
--- linux-2.5.8-pre1/drivers/net/irda/sa1100_ir.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/net/irda/sa1100_ir.c	Fri Apr  5 16:59:29 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 {
@@ -621,7 +622,7 @@
 	/*
 	 * Stop RX DMA
 	 */
-	sa1100_dma_stop(si->rxdma);
+	sa1100_stop_dma(si->rxdma);
 
 	/*
 	 * Framing error - we throw away the packet completely.
@@ -673,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;
@@ -715,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);
 	}
 
@@ -728,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;
@@ -759,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);
@@ -787,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
@@ -869,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;
 
@@ -897,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
 	 */
@@ -1011,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;
 
@@ -1149,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);
@@ -1161,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 -urN linux-2.5.8-pre1/drivers/net/irda/w83977af_ir.c linux-2.5.8-pre2/drivers/net/irda/w83977af_ir.c
--- linux-2.5.8-pre1/drivers/net/irda/w83977af_ir.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/drivers/net/irda/w83977af_ir.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/pcmcia/pcnet_cs.c linux-2.5.8-pre2/drivers/net/pcmcia/pcnet_cs.c
--- linux-2.5.8-pre1/drivers/net/pcmcia/pcnet_cs.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/net/pcmcia/pcnet_cs.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/rrunner.c linux-2.5.8-pre2/drivers/net/rrunner.c
--- linux-2.5.8-pre1/drivers/net/rrunner.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/drivers/net/rrunner.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/sgiseeq.c linux-2.5.8-pre2/drivers/net/sgiseeq.c
--- linux-2.5.8-pre1/drivers/net/sgiseeq.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/drivers/net/sgiseeq.c	Fri Apr  5 16:59:29 2002
@@ -720,3 +720,5 @@
 			    (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)),
 			    &hpc3c0->ethregs, SGI_ENET_IRQ);
 }
+
+MODULE_LICENSE("GPL");
diff -urN linux-2.5.8-pre1/drivers/net/sonic.c linux-2.5.8-pre2/drivers/net/sonic.c
--- linux-2.5.8-pre1/drivers/net/sonic.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/drivers/net/sonic.c	Fri Apr  5 16:59:29 2002
@@ -620,3 +620,5 @@
 
 	return 0;
 }
+
+MODULE_LICENSE("GPL");
diff -urN linux-2.5.8-pre1/drivers/net/tokenring/olympic.c linux-2.5.8-pre2/drivers/net/tokenring/olympic.c
--- linux-2.5.8-pre1/drivers/net/tokenring/olympic.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/drivers/net/tokenring/olympic.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/net/wireless/wavelan_cs.c linux-2.5.8-pre2/drivers/net/wireless/wavelan_cs.c
--- linux-2.5.8-pre1/drivers/net/wireless/wavelan_cs.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/drivers/net/wireless/wavelan_cs.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/scsi/aic7xxx/aic7xxx_linux.c linux-2.5.8-pre2/drivers/scsi/aic7xxx/aic7xxx_linux.c
--- linux-2.5.8-pre1/drivers/scsi/aic7xxx/aic7xxx_linux.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/scsi/aic7xxx/aic7xxx_linux.c	Fri Apr  5 16:59:29 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);
 
diff -urN linux-2.5.8-pre1/drivers/scsi/qla1280.c linux-2.5.8-pre2/drivers/scsi/qla1280.c
--- linux-2.5.8-pre1/drivers/scsi/qla1280.c	Mon Mar 18 12:37:19 2002
+++ linux-2.5.8-pre2/drivers/scsi/qla1280.c	Fri Apr  5 16:59:29 2002
@@ -182,11 +182,7 @@
     -   Initial Beta Release.  
 *****************************************************************************/
 
-#error Please convert me to Documentation/DMA-mapping.txt
-
-#ifdef MODULE
 #include <linux/module.h>
-#endif
 
 #define QLA1280_VERSION      " 3.00-Beta"
 
@@ -3983,10 +3979,11 @@
                     /* 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));
+                    	unsigned long long address = page_to_phys(sg->page) + sg->offset;
+                        DEBUG(sprintf(debug_buff,"SG Segment ap=0x%ull, len=0x%x\n\r",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++ = cpu_to_le32(address);
+                        *dword_ptr++ = cpu_to_le32(address >> 32);
                         *dword_ptr++ = sg->length;
                         sg++;
                     }
@@ -4038,8 +4035,9 @@
                         /* 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));
+                            unsigned long long address = page_to_phys(sg->page) + sg->offset;
+                            *dword_ptr++ = cpu_to_le32(address);
+                            *dword_ptr++ = cpu_to_le32(address >> 32);
                             *dword_ptr++ = sg->length;
                             sg++;
                         }
@@ -4325,9 +4323,10 @@
                     /* 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));
+                    	unsigned long long address = page_to_phys(sg->page) + sg->offset;
+                        *dword_ptr++ = (uint32_t) cpu_to_le32(address);
                         *dword_ptr++ = sg->length;
-                        DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length));
+                        DEBUG(sprintf(debug_buff,"SG Segment ap=0x%ull, len=0x%x\n\r",address,sg->length));
                         DEBUG(qla1280_print(debug_buff));
                         sg++;
                     }
@@ -4368,7 +4367,8 @@
                         /* 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));
+                            unsigned long long address = page_to_phys(sg->page) + sg->offset;
+                            *dword_ptr++ = (u_int) cpu_to_le32(address);
                             *dword_ptr++ = sg->length;
                             sg++;
                         }
diff -urN linux-2.5.8-pre1/drivers/usb/CDCEther.c linux-2.5.8-pre2/drivers/usb/CDCEther.c
--- linux-2.5.8-pre1/drivers/usb/CDCEther.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/drivers/usb/CDCEther.c	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 -urN linux-2.5.8-pre1/drivers/usb/CDCEther.h linux-2.5.8-pre2/drivers/usb/CDCEther.h
--- linux-2.5.8-pre1/drivers/usb/CDCEther.h	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/drivers/usb/CDCEther.h	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 -urN linux-2.5.8-pre1/drivers/usb/Config.help linux-2.5.8-pre2/drivers/usb/Config.help
--- linux-2.5.8-pre1/drivers/usb/Config.help	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/Config.help	Fri Apr  5 16:59:29 2002
@@ -37,60 +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
@@ -445,32 +391,6 @@
   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
@@ -576,19 +496,6 @@
   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>
diff -urN linux-2.5.8-pre1/drivers/usb/Config.in linux-2.5.8-pre2/drivers/usb/Config.in
--- linux-2.5.8-pre1/drivers/usb/Config.in	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/Config.in	Fri Apr  5 16:59:29 2002
@@ -6,104 +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)'
-   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
+   source drivers/usb/storage/Config.in
 
-   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
+   source drivers/usb/input/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/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 RTL8150 based ethernet device support (EXPERIMENTAL)' CONFIG_USB_RTL8150 $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 '  USB Auerswald ISDN support (EXPERIMENTAL)' CONFIG_USB_AUERSWALD $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 -urN linux-2.5.8-pre1/drivers/usb/Makefile linux-2.5.8-pre2/drivers/usb/Makefile
--- linux-2.5.8-pre1/drivers/usb/Makefile	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/Makefile	Fri Apr  5 16:59:29 2002
@@ -2,108 +2,90 @@
 # Makefile for the kernel USB device drivers.
 #
 
-# 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.
-
-usbcore-objs		:= usb.o usb-debug.o hub.o hcd.o
-hid-objs		:= hid-core.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
-
-ifeq ($(CONFIG_USB_HIDDEV),y)
-	hid-objs	+= hiddev.o
-endif
+# Object files in subdirectories
+mod-subdirs	:= core host class media net serial storage image misc input
 
-ifeq ($(CONFIG_USB_HIDINPUT),y)
-	hid-objs	+= hid-input.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_RTL8150)	+= rtl8150.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
-obj-$(CONFIG_USB_TIGL)		+= tiglusb.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
diff -urN linux-2.5.8-pre1/drivers/usb/Makefile.lib linux-2.5.8-pre2/drivers/usb/Makefile.lib
--- linux-2.5.8-pre1/drivers/usb/Makefile.lib	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/drivers/usb/Makefile.lib	Wed Dec 31 16:00:00 1969
@@ -1 +0,0 @@
-obj-$(CONFIG_USB_CATC)		+= crc32.o
diff -urN linux-2.5.8-pre1/drivers/usb/README linux-2.5.8-pre2/drivers/usb/README
--- linux-2.5.8-pre1/drivers/usb/README	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/README	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/acm.c linux-2.5.8-pre2/drivers/usb/acm.c
--- linux-2.5.8-pre1/drivers/usb/acm.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/drivers/usb/acm.c	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 -urN linux-2.5.8-pre1/drivers/usb/audio.c linux-2.5.8-pre2/drivers/usb/audio.c
--- linux-2.5.8-pre1/drivers/usb/audio.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/audio.c	Wed Dec 31 16:00:00 1969
@@ -1,3876 +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;
-	}
-	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 -urN linux-2.5.8-pre1/drivers/usb/audio.h linux-2.5.8-pre2/drivers/usb/audio.h
--- linux-2.5.8-pre1/drivers/usb/audio.h	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/drivers/usb/audio.h	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 -urN linux-2.5.8-pre1/drivers/usb/auerswald.c linux-2.5.8-pre2/drivers/usb/auerswald.c
--- linux-2.5.8-pre1/drivers/usb/auerswald.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/drivers/usb/auerswald.c	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 -urN linux-2.5.8-pre1/drivers/usb/bluetooth.c linux-2.5.8-pre2/drivers/usb/bluetooth.c
--- linux-2.5.8-pre1/drivers/usb/bluetooth.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/drivers/usb/bluetooth.c	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 -urN linux-2.5.8-pre1/drivers/usb/catc.c linux-2.5.8-pre2/drivers/usb/catc.c
--- linux-2.5.8-pre1/drivers/usb/catc.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/catc.c	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;
-	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 -urN linux-2.5.8-pre1/drivers/usb/class/Config.in linux-2.5.8-pre2/drivers/usb/class/Config.in
--- linux-2.5.8-pre1/drivers/usb/class/Config.in	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/class/Config.in	Fri Apr  5 16:59:29 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 support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL
+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" = "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 -urN linux-2.5.8-pre1/drivers/usb/class/Makefile linux-2.5.8-pre2/drivers/usb/class/Makefile
--- linux-2.5.8-pre1/drivers/usb/class/Makefile	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/class/Makefile	Fri Apr  5 16:59:29 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)	+= bluetooth.o
+obj-$(CONFIG_USB_PRINTER)	+= printer.o
+
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.5.8-pre1/drivers/usb/class/Makefile.lib linux-2.5.8-pre2/drivers/usb/class/Makefile.lib
--- linux-2.5.8-pre1/drivers/usb/class/Makefile.lib	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/class/Makefile.lib	Fri Apr  5 16:59:29 2002
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_CATC)		+= crc32.o
diff -urN linux-2.5.8-pre1/drivers/usb/class/audio.c linux-2.5.8-pre2/drivers/usb/class/audio.c
--- linux-2.5.8-pre1/drivers/usb/class/audio.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/class/audio.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/class/audio.h linux-2.5.8-pre2/drivers/usb/class/audio.h
--- linux-2.5.8-pre1/drivers/usb/class/audio.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/class/audio.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/class/bluetooth.c linux-2.5.8-pre2/drivers/usb/class/bluetooth.c
--- linux-2.5.8-pre1/drivers/usb/class/bluetooth.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/class/bluetooth.c	Fri Apr  5 16:59:29 2002
@@ -0,0 +1,1364 @@
+/*
+ * 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 -urN linux-2.5.8-pre1/drivers/usb/class/cdc-acm.c linux-2.5.8-pre2/drivers/usb/class/cdc-acm.c
--- linux-2.5.8-pre1/drivers/usb/class/cdc-acm.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/class/cdc-acm.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/class/printer.c linux-2.5.8-pre2/drivers/usb/class/printer.c
--- linux-2.5.8-pre1/drivers/usb/class/printer.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/class/printer.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/core/Config.in linux-2.5.8-pre2/drivers/usb/core/Config.in
--- linux-2.5.8-pre1/drivers/usb/core/Config.in	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/core/Config.in	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/core/Makefile linux-2.5.8-pre2/drivers/usb/core/Makefile
--- linux-2.5.8-pre1/drivers/usb/core/Makefile	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/core/Makefile	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/core/devices.c linux-2.5.8-pre2/drivers/usb/core/devices.c
--- linux-2.5.8-pre1/drivers/usb/core/devices.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/core/devices.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/core/devio.c linux-2.5.8-pre2/drivers/usb/core/devio.c
--- linux-2.5.8-pre1/drivers/usb/core/devio.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/core/devio.c	Fri Apr  5 16:59:29 2002
@@ -0,0 +1,1241 @@
+/*****************************************************************************/
+
+/*
+ *      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 -urN linux-2.5.8-pre1/drivers/usb/core/drivers.c linux-2.5.8-pre2/drivers/usb/core/drivers.c
--- linux-2.5.8-pre1/drivers/usb/core/drivers.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/core/drivers.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/core/hcd.c linux-2.5.8-pre2/drivers/usb/core/hcd.c
--- linux-2.5.8-pre1/drivers/usb/core/hcd.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/core/hcd.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/core/hcd.h linux-2.5.8-pre2/drivers/usb/core/hcd.h
--- linux-2.5.8-pre1/drivers/usb/core/hcd.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/core/hcd.h	Fri Apr  5 16:59:29 2002
@@ -0,0 +1,290 @@
+/*
+ * 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 -urN linux-2.5.8-pre1/drivers/usb/core/hub.c linux-2.5.8-pre2/drivers/usb/core/hub.c
--- linux-2.5.8-pre1/drivers/usb/core/hub.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/core/hub.c	Fri Apr  5 16:59:29 2002
@@ -0,0 +1,1168 @@
+/*
+ * 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 "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 -urN linux-2.5.8-pre1/drivers/usb/core/hub.h linux-2.5.8-pre2/drivers/usb/core/hub.h
--- linux-2.5.8-pre1/drivers/usb/core/hub.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/core/hub.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/core/inode.c linux-2.5.8-pre2/drivers/usb/core/inode.c
--- linux-2.5.8-pre1/drivers/usb/core/inode.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/core/inode.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/core/usb-debug.c linux-2.5.8-pre2/drivers/usb/core/usb-debug.c
--- linux-2.5.8-pre1/drivers/usb/core/usb-debug.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/core/usb-debug.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/core/usb.c linux-2.5.8-pre2/drivers/usb/core/usb.c
--- linux-2.5.8-pre1/drivers/usb/core/usb.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/core/usb.c	Fri Apr  5 16:59:29 2002
@@ -0,0 +1,2687 @@
+/*
+ * 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!!
+// FIXME the public call should BUG() whenever count goes to zero,
+// the usbcore-internal one should do so _unless_ it does so...
+void usb_free_dev(struct usb_device *dev)
+{
+	if (atomic_dec_and_test(&dev->refcnt)) {
+		/* Normally only goes to zero in usb_disconnect(), from
+		 * khubd or from roothub shutdown (rmmod/apmd/... thread).
+		 * Abnormally, roothub init errors can happen, so HCDs
+		 * call this directly.
+		 *
+		 * Otherwise this is a nasty device driver bug, often in
+		 * disconnect processing.
+		 */
+		if (in_interrupt ())
+			BUG ();
+
+		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 -urN linux-2.5.8-pre1/drivers/usb/dabfirmware.h linux-2.5.8-pre2/drivers/usb/dabfirmware.h
--- linux-2.5.8-pre1/drivers/usb/dabfirmware.h	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/drivers/usb/dabfirmware.h	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 -urN linux-2.5.8-pre1/drivers/usb/dabusb.c linux-2.5.8-pre2/drivers/usb/dabusb.c
--- linux-2.5.8-pre1/drivers/usb/dabusb.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/drivers/usb/dabusb.c	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 -urN linux-2.5.8-pre1/drivers/usb/dabusb.h linux-2.5.8-pre2/drivers/usb/dabusb.h
--- linux-2.5.8-pre1/drivers/usb/dabusb.h	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/drivers/usb/dabusb.h	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 -urN linux-2.5.8-pre1/drivers/usb/dc2xx.c linux-2.5.8-pre2/drivers/usb/dc2xx.c
--- linux-2.5.8-pre1/drivers/usb/dc2xx.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/drivers/usb/dc2xx.c	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 -urN linux-2.5.8-pre1/drivers/usb/devices.c linux-2.5.8-pre2/drivers/usb/devices.c
--- linux-2.5.8-pre1/drivers/usb/devices.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/devices.c	Wed Dec 31 16:00:00 1969
@@ -1,662 +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=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 -urN linux-2.5.8-pre1/drivers/usb/devio.c linux-2.5.8-pre2/drivers/usb/devio.c
--- linux-2.5.8-pre1/drivers/usb/devio.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/drivers/usb/devio.c	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 -urN linux-2.5.8-pre1/drivers/usb/drivers.c linux-2.5.8-pre2/drivers/usb/drivers.c
--- linux-2.5.8-pre1/drivers/usb/drivers.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/drivers/usb/drivers.c	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 -urN linux-2.5.8-pre1/drivers/usb/dsbr100.c linux-2.5.8-pre2/drivers/usb/dsbr100.c
--- linux-2.5.8-pre1/drivers/usb/dsbr100.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/drivers/usb/dsbr100.c	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 -urN linux-2.5.8-pre1/drivers/usb/emi26.c linux-2.5.8-pre2/drivers/usb/emi26.c
--- linux-2.5.8-pre1/drivers/usb/emi26.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/usb/emi26.c	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 -urN linux-2.5.8-pre1/drivers/usb/emi26_fw.h linux-2.5.8-pre2/drivers/usb/emi26_fw.h
--- linux-2.5.8-pre1/drivers/usb/emi26_fw.h	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/usb/emi26_fw.h	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 -urN linux-2.5.8-pre1/drivers/usb/hcd/Config.help linux-2.5.8-pre2/drivers/usb/hcd/Config.help
--- linux-2.5.8-pre1/drivers/usb/hcd/Config.help	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/Config.help	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 -urN linux-2.5.8-pre1/drivers/usb/hcd/Config.in linux-2.5.8-pre2/drivers/usb/hcd/Config.in
--- linux-2.5.8-pre1/drivers/usb/hcd/Config.in	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/Config.in	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 -urN linux-2.5.8-pre1/drivers/usb/hcd/Makefile linux-2.5.8-pre2/drivers/usb/hcd/Makefile
--- linux-2.5.8-pre1/drivers/usb/hcd/Makefile	Mon Mar 18 12:37:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/Makefile	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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ehci-dbg.c linux-2.5.8-pre2/drivers/usb/hcd/ehci-dbg.c
--- linux-2.5.8-pre1/drivers/usb/hcd/ehci-dbg.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ehci-dbg.c	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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ehci-hcd.c linux-2.5.8-pre2/drivers/usb/hcd/ehci-hcd.c
--- linux-2.5.8-pre1/drivers/usb/hcd/ehci-hcd.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ehci-hcd.c	Wed Dec 31 16:00:00 1969
@@ -1,762 +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
-
-/* 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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ehci-hub.c linux-2.5.8-pre2/drivers/usb/hcd/ehci-hub.c
--- linux-2.5.8-pre1/drivers/usb/hcd/ehci-hub.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ehci-hub.c	Wed Dec 31 16:00:00 1969
@@ -1,339 +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 {
-				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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ehci-mem.c linux-2.5.8-pre2/drivers/usb/hcd/ehci-mem.c
--- linux-2.5.8-pre1/drivers/usb/hcd/ehci-mem.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ehci-mem.c	Wed Dec 31 16:00:00 1969
@@ -1,236 +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);
-	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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ehci-q.c linux-2.5.8-pre2/drivers/usb/hcd/ehci-q.c
--- linux-2.5.8-pre1/drivers/usb/hcd/ehci-q.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ehci-q.c	Wed Dec 31 16:00:00 1969
@@ -1,967 +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 */
-		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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ehci-sched.c linux-2.5.8-pre2/drivers/usb/hcd/ehci-sched.c
--- linux-2.5.8-pre1/drivers/usb/hcd/ehci-sched.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ehci-sched.c	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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ehci.h linux-2.5.8-pre2/drivers/usb/hcd/ehci.h
--- linux-2.5.8-pre1/drivers/usb/hcd/ehci.h	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ehci.h	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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ohci-dbg.c linux-2.5.8-pre2/drivers/usb/hcd/ohci-dbg.c
--- linux-2.5.8-pre1/drivers/usb/hcd/ohci-dbg.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ohci-dbg.c	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.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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ohci-hcd.c linux-2.5.8-pre2/drivers/usb/hcd/ohci-hcd.c
--- linux-2.5.8-pre1/drivers/usb/hcd/ohci-hcd.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ohci-hcd.c	Wed Dec 31 16:00:00 1969
@@ -1,961 +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.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 "../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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ohci-hub.c linux-2.5.8-pre2/drivers/usb/hcd/ohci-hub.c
--- linux-2.5.8-pre1/drivers/usb/hcd/ohci-hub.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ohci-hub.c	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.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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ohci-mem.c linux-2.5.8-pre2/drivers/usb/hcd/ohci-mem.c
--- linux-2.5.8-pre1/drivers/usb/hcd/ohci-mem.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ohci-mem.c	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-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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ohci-q.c linux-2.5.8-pre2/drivers/usb/hcd/ohci-q.c
--- linux-2.5.8-pre1/drivers/usb/hcd/ohci-q.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ohci-q.c	Wed Dec 31 16:00:00 1969
@@ -1,979 +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.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 -urN linux-2.5.8-pre1/drivers/usb/hcd/ohci.h linux-2.5.8-pre2/drivers/usb/hcd/ohci.h
--- linux-2.5.8-pre1/drivers/usb/hcd/ohci.h	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd/ohci.h	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.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 -urN linux-2.5.8-pre1/drivers/usb/hcd.c linux-2.5.8-pre2/drivers/usb/hcd.c
--- linux-2.5.8-pre1/drivers/usb/hcd.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd.c	Wed Dec 31 16:00:00 1969
@@ -1,1813 +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/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 -urN linux-2.5.8-pre1/drivers/usb/hcd.h linux-2.5.8-pre2/drivers/usb/hcd.h
--- linux-2.5.8-pre1/drivers/usb/hcd.h	Mon Mar 18 12:37:11 2002
+++ linux-2.5.8-pre2/drivers/usb/hcd.h	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 -urN linux-2.5.8-pre1/drivers/usb/hid-core.c linux-2.5.8-pre2/drivers/usb/hid-core.c
--- linux-2.5.8-pre1/drivers/usb/hid-core.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hid-core.c	Wed Dec 31 16:00:00 1969
@@ -1,1530 +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"
-#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 -urN linux-2.5.8-pre1/drivers/usb/hid-debug.h linux-2.5.8-pre2/drivers/usb/hid-debug.h
--- linux-2.5.8-pre1/drivers/usb/hid-debug.h	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/drivers/usb/hid-debug.h	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 -urN linux-2.5.8-pre1/drivers/usb/hid-input.c linux-2.5.8-pre2/drivers/usb/hid-input.c
--- linux-2.5.8-pre1/drivers/usb/hid-input.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/drivers/usb/hid-input.c	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 -urN linux-2.5.8-pre1/drivers/usb/hid.h linux-2.5.8-pre2/drivers/usb/hid.h
--- linux-2.5.8-pre1/drivers/usb/hid.h	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hid.h	Wed Dec 31 16:00:00 1969
@@ -1,421 +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));
-
-#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 -urN linux-2.5.8-pre1/drivers/usb/hiddev.c linux-2.5.8-pre2/drivers/usb/hiddev.c
--- linux-2.5.8-pre1/drivers/usb/hiddev.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hiddev.c	Wed Dec 31 16:00:00 1969
@@ -1,699 +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;
-}
-
-/*
- * "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 -urN linux-2.5.8-pre1/drivers/usb/host/Config.help linux-2.5.8-pre2/drivers/usb/host/Config.help
--- linux-2.5.8-pre1/drivers/usb/host/Config.help	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/Config.help	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/Config.in linux-2.5.8-pre2/drivers/usb/host/Config.in
--- linux-2.5.8-pre1/drivers/usb/host/Config.in	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/Config.in	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/Makefile linux-2.5.8-pre2/drivers/usb/host/Makefile
--- linux-2.5.8-pre1/drivers/usb/host/Makefile	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/Makefile	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ehci-dbg.c linux-2.5.8-pre2/drivers/usb/host/ehci-dbg.c
--- linux-2.5.8-pre1/drivers/usb/host/ehci-dbg.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ehci-dbg.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ehci-hcd.c linux-2.5.8-pre2/drivers/usb/host/ehci-hcd.c
--- linux-2.5.8-pre1/drivers/usb/host/ehci-hcd.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ehci-hcd.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ehci-hub.c linux-2.5.8-pre2/drivers/usb/host/ehci-hub.c
--- linux-2.5.8-pre1/drivers/usb/host/ehci-hub.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ehci-hub.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ehci-mem.c linux-2.5.8-pre2/drivers/usb/host/ehci-mem.c
--- linux-2.5.8-pre1/drivers/usb/host/ehci-mem.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ehci-mem.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ehci-q.c linux-2.5.8-pre2/drivers/usb/host/ehci-q.c
--- linux-2.5.8-pre1/drivers/usb/host/ehci-q.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ehci-q.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ehci-sched.c linux-2.5.8-pre2/drivers/usb/host/ehci-sched.c
--- linux-2.5.8-pre1/drivers/usb/host/ehci-sched.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ehci-sched.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ehci.h linux-2.5.8-pre2/drivers/usb/host/ehci.h
--- linux-2.5.8-pre1/drivers/usb/host/ehci.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ehci.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ohci-dbg.c linux-2.5.8-pre2/drivers/usb/host/ohci-dbg.c
--- linux-2.5.8-pre1/drivers/usb/host/ohci-dbg.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ohci-dbg.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ohci-hcd.c linux-2.5.8-pre2/drivers/usb/host/ohci-hcd.c
--- linux-2.5.8-pre1/drivers/usb/host/ohci-hcd.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ohci-hcd.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ohci-hub.c linux-2.5.8-pre2/drivers/usb/host/ohci-hub.c
--- linux-2.5.8-pre1/drivers/usb/host/ohci-hub.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ohci-hub.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ohci-mem.c linux-2.5.8-pre2/drivers/usb/host/ohci-mem.c
--- linux-2.5.8-pre1/drivers/usb/host/ohci-mem.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ohci-mem.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ohci-q.c linux-2.5.8-pre2/drivers/usb/host/ohci-q.c
--- linux-2.5.8-pre1/drivers/usb/host/ohci-q.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ohci-q.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/ohci.h linux-2.5.8-pre2/drivers/usb/host/ohci.h
--- linux-2.5.8-pre1/drivers/usb/host/ohci.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/ohci.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/uhci-debug.h linux-2.5.8-pre2/drivers/usb/host/uhci-debug.h
--- linux-2.5.8-pre1/drivers/usb/host/uhci-debug.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/uhci-debug.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/uhci.c linux-2.5.8-pre2/drivers/usb/host/uhci.c
--- linux-2.5.8-pre1/drivers/usb/host/uhci.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/uhci.c	Fri Apr  5 16:59:29 2002
@@ -0,0 +1,3174 @@
+/*
+ * 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->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);
+		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);
+			spin_unlock_irqrestore(&urb->lock, flags);
+			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, 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;
+
+			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);
+
+	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->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 -urN linux-2.5.8-pre1/drivers/usb/host/uhci.h linux-2.5.8-pre2/drivers/usb/host/uhci.h
--- linux-2.5.8-pre1/drivers/usb/host/uhci.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/uhci.h	Fri Apr  5 16:59:29 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;
+
+	/* 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 -urN linux-2.5.8-pre1/drivers/usb/host/usb-ohci.c linux-2.5.8-pre2/drivers/usb/host/usb-ohci.c
--- linux-2.5.8-pre1/drivers/usb/host/usb-ohci.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/usb-ohci.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/usb-ohci.h linux-2.5.8-pre2/drivers/usb/host/usb-ohci.h
--- linux-2.5.8-pre1/drivers/usb/host/usb-ohci.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/usb-ohci.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/usb-uhci-debug.h linux-2.5.8-pre2/drivers/usb/host/usb-uhci-debug.h
--- linux-2.5.8-pre1/drivers/usb/host/usb-uhci-debug.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/usb-uhci-debug.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/usb-uhci.c linux-2.5.8-pre2/drivers/usb/host/usb-uhci.c
--- linux-2.5.8-pre1/drivers/usb/host/usb-uhci.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/usb-uhci.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/host/usb-uhci.h linux-2.5.8-pre2/drivers/usb/host/usb-uhci.h
--- linux-2.5.8-pre1/drivers/usb/host/usb-uhci.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/host/usb-uhci.h	Fri Apr  5 16:59:29 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())
+	{
+		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 -urN linux-2.5.8-pre1/drivers/usb/hpusbscsi.c linux-2.5.8-pre2/drivers/usb/hpusbscsi.c
--- linux-2.5.8-pre1/drivers/usb/hpusbscsi.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hpusbscsi.c	Wed Dec 31 16:00:00 1969
@@ -1,598 +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;
-
-	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 -urN linux-2.5.8-pre1/drivers/usb/hpusbscsi.h linux-2.5.8-pre2/drivers/usb/hpusbscsi.h
--- linux-2.5.8-pre1/drivers/usb/hpusbscsi.h	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hpusbscsi.h	Wed Dec 31 16:00:00 1969
@@ -1,96 +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 */
-
-/* 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 -urN linux-2.5.8-pre1/drivers/usb/hub.c linux-2.5.8-pre2/drivers/usb/hub.c
--- linux-2.5.8-pre1/drivers/usb/hub.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/hub.c	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 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 -urN linux-2.5.8-pre1/drivers/usb/hub.h linux-2.5.8-pre2/drivers/usb/hub.h
--- linux-2.5.8-pre1/drivers/usb/hub.h	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/drivers/usb/hub.h	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 -urN linux-2.5.8-pre1/drivers/usb/ibmcam.c linux-2.5.8-pre2/drivers/usb/ibmcam.c
--- linux-2.5.8-pre1/drivers/usb/ibmcam.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/drivers/usb/ibmcam.c	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 -urN linux-2.5.8-pre1/drivers/usb/image/Config.in linux-2.5.8-pre2/drivers/usb/image/Config.in
--- linux-2.5.8-pre1/drivers/usb/image/Config.in	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/image/Config.in	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/image/Makefile linux-2.5.8-pre2/drivers/usb/image/Makefile
--- linux-2.5.8-pre1/drivers/usb/image/Makefile	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/image/Makefile	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/image/dc2xx.c linux-2.5.8-pre2/drivers/usb/image/dc2xx.c
--- linux-2.5.8-pre1/drivers/usb/image/dc2xx.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/image/dc2xx.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/image/hpusbscsi.c linux-2.5.8-pre2/drivers/usb/image/hpusbscsi.c
--- linux-2.5.8-pre1/drivers/usb/image/hpusbscsi.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/image/hpusbscsi.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/image/hpusbscsi.h linux-2.5.8-pre2/drivers/usb/image/hpusbscsi.h
--- linux-2.5.8-pre1/drivers/usb/image/hpusbscsi.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/image/hpusbscsi.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/image/mdc800.c linux-2.5.8-pre2/drivers/usb/image/mdc800.c
--- linux-2.5.8-pre1/drivers/usb/image/mdc800.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/image/mdc800.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/image/microtek.c linux-2.5.8-pre2/drivers/usb/image/microtek.c
--- linux-2.5.8-pre1/drivers/usb/image/microtek.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/image/microtek.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/image/microtek.h linux-2.5.8-pre2/drivers/usb/image/microtek.h
--- linux-2.5.8-pre1/drivers/usb/image/microtek.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/image/microtek.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/image/scanner.c linux-2.5.8-pre2/drivers/usb/image/scanner.c
--- linux-2.5.8-pre1/drivers/usb/image/scanner.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/image/scanner.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/image/scanner.h linux-2.5.8-pre2/drivers/usb/image/scanner.h
--- linux-2.5.8-pre1/drivers/usb/image/scanner.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/image/scanner.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/inode.c linux-2.5.8-pre2/drivers/usb/inode.c
--- linux-2.5.8-pre1/drivers/usb/inode.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/inode.c	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;
-
-	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 -urN linux-2.5.8-pre1/drivers/usb/input/Config.in linux-2.5.8-pre2/drivers/usb/input/Config.in
--- linux-2.5.8-pre1/drivers/usb/input/Config.in	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/input/Config.in	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/input/Makefile linux-2.5.8-pre2/drivers/usb/input/Makefile
--- linux-2.5.8-pre1/drivers/usb/input/Makefile	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/input/Makefile	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/input/hid-core.c linux-2.5.8-pre2/drivers/usb/input/hid-core.c
--- linux-2.5.8-pre1/drivers/usb/input/hid-core.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/input/hid-core.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/input/hid-debug.h linux-2.5.8-pre2/drivers/usb/input/hid-debug.h
--- linux-2.5.8-pre1/drivers/usb/input/hid-debug.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/input/hid-debug.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/input/hid-input.c linux-2.5.8-pre2/drivers/usb/input/hid-input.c
--- linux-2.5.8-pre1/drivers/usb/input/hid-input.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/input/hid-input.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/input/hid.h linux-2.5.8-pre2/drivers/usb/input/hid.h
--- linux-2.5.8-pre1/drivers/usb/input/hid.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/input/hid.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/input/hiddev.c linux-2.5.8-pre2/drivers/usb/input/hiddev.c
--- linux-2.5.8-pre1/drivers/usb/input/hiddev.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/input/hiddev.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/input/usbkbd.c linux-2.5.8-pre2/drivers/usb/input/usbkbd.c
--- linux-2.5.8-pre1/drivers/usb/input/usbkbd.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/input/usbkbd.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/input/usbmouse.c linux-2.5.8-pre2/drivers/usb/input/usbmouse.c
--- linux-2.5.8-pre1/drivers/usb/input/usbmouse.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/input/usbmouse.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/input/wacom.c linux-2.5.8-pre2/drivers/usb/input/wacom.c
--- linux-2.5.8-pre1/drivers/usb/input/wacom.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/input/wacom.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/kaweth.c linux-2.5.8-pre2/drivers/usb/kaweth.c
--- linux-2.5.8-pre1/drivers/usb/kaweth.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/kaweth.c	Wed Dec 31 16:00:00 1969
@@ -1,1067 +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, 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 -urN linux-2.5.8-pre1/drivers/usb/kawethfw.h linux-2.5.8-pre2/drivers/usb/kawethfw.h
--- linux-2.5.8-pre1/drivers/usb/kawethfw.h	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/drivers/usb/kawethfw.h	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 -urN linux-2.5.8-pre1/drivers/usb/konicawc.c linux-2.5.8-pre2/drivers/usb/konicawc.c
--- linux-2.5.8-pre1/drivers/usb/konicawc.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/konicawc.c	Wed Dec 31 16:00:00 1969
@@ -1,802 +0,0 @@
-/*
- * $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 -urN linux-2.5.8-pre1/drivers/usb/mdc800.c linux-2.5.8-pre2/drivers/usb/mdc800.c
--- linux-2.5.8-pre1/drivers/usb/mdc800.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/drivers/usb/mdc800.c	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 -urN linux-2.5.8-pre1/drivers/usb/media/Config.in linux-2.5.8-pre2/drivers/usb/media/Config.in
--- linux-2.5.8-pre1/drivers/usb/media/Config.in	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/Config.in	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/Makefile linux-2.5.8-pre2/drivers/usb/media/Makefile
--- linux-2.5.8-pre1/drivers/usb/media/Makefile	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/Makefile	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/dabfirmware.h linux-2.5.8-pre2/drivers/usb/media/dabfirmware.h
--- linux-2.5.8-pre1/drivers/usb/media/dabfirmware.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/dabfirmware.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/dabusb.c linux-2.5.8-pre2/drivers/usb/media/dabusb.c
--- linux-2.5.8-pre1/drivers/usb/media/dabusb.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/dabusb.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/dabusb.h linux-2.5.8-pre2/drivers/usb/media/dabusb.h
--- linux-2.5.8-pre1/drivers/usb/media/dabusb.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/dabusb.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/dsbr100.c linux-2.5.8-pre2/drivers/usb/media/dsbr100.c
--- linux-2.5.8-pre1/drivers/usb/media/dsbr100.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/dsbr100.c	Fri Apr  5 16:59:29 2002
@@ -0,0 +1,369 @@
+/* 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 -urN linux-2.5.8-pre1/drivers/usb/media/ibmcam.c linux-2.5.8-pre2/drivers/usb/media/ibmcam.c
--- linux-2.5.8-pre1/drivers/usb/media/ibmcam.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/ibmcam.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/konicawc.c linux-2.5.8-pre2/drivers/usb/media/konicawc.c
--- linux-2.5.8-pre1/drivers/usb/media/konicawc.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/konicawc.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/ov511.c linux-2.5.8-pre2/drivers/usb/media/ov511.c
--- linux-2.5.8-pre1/drivers/usb/media/ov511.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/ov511.c	Fri Apr  5 16:59:29 2002
@@ -0,0 +1,6713 @@
+/*
+ * 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 -urN linux-2.5.8-pre1/drivers/usb/media/ov511.h linux-2.5.8-pre2/drivers/usb/media/ov511.h
--- linux-2.5.8-pre1/drivers/usb/media/ov511.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/ov511.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/pwc-ctrl.c linux-2.5.8-pre2/drivers/usb/media/pwc-ctrl.c
--- linux-2.5.8-pre1/drivers/usb/media/pwc-ctrl.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/pwc-ctrl.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/pwc-if.c linux-2.5.8-pre2/drivers/usb/media/pwc-if.c
--- linux-2.5.8-pre1/drivers/usb/media/pwc-if.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/pwc-if.c	Fri Apr  5 16:59:29 2002
@@ -0,0 +1,2013 @@
+/* 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 -urN linux-2.5.8-pre1/drivers/usb/media/pwc-ioctl.h linux-2.5.8-pre2/drivers/usb/media/pwc-ioctl.h
--- linux-2.5.8-pre1/drivers/usb/media/pwc-ioctl.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/pwc-ioctl.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/pwc-misc.c linux-2.5.8-pre2/drivers/usb/media/pwc-misc.c
--- linux-2.5.8-pre1/drivers/usb/media/pwc-misc.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/pwc-misc.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/pwc-uncompress.c linux-2.5.8-pre2/drivers/usb/media/pwc-uncompress.c
--- linux-2.5.8-pre1/drivers/usb/media/pwc-uncompress.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/pwc-uncompress.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/pwc-uncompress.h linux-2.5.8-pre2/drivers/usb/media/pwc-uncompress.h
--- linux-2.5.8-pre1/drivers/usb/media/pwc-uncompress.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/pwc-uncompress.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/pwc.h linux-2.5.8-pre2/drivers/usb/media/pwc.h
--- linux-2.5.8-pre1/drivers/usb/media/pwc.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/pwc.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/pwc_kiara.h linux-2.5.8-pre2/drivers/usb/media/pwc_kiara.h
--- linux-2.5.8-pre1/drivers/usb/media/pwc_kiara.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/pwc_kiara.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/pwc_nala.h linux-2.5.8-pre2/drivers/usb/media/pwc_nala.h
--- linux-2.5.8-pre1/drivers/usb/media/pwc_nala.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/pwc_nala.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/pwc_timon.h linux-2.5.8-pre2/drivers/usb/media/pwc_timon.h
--- linux-2.5.8-pre1/drivers/usb/media/pwc_timon.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/pwc_timon.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/se401.c linux-2.5.8-pre2/drivers/usb/media/se401.c
--- linux-2.5.8-pre1/drivers/usb/media/se401.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/se401.c	Fri Apr  5 16:59:29 2002
@@ -0,0 +1,1574 @@
+/*
+ * 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 -urN linux-2.5.8-pre1/drivers/usb/media/se401.h linux-2.5.8-pre2/drivers/usb/media/se401.h
--- linux-2.5.8-pre1/drivers/usb/media/se401.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/se401.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/stv680.c linux-2.5.8-pre2/drivers/usb/media/stv680.c
--- linux-2.5.8-pre1/drivers/usb/media/stv680.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/stv680.c	Fri Apr  5 16:59:29 2002
@@ -0,0 +1,1584 @@
+/*
+ *  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 -urN linux-2.5.8-pre1/drivers/usb/media/stv680.h linux-2.5.8-pre2/drivers/usb/media/stv680.h
--- linux-2.5.8-pre1/drivers/usb/media/stv680.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/stv680.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/ultracam.c linux-2.5.8-pre2/drivers/usb/media/ultracam.c
--- linux-2.5.8-pre1/drivers/usb/media/ultracam.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/ultracam.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/usbvideo.c linux-2.5.8-pre2/drivers/usb/media/usbvideo.c
--- linux-2.5.8-pre1/drivers/usb/media/usbvideo.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/usbvideo.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/usbvideo.h linux-2.5.8-pre2/drivers/usb/media/usbvideo.h
--- linux-2.5.8-pre1/drivers/usb/media/usbvideo.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/usbvideo.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/vicam.c linux-2.5.8-pre2/drivers/usb/media/vicam.c
--- linux-2.5.8-pre1/drivers/usb/media/vicam.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/vicam.c	Fri Apr  5 16:59:29 2002
@@ -0,0 +1,921 @@
+/* -*- 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 -urN linux-2.5.8-pre1/drivers/usb/media/vicam.h linux-2.5.8-pre2/drivers/usb/media/vicam.h
--- linux-2.5.8-pre1/drivers/usb/media/vicam.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/vicam.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/media/vicamurbs.h linux-2.5.8-pre2/drivers/usb/media/vicamurbs.h
--- linux-2.5.8-pre1/drivers/usb/media/vicamurbs.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/media/vicamurbs.h	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/microtek.c linux-2.5.8-pre2/drivers/usb/microtek.c
--- linux-2.5.8-pre1/drivers/usb/microtek.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/drivers/usb/microtek.c	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 -urN linux-2.5.8-pre1/drivers/usb/microtek.h linux-2.5.8-pre2/drivers/usb/microtek.h
--- linux-2.5.8-pre1/drivers/usb/microtek.h	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/drivers/usb/microtek.h	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 -urN linux-2.5.8-pre1/drivers/usb/misc/Makefile linux-2.5.8-pre2/drivers/usb/misc/Makefile
--- linux-2.5.8-pre1/drivers/usb/misc/Makefile	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/misc/Makefile	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/misc/auerswald.c linux-2.5.8-pre2/drivers/usb/misc/auerswald.c
--- linux-2.5.8-pre1/drivers/usb/misc/auerswald.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/misc/auerswald.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/misc/emi26.c linux-2.5.8-pre2/drivers/usb/misc/emi26.c
--- linux-2.5.8-pre1/drivers/usb/misc/emi26.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/misc/emi26.c	Fri Apr  5 16:59:29 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 -urN linux-2.5.8-pre1/drivers/usb/misc/emi26_fw.h linux-2.5.8-pre2/drivers/usb/misc/emi26_fw.h
--- linux-2.5.8-pre1/drivers/usb/misc/emi26_fw.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/misc/emi26_fw.h	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/misc/rio500.c linux-2.5.8-pre2/drivers/usb/misc/rio500.c
--- linux-2.5.8-pre1/drivers/usb/misc/rio500.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/misc/rio500.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/misc/rio500_usb.h linux-2.5.8-pre2/drivers/usb/misc/rio500_usb.h
--- linux-2.5.8-pre1/drivers/usb/misc/rio500_usb.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/misc/rio500_usb.h	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/misc/tiglusb.c linux-2.5.8-pre2/drivers/usb/misc/tiglusb.c
--- linux-2.5.8-pre1/drivers/usb/misc/tiglusb.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/misc/tiglusb.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/misc/tiglusb.h linux-2.5.8-pre2/drivers/usb/misc/tiglusb.h
--- linux-2.5.8-pre1/drivers/usb/misc/tiglusb.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/misc/tiglusb.h	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/misc/uss720.c linux-2.5.8-pre2/drivers/usb/misc/uss720.c
--- linux-2.5.8-pre1/drivers/usb/misc/uss720.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/misc/uss720.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/net/Config.in linux-2.5.8-pre2/drivers/usb/net/Config.in
--- linux-2.5.8-pre1/drivers/usb/net/Config.in	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/net/Config.in	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/net/Makefile linux-2.5.8-pre2/drivers/usb/net/Makefile
--- linux-2.5.8-pre1/drivers/usb/net/Makefile	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/net/Makefile	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/net/catc.c linux-2.5.8-pre2/drivers/usb/net/catc.c
--- linux-2.5.8-pre1/drivers/usb/net/catc.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/net/catc.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/net/cdc-ether.c linux-2.5.8-pre2/drivers/usb/net/cdc-ether.c
--- linux-2.5.8-pre1/drivers/usb/net/cdc-ether.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/net/cdc-ether.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/net/cdc-ether.h linux-2.5.8-pre2/drivers/usb/net/cdc-ether.h
--- linux-2.5.8-pre1/drivers/usb/net/cdc-ether.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/net/cdc-ether.h	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/net/kaweth.c linux-2.5.8-pre2/drivers/usb/net/kaweth.c
--- linux-2.5.8-pre1/drivers/usb/net/kaweth.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/net/kaweth.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/net/kawethfw.h linux-2.5.8-pre2/drivers/usb/net/kawethfw.h
--- linux-2.5.8-pre1/drivers/usb/net/kawethfw.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/net/kawethfw.h	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/net/pegasus.c linux-2.5.8-pre2/drivers/usb/net/pegasus.c
--- linux-2.5.8-pre1/drivers/usb/net/pegasus.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/net/pegasus.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/net/pegasus.h linux-2.5.8-pre2/drivers/usb/net/pegasus.h
--- linux-2.5.8-pre1/drivers/usb/net/pegasus.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/net/pegasus.h	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/net/rtl8150.c linux-2.5.8-pre2/drivers/usb/net/rtl8150.c
--- linux-2.5.8-pre1/drivers/usb/net/rtl8150.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/net/rtl8150.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/net/usbnet.c linux-2.5.8-pre2/drivers/usb/net/usbnet.c
--- linux-2.5.8-pre1/drivers/usb/net/usbnet.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/net/usbnet.c	Fri Apr  5 16:59:30 2002
@@ -0,0 +1,1972 @@
+/*
+ * 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,
+			(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);
+
+	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 -urN linux-2.5.8-pre1/drivers/usb/ov511.c linux-2.5.8-pre2/drivers/usb/ov511.c
--- linux-2.5.8-pre1/drivers/usb/ov511.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/usb/ov511.c	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 -urN linux-2.5.8-pre1/drivers/usb/ov511.h linux-2.5.8-pre2/drivers/usb/ov511.h
--- linux-2.5.8-pre1/drivers/usb/ov511.h	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/drivers/usb/ov511.h	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 -urN linux-2.5.8-pre1/drivers/usb/pegasus.c linux-2.5.8-pre2/drivers/usb/pegasus.c
--- linux-2.5.8-pre1/drivers/usb/pegasus.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/pegasus.c	Wed Dec 31 16:00:00 1969
@@ -1,1115 +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.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 -urN linux-2.5.8-pre1/drivers/usb/pegasus.h linux-2.5.8-pre2/drivers/usb/pegasus.h
--- linux-2.5.8-pre1/drivers/usb/pegasus.h	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/pegasus.h	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	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 -urN linux-2.5.8-pre1/drivers/usb/printer.c linux-2.5.8-pre2/drivers/usb/printer.c
--- linux-2.5.8-pre1/drivers/usb/printer.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/printer.c	Wed Dec 31 16:00:00 1969
@@ -1,1116 +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 */
-	{ 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 -urN linux-2.5.8-pre1/drivers/usb/pwc-ctrl.c linux-2.5.8-pre2/drivers/usb/pwc-ctrl.c
--- linux-2.5.8-pre1/drivers/usb/pwc-ctrl.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/drivers/usb/pwc-ctrl.c	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 -urN linux-2.5.8-pre1/drivers/usb/pwc-if.c linux-2.5.8-pre2/drivers/usb/pwc-if.c
--- linux-2.5.8-pre1/drivers/usb/pwc-if.c	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/drivers/usb/pwc-if.c	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 -urN linux-2.5.8-pre1/drivers/usb/pwc-ioctl.h linux-2.5.8-pre2/drivers/usb/pwc-ioctl.h
--- linux-2.5.8-pre1/drivers/usb/pwc-ioctl.h	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/drivers/usb/pwc-ioctl.h	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 -urN linux-2.5.8-pre1/drivers/usb/pwc-misc.c linux-2.5.8-pre2/drivers/usb/pwc-misc.c
--- linux-2.5.8-pre1/drivers/usb/pwc-misc.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/drivers/usb/pwc-misc.c	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 -urN linux-2.5.8-pre1/drivers/usb/pwc-uncompress.c linux-2.5.8-pre2/drivers/usb/pwc-uncompress.c
--- linux-2.5.8-pre1/drivers/usb/pwc-uncompress.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/drivers/usb/pwc-uncompress.c	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 -urN linux-2.5.8-pre1/drivers/usb/pwc-uncompress.h linux-2.5.8-pre2/drivers/usb/pwc-uncompress.h
--- linux-2.5.8-pre1/drivers/usb/pwc-uncompress.h	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/usb/pwc-uncompress.h	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 -urN linux-2.5.8-pre1/drivers/usb/pwc.h linux-2.5.8-pre2/drivers/usb/pwc.h
--- linux-2.5.8-pre1/drivers/usb/pwc.h	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/drivers/usb/pwc.h	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 -urN linux-2.5.8-pre1/drivers/usb/pwc_kiara.h linux-2.5.8-pre2/drivers/usb/pwc_kiara.h
--- linux-2.5.8-pre1/drivers/usb/pwc_kiara.h	Mon Mar 18 12:37:11 2002
+++ linux-2.5.8-pre2/drivers/usb/pwc_kiara.h	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 -urN linux-2.5.8-pre1/drivers/usb/pwc_nala.h linux-2.5.8-pre2/drivers/usb/pwc_nala.h
--- linux-2.5.8-pre1/drivers/usb/pwc_nala.h	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/drivers/usb/pwc_nala.h	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 -urN linux-2.5.8-pre1/drivers/usb/pwc_timon.h linux-2.5.8-pre2/drivers/usb/pwc_timon.h
--- linux-2.5.8-pre1/drivers/usb/pwc_timon.h	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/drivers/usb/pwc_timon.h	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 -urN linux-2.5.8-pre1/drivers/usb/rio500.c linux-2.5.8-pre2/drivers/usb/rio500.c
--- linux-2.5.8-pre1/drivers/usb/rio500.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/drivers/usb/rio500.c	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 -urN linux-2.5.8-pre1/drivers/usb/rio500_usb.h linux-2.5.8-pre2/drivers/usb/rio500_usb.h
--- linux-2.5.8-pre1/drivers/usb/rio500_usb.h	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/drivers/usb/rio500_usb.h	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 -urN linux-2.5.8-pre1/drivers/usb/rtl8150.c linux-2.5.8-pre2/drivers/usb/rtl8150.c
--- linux-2.5.8-pre1/drivers/usb/rtl8150.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/rtl8150.c	Wed Dec 31 16:00:00 1969
@@ -1,763 +0,0 @@
-/*
- * 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 -urN linux-2.5.8-pre1/drivers/usb/scanner.c linux-2.5.8-pre2/drivers/usb/scanner.c
--- linux-2.5.8-pre1/drivers/usb/scanner.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/drivers/usb/scanner.c	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 -urN linux-2.5.8-pre1/drivers/usb/scanner.h linux-2.5.8-pre2/drivers/usb/scanner.h
--- linux-2.5.8-pre1/drivers/usb/scanner.h	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/drivers/usb/scanner.h	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 -urN linux-2.5.8-pre1/drivers/usb/se401.c linux-2.5.8-pre2/drivers/usb/se401.c
--- linux-2.5.8-pre1/drivers/usb/se401.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/usb/se401.c	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 -urN linux-2.5.8-pre1/drivers/usb/se401.h linux-2.5.8-pre2/drivers/usb/se401.h
--- linux-2.5.8-pre1/drivers/usb/se401.h	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/usb/se401.h	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 -urN linux-2.5.8-pre1/drivers/usb/serial/visor.c linux-2.5.8-pre2/drivers/usb/serial/visor.c
--- linux-2.5.8-pre1/drivers/usb/serial/visor.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/serial/visor.c	Fri Apr  5 16:59:30 2002
@@ -12,6 +12,10 @@
  *
  * 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.)
@@ -186,6 +190,7 @@
 	{ 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 */
 };
 
@@ -205,6 +210,7 @@
 	{ 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 */
 };
 
@@ -215,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,
@@ -582,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,
diff -urN linux-2.5.8-pre1/drivers/usb/serial/visor.h linux-2.5.8-pre2/drivers/usb/serial/visor.h
--- linux-2.5.8-pre1/drivers/usb/serial/visor.h	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/serial/visor.h	Fri Apr  5 16:59:30 2002
@@ -32,6 +32,7 @@
 #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 -urN linux-2.5.8-pre1/drivers/usb/storage/Config.help linux-2.5.8-pre2/drivers/usb/storage/Config.help
--- linux-2.5.8-pre1/drivers/usb/storage/Config.help	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/storage/Config.help	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/storage/Config.in linux-2.5.8-pre2/drivers/usb/storage/Config.in
--- linux-2.5.8-pre1/drivers/usb/storage/Config.in	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/usb/storage/Config.in	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/storage/Makefile linux-2.5.8-pre2/drivers/usb/storage/Makefile
--- linux-2.5.8-pre1/drivers/usb/storage/Makefile	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/drivers/usb/storage/Makefile	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/usb/stv680.c linux-2.5.8-pre2/drivers/usb/stv680.c
--- linux-2.5.8-pre1/drivers/usb/stv680.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/drivers/usb/stv680.c	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 -urN linux-2.5.8-pre1/drivers/usb/stv680.h linux-2.5.8-pre2/drivers/usb/stv680.h
--- linux-2.5.8-pre1/drivers/usb/stv680.h	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/drivers/usb/stv680.h	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 -urN linux-2.5.8-pre1/drivers/usb/tiglusb.c linux-2.5.8-pre2/drivers/usb/tiglusb.c
--- linux-2.5.8-pre1/drivers/usb/tiglusb.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/tiglusb.c	Wed Dec 31 16:00:00 1969
@@ -1,495 +0,0 @@
-/* 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 -urN linux-2.5.8-pre1/drivers/usb/tiglusb.h linux-2.5.8-pre2/drivers/usb/tiglusb.h
--- linux-2.5.8-pre1/drivers/usb/tiglusb.h	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/tiglusb.h	Wed Dec 31 16:00:00 1969
@@ -1,55 +0,0 @@
-/* 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 -urN linux-2.5.8-pre1/drivers/usb/uhci-debug.h linux-2.5.8-pre2/drivers/usb/uhci-debug.h
--- linux-2.5.8-pre1/drivers/usb/uhci-debug.h	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/drivers/usb/uhci-debug.h	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 -urN linux-2.5.8-pre1/drivers/usb/uhci.c linux-2.5.8-pre2/drivers/usb/uhci.c
--- linux-2.5.8-pre1/drivers/usb/uhci.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/uhci.c	Wed Dec 31 16:00:00 1969
@@ -1,3174 +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;
-	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->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);
-		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);
-			spin_unlock_irqrestore(&urb->lock, flags);
-			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, 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;
-
-			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);
-
-	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->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 -urN linux-2.5.8-pre1/drivers/usb/uhci.h linux-2.5.8-pre2/drivers/usb/uhci.h
--- linux-2.5.8-pre1/drivers/usb/uhci.h	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/drivers/usb/uhci.h	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 -urN linux-2.5.8-pre1/drivers/usb/ultracam.c linux-2.5.8-pre2/drivers/usb/ultracam.c
--- linux-2.5.8-pre1/drivers/usb/ultracam.c	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/drivers/usb/ultracam.c	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 -urN linux-2.5.8-pre1/drivers/usb/usb-debug.c linux-2.5.8-pre2/drivers/usb/usb-debug.c
--- linux-2.5.8-pre1/drivers/usb/usb-debug.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/drivers/usb/usb-debug.c	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 -urN linux-2.5.8-pre1/drivers/usb/usb-ohci.c linux-2.5.8-pre2/drivers/usb/usb-ohci.c
--- linux-2.5.8-pre1/drivers/usb/usb-ohci.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/usb-ohci.c	Wed Dec 31 16:00:00 1969
@@ -1,2919 +0,0 @@
-/*
- * 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 "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 -urN linux-2.5.8-pre1/drivers/usb/usb-ohci.h linux-2.5.8-pre2/drivers/usb/usb-ohci.h
--- linux-2.5.8-pre1/drivers/usb/usb-ohci.h	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/usb-ohci.h	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 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 -urN linux-2.5.8-pre1/drivers/usb/usb-uhci-debug.h linux-2.5.8-pre2/drivers/usb/usb-uhci-debug.h
--- linux-2.5.8-pre1/drivers/usb/usb-uhci-debug.h	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/drivers/usb/usb-uhci-debug.h	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 -urN linux-2.5.8-pre1/drivers/usb/usb-uhci.c linux-2.5.8-pre2/drivers/usb/usb-uhci.c
--- linux-2.5.8-pre1/drivers/usb/usb-uhci.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/usb-uhci.c	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)
-{
-	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 -urN linux-2.5.8-pre1/drivers/usb/usb-uhci.h linux-2.5.8-pre2/drivers/usb/usb-uhci.h
--- linux-2.5.8-pre1/drivers/usb/usb-uhci.h	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/drivers/usb/usb-uhci.h	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 -urN linux-2.5.8-pre1/drivers/usb/usb.c linux-2.5.8-pre2/drivers/usb/usb.c
--- linux-2.5.8-pre1/drivers/usb/usb.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/usb.c	Wed Dec 31 16:00:00 1969
@@ -1,2687 +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!!
-// FIXME the public call should BUG() whenever count goes to zero,
-// the usbcore-internal one should do so _unless_ it does so...
-void usb_free_dev(struct usb_device *dev)
-{
-	if (atomic_dec_and_test(&dev->refcnt)) {
-		/* Normally only goes to zero in usb_disconnect(), from
-		 * khubd or from roothub shutdown (rmmod/apmd/... thread).
-		 * Abnormally, roothub init errors can happen, so HCDs
-		 * call this directly.
-		 *
-		 * Otherwise this is a nasty device driver bug, often in
-		 * disconnect processing.
-		 */
-		if (in_interrupt ())
-			BUG ();
-
-		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 -urN linux-2.5.8-pre1/drivers/usb/usbkbd.c linux-2.5.8-pre2/drivers/usb/usbkbd.c
--- linux-2.5.8-pre1/drivers/usb/usbkbd.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/drivers/usb/usbkbd.c	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 -urN linux-2.5.8-pre1/drivers/usb/usbmouse.c linux-2.5.8-pre2/drivers/usb/usbmouse.c
--- linux-2.5.8-pre1/drivers/usb/usbmouse.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/drivers/usb/usbmouse.c	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 -urN linux-2.5.8-pre1/drivers/usb/usbnet.c linux-2.5.8-pre2/drivers/usb/usbnet.c
--- linux-2.5.8-pre1/drivers/usb/usbnet.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/usbnet.c	Wed Dec 31 16:00:00 1969
@@ -1,1972 +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,
-			(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);
-
-	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 -urN linux-2.5.8-pre1/drivers/usb/usbvideo.c linux-2.5.8-pre2/drivers/usb/usbvideo.c
--- linux-2.5.8-pre1/drivers/usb/usbvideo.c	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/usbvideo.c	Wed Dec 31 16:00:00 1969
@@ -1,2402 +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:    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 -urN linux-2.5.8-pre1/drivers/usb/usbvideo.h linux-2.5.8-pre2/drivers/usb/usbvideo.h
--- linux-2.5.8-pre1/drivers/usb/usbvideo.h	Fri Apr  5 16:59:19 2002
+++ linux-2.5.8-pre2/drivers/usb/usbvideo.h	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 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 -urN linux-2.5.8-pre1/drivers/usb/uss720.c linux-2.5.8-pre2/drivers/usb/uss720.c
--- linux-2.5.8-pre1/drivers/usb/uss720.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/drivers/usb/uss720.c	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 -urN linux-2.5.8-pre1/drivers/usb/vicam.c linux-2.5.8-pre2/drivers/usb/vicam.c
--- linux-2.5.8-pre1/drivers/usb/vicam.c	Mon Mar 18 12:37:11 2002
+++ linux-2.5.8-pre2/drivers/usb/vicam.c	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 -urN linux-2.5.8-pre1/drivers/usb/vicam.h linux-2.5.8-pre2/drivers/usb/vicam.h
--- linux-2.5.8-pre1/drivers/usb/vicam.h	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/drivers/usb/vicam.h	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 -urN linux-2.5.8-pre1/drivers/usb/vicamurbs.h linux-2.5.8-pre2/drivers/usb/vicamurbs.h
--- linux-2.5.8-pre1/drivers/usb/vicamurbs.h	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/drivers/usb/vicamurbs.h	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 -urN linux-2.5.8-pre1/drivers/usb/wacom.c linux-2.5.8-pre2/drivers/usb/wacom.c
--- linux-2.5.8-pre1/drivers/usb/wacom.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/drivers/usb/wacom.c	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 -urN linux-2.5.8-pre1/drivers/video/Config.in linux-2.5.8-pre2/drivers/video/Config.in
--- linux-2.5.8-pre1/drivers/video/Config.in	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/drivers/video/Config.in	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/video/Makefile linux-2.5.8-pre2/drivers/video/Makefile
--- linux-2.5.8-pre1/drivers/video/Makefile	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/drivers/video/Makefile	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/video/anakinfb.c linux-2.5.8-pre2/drivers/video/anakinfb.c
--- linux-2.5.8-pre1/drivers/video/anakinfb.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/video/anakinfb.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/video/clps711xfb.c linux-2.5.8-pre2/drivers/video/clps711xfb.c
--- linux-2.5.8-pre1/drivers/video/clps711xfb.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/drivers/video/clps711xfb.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/video/cyber2000fb.c linux-2.5.8-pre2/drivers/video/cyber2000fb.c
--- linux-2.5.8-pre1/drivers/video/cyber2000fb.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/drivers/video/cyber2000fb.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/video/cyber2000fb.h linux-2.5.8-pre2/drivers/video/cyber2000fb.h
--- linux-2.5.8-pre1/drivers/video/cyber2000fb.h	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/drivers/video/cyber2000fb.h	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/video/fbmem.c linux-2.5.8-pre2/drivers/video/fbmem.c
--- linux-2.5.8-pre1/drivers/video/fbmem.c	Mon Mar 18 12:37:01 2002
+++ linux-2.5.8-pre2/drivers/video/fbmem.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/video/sa1100fb.c linux-2.5.8-pre2/drivers/video/sa1100fb.c
--- linux-2.5.8-pre1/drivers/video/sa1100fb.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/drivers/video/sa1100fb.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/drivers/video/sa1100fb.h linux-2.5.8-pre2/drivers/video/sa1100fb.h
--- linux-2.5.8-pre1/drivers/video/sa1100fb.h	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/drivers/video/sa1100fb.h	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/Config.help linux-2.5.8-pre2/fs/Config.help
--- linux-2.5.8-pre1/fs/Config.help	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/fs/Config.help	Fri Apr  5 16:59:30 2002
@@ -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
@@ -696,6 +698,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
   on demand. This implementation is partially kernel-based to reduce
diff -urN linux-2.5.8-pre1/fs/Config.in linux-2.5.8-pre2/fs/Config.in
--- linux-2.5.8-pre1/fs/Config.in	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/fs/Config.in	Fri Apr  5 16:59:30 2002
@@ -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 -urN linux-2.5.8-pre1/fs/adfs/dir_f.c linux-2.5.8-pre2/fs/adfs/dir_f.c
--- linux-2.5.8-pre1/fs/adfs/dir_f.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/fs/adfs/dir_f.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/adfs/dir_fplus.c linux-2.5.8-pre2/fs/adfs/dir_fplus.c
--- linux-2.5.8-pre1/fs/adfs/dir_fplus.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/fs/adfs/dir_fplus.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/adfs/inode.c linux-2.5.8-pre2/fs/adfs/inode.c
--- linux-2.5.8-pre1/fs/adfs/inode.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/fs/adfs/inode.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/affs/inode.c linux-2.5.8-pre2/fs/affs/inode.c
--- linux-2.5.8-pre1/fs/affs/inode.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/fs/affs/inode.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/attr.c linux-2.5.8-pre2/fs/attr.c
--- linux-2.5.8-pre1/fs/attr.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/fs/attr.c	Fri Apr  5 16:59:30 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;
 }
 
@@ -127,7 +132,7 @@
 	if (!(ia_valid & ATTR_MTIME_SET))
 		attr->ia_mtime = now;
 
-	lock_kernel();
+	down(&inode->i_sem);
 	if (inode->i_op && inode->i_op->setattr) 
 		error = inode->i_op->setattr(dentry, attr);
 	else {
@@ -140,7 +145,7 @@
 				error = inode_setattr(inode, attr);
 		}
 	}
-	unlock_kernel();
+	up(&inode->i_sem);
 	if (!error) {
 		unsigned long dn_mask = setattr_mask(ia_valid);
 		if (dn_mask)
diff -urN linux-2.5.8-pre1/fs/binfmt_aout.c linux-2.5.8-pre2/fs/binfmt_aout.c
--- linux-2.5.8-pre1/fs/binfmt_aout.c	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/fs/binfmt_aout.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/binfmt_elf.c linux-2.5.8-pre2/fs/binfmt_elf.c
--- linux-2.5.8-pre1/fs/binfmt_elf.c	Fri Apr  5 16:59:20 2002
+++ linux-2.5.8-pre2/fs/binfmt_elf.c	Fri Apr  5 16:59:30 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)
diff -urN linux-2.5.8-pre1/fs/binfmt_em86.c linux-2.5.8-pre2/fs/binfmt_em86.c
--- linux-2.5.8-pre1/fs/binfmt_em86.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/fs/binfmt_em86.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/binfmt_misc.c linux-2.5.8-pre2/fs/binfmt_misc.c
--- linux-2.5.8-pre1/fs/binfmt_misc.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/fs/binfmt_misc.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/binfmt_script.c linux-2.5.8-pre2/fs/binfmt_script.c
--- linux-2.5.8-pre1/fs/binfmt_script.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/fs/binfmt_script.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/block_dev.c linux-2.5.8-pre2/fs/block_dev.c
--- linux-2.5.8-pre1/fs/block_dev.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/block_dev.c	Fri Apr  5 16:59:30 2002
@@ -337,7 +337,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;
diff -urN linux-2.5.8-pre1/fs/char_dev.c linux-2.5.8-pre2/fs/char_dev.c
--- linux-2.5.8-pre1/fs/char_dev.c	Mon Mar 18 12:37:11 2002
+++ linux-2.5.8-pre2/fs/char_dev.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/coda/inode.c linux-2.5.8-pre2/fs/coda/inode.c
--- linux-2.5.8-pre1/fs/coda/inode.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/coda/inode.c	Fri Apr  5 16:59:30 2002
@@ -258,6 +258,8 @@
         struct coda_vattr vattr;
         int error;
 	
+	lock_kernel();
+	
         memset(&vattr, 0, sizeof(vattr)); 
 
 	inode->i_ctime = CURRENT_TIME;
@@ -272,6 +274,8 @@
 		coda_cache_clear_inode(inode);
 	}
 
+	unlock_kernel();
+
 	return error;
 }
 
diff -urN linux-2.5.8-pre1/fs/dquot.c linux-2.5.8-pre2/fs/dquot.c
--- linux-2.5.8-pre1/fs/dquot.c	Fri Apr  5 16:59:20 2002
+++ linux-2.5.8-pre2/fs/dquot.c	Fri Apr  5 16:59:30 2002
@@ -337,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;
@@ -367,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;
@@ -429,8 +429,7 @@
 	count = nr_free_dquots / priority;
 	prune_dqcache(count);
 	unlock_kernel();
-	kmem_cache_shrink(dquot_cachep);
-	return 0;
+	return kmem_cache_shrink_nr(dquot_cachep);
 }
 
 /* NOTE: If you change this function please check whether dqput_blocks() works right... */
@@ -579,7 +578,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)) {
@@ -1269,13 +1268,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 -urN linux-2.5.8-pre1/fs/ext2/ext2.h linux-2.5.8-pre2/fs/ext2/ext2.h
--- linux-2.5.8-pre1/fs/ext2/ext2.h	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/fs/ext2/ext2.h	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/ext2/ialloc.c linux-2.5.8-pre2/fs/ext2/ialloc.c
--- linux-2.5.8-pre1/fs/ext2/ialloc.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/fs/ext2/ialloc.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/ext2/inode.c linux-2.5.8-pre2/fs/ext2/inode.c
--- linux-2.5.8-pre1/fs/ext2/inode.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/ext2/inode.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/ext3/balloc.c linux-2.5.8-pre2/fs/ext3/balloc.c
--- linux-2.5.8-pre1/fs/ext3/balloc.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/ext3/balloc.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/ext3/ialloc.c linux-2.5.8-pre2/fs/ext3/ialloc.c
--- linux-2.5.8-pre1/fs/ext3/ialloc.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/ext3/ialloc.c	Fri Apr  5 16:59:30 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 -urN linux-2.5.8-pre1/fs/ext3/inode.c linux-2.5.8-pre2/fs/ext3/inode.c
--- linux-2.5.8-pre1/fs/ext3/inode.c	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/fs/ext3/inode.c	Fri Apr  5 16:59:30 2002
@@ -584,8 +584,6 @@
 			
 			parent = nr;
 		}
-		if (IS_SYNC(inode))
-			handle->h_sync = 1;
 	}
 	if (n == num)
 		return 0;
diff -urN linux-2.5.8-pre1/fs/fat/inode.c linux-2.5.8-pre2/fs/fat/inode.c
--- linux-2.5.8-pre1/fs/fat/inode.c	Fri Apr  5 16:59:20 2002
+++ linux-2.5.8-pre2/fs/fat/inode.c	Fri Apr  5 16:59:31 2002
@@ -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,13 @@
 	     (attr->ia_mode & ~MSDOS_VALID_MODE)))
 		error = -EPERM;
 
-	if (error)
-		return MSDOS_SB(sb)->options.quiet ? 0 : error;
-
-	error = inode_setattr(inode, attr);
-	if (error)
-		return error;
+	if (error) {
+		if( MSDOS_SB(sb)->options.quiet )  
+			error = 0;
+		goto out;
+	}
+	if( error = inode_setattr(inode, attr) )
+		goto out;
 
 	if (S_ISDIR(inode->i_mode))
 		inode->i_mode |= S_IXUGO;
@@ -1087,6 +1095,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 -urN linux-2.5.8-pre1/fs/file_table.c linux-2.5.8-pre2/fs/file_table.c
--- linux-2.5.8-pre1/fs/file_table.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/file_table.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/hfs/file_hdr.c linux-2.5.8-pre2/fs/hfs/file_hdr.c
--- linux-2.5.8-pre1/fs/hfs/file_hdr.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/fs/hfs/file_hdr.c	Fri Apr  5 16:59:31 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},
diff -urN linux-2.5.8-pre1/fs/hfs/inode.c linux-2.5.8-pre2/fs/hfs/inode.c
--- linux-2.5.8-pre1/fs/hfs/inode.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/fs/hfs/inode.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/hpfs/inode.c linux-2.5.8-pre2/fs/hpfs/inode.c
--- linux-2.5.8-pre1/fs/hpfs/inode.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/fs/hpfs/inode.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/intermezzo/dir.c linux-2.5.8-pre2/fs/intermezzo/dir.c
--- linux-2.5.8-pre1/fs/intermezzo/dir.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/fs/intermezzo/dir.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/isofs/compress.c linux-2.5.8-pre2/fs/isofs/compress.c
--- linux-2.5.8-pre1/fs/isofs/compress.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/fs/isofs/compress.c	Fri Apr  5 16:59:31 2002
@@ -330,7 +330,7 @@
 	/* No bmap operation supported */
 };
 
-static int initialized = 0;
+static int initialized;
 
 int __init zisofs_init(void)
 {
diff -urN linux-2.5.8-pre1/fs/isofs/inode.c linux-2.5.8-pre2/fs/isofs/inode.c
--- linux-2.5.8-pre1/fs/isofs/inode.c	Fri Apr  5 16:59:20 2002
+++ linux-2.5.8-pre2/fs/isofs/inode.c	Fri Apr  5 16:59:31 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);
diff -urN linux-2.5.8-pre1/fs/jbd/journal.c linux-2.5.8-pre2/fs/jbd/journal.c
--- linux-2.5.8-pre1/fs/jbd/journal.c	Fri Apr  5 16:59:20 2002
+++ linux-2.5.8-pre2/fs/jbd/journal.c	Fri Apr  5 16:59:31 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;
 }
 
diff -urN linux-2.5.8-pre1/fs/jffs/inode-v23.c linux-2.5.8-pre2/fs/jffs/inode-v23.c
--- linux-2.5.8-pre1/fs/jffs/inode-v23.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/jffs/inode-v23.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jffs2/file.c linux-2.5.8-pre2/fs/jffs2/file.c
--- linux-2.5.8-pre1/fs/jffs2/file.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/fs/jffs2/file.c	Fri Apr  5 16:59:31 2002
@@ -109,11 +109,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 +131,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 +147,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 +156,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 +205,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 +240,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 -urN linux-2.5.8-pre1/fs/jfs/endian24.h linux-2.5.8-pre2/fs/jfs/endian24.h
--- linux-2.5.8-pre1/fs/jfs/endian24.h	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/fs/jfs/endian24.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/file.c linux-2.5.8-pre2/fs/jfs/file.c
--- linux-2.5.8-pre1/fs/jfs/file.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/fs/jfs/file.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/inode.c linux-2.5.8-pre2/fs/jfs/inode.c
--- linux-2.5.8-pre1/fs/jfs/inode.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/fs/jfs/inode.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_btree.h linux-2.5.8-pre2/fs/jfs/jfs_btree.h
--- linux-2.5.8-pre1/fs/jfs/jfs_btree.h	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_btree.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_debug.c linux-2.5.8-pre2/fs/jfs/jfs_debug.c
--- linux-2.5.8-pre1/fs/jfs/jfs_debug.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_debug.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_debug.h linux-2.5.8-pre2/fs/jfs/jfs_debug.h
--- linux-2.5.8-pre1/fs/jfs/jfs_debug.h	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_debug.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_defragfs.h linux-2.5.8-pre2/fs/jfs/jfs_defragfs.h
--- linux-2.5.8-pre1/fs/jfs/jfs_defragfs.h	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_defragfs.h	Fri Apr  5 16:59:31 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,11 @@
  *   You should have received a copy of the GNU General Public 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
  */
 typedef struct {
diff -urN linux-2.5.8-pre1/fs/jfs/jfs_dinode.h linux-2.5.8-pre2/fs/jfs/jfs_dinode.h
--- linux-2.5.8-pre1/fs/jfs/jfs_dinode.h	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_dinode.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_dmap.c linux-2.5.8-pre2/fs/jfs/jfs_dmap.c
--- linux-2.5.8-pre1/fs/jfs/jfs_dmap.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_dmap.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_dmap.h linux-2.5.8-pre2/fs/jfs/jfs_dmap.h
--- linux-2.5.8-pre1/fs/jfs/jfs_dmap.h	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_dmap.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_dtree.c linux-2.5.8-pre2/fs/jfs/jfs_dtree.c
--- linux-2.5.8-pre1/fs/jfs/jfs_dtree.c	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_dtree.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_dtree.h linux-2.5.8-pre2/fs/jfs/jfs_dtree.h
--- linux-2.5.8-pre1/fs/jfs/jfs_dtree.h	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_dtree.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_extendfs.h linux-2.5.8-pre2/fs/jfs/jfs_extendfs.h
--- linux-2.5.8-pre1/fs/jfs/jfs_extendfs.h	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_extendfs.h	Fri Apr  5 16:59:31 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
@@ -19,9 +19,6 @@
 #define _H_JFS_EXTENDFS
 
 /*
- *	jfs_extendfs.h
- */
-/*
  *	extendfs parameter list
  */
 typedef struct {
diff -urN linux-2.5.8-pre1/fs/jfs/jfs_extent.c linux-2.5.8-pre2/fs/jfs/jfs_extent.c
--- linux-2.5.8-pre1/fs/jfs/jfs_extent.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_extent.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_extent.h linux-2.5.8-pre2/fs/jfs/jfs_extent.h
--- linux-2.5.8-pre1/fs/jfs/jfs_extent.h	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_extent.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_filsys.h linux-2.5.8-pre2/fs/jfs/jfs_filsys.h
--- linux-2.5.8-pre1/fs/jfs/jfs_filsys.h	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_filsys.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_imap.c linux-2.5.8-pre2/fs/jfs/jfs_imap.c
--- linux-2.5.8-pre1/fs/jfs/jfs_imap.c	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_imap.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_imap.h linux-2.5.8-pre2/fs/jfs/jfs_imap.h
--- linux-2.5.8-pre1/fs/jfs/jfs_imap.h	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_imap.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_incore.h linux-2.5.8-pre2/fs/jfs/jfs_incore.h
--- linux-2.5.8-pre1/fs/jfs/jfs_incore.h	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_incore.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_inode.c linux-2.5.8-pre2/fs/jfs/jfs_inode.c
--- linux-2.5.8-pre1/fs/jfs/jfs_inode.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_inode.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_inode.h linux-2.5.8-pre2/fs/jfs/jfs_inode.h
--- linux-2.5.8-pre1/fs/jfs/jfs_inode.h	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_inode.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_lock.h linux-2.5.8-pre2/fs/jfs/jfs_lock.h
--- linux-2.5.8-pre1/fs/jfs/jfs_lock.h	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_lock.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_logmgr.c linux-2.5.8-pre2/fs/jfs/jfs_logmgr.c
--- linux-2.5.8-pre1/fs/jfs/jfs_logmgr.c	Fri Apr  5 16:59:20 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_logmgr.c	Fri Apr  5 16:59:31 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,7 +60,6 @@
 
 #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>
@@ -160,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;
@@ -173,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);
 
@@ -186,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);
 
@@ -1060,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;
 
 	/*
@@ -1108,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));
@@ -1256,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;
 
@@ -1285,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));
@@ -1379,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;
@@ -1422,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;
 }
@@ -1564,7 +1476,6 @@
 }
 
 
-#ifdef _STILL_TO_PORT
 /*
  * NAME:	lmLogFileSystem()
  *
@@ -1572,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.
  *
@@ -1581,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;
 
@@ -1595,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:
@@ -1621,7 +1543,6 @@
 
 	return rc;
 }
-#endif				/* _STILL_TO_PORT */
 
 
 /*
@@ -1811,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
  *
@@ -2275,63 +2160,6 @@
 
 #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
-/*
  * NAME:	lmLogFormat()/jfs_logform()
  *
  * FUNCTION:	format file system log (ref. jfs_logform()).
diff -urN linux-2.5.8-pre1/fs/jfs/jfs_logmgr.h linux-2.5.8-pre2/fs/jfs/jfs_logmgr.h
--- linux-2.5.8-pre1/fs/jfs/jfs_logmgr.h	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_logmgr.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_metapage.c linux-2.5.8-pre2/fs/jfs/jfs_metapage.c
--- linux-2.5.8-pre1/fs/jfs/jfs_metapage.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_metapage.c	Fri Apr  5 16:59:31 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,
@@ -528,8 +540,6 @@
 		return;
 	}
 
-	ip = (struct inode *) mp->mapping->host;
-
 	assert(mp->count);
 	if (--mp->count || atomic_read(&mp->nohomeok)) {
 		unlock_metapage(mp);
diff -urN linux-2.5.8-pre1/fs/jfs/jfs_metapage.h linux-2.5.8-pre2/fs/jfs/jfs_metapage.h
--- linux-2.5.8-pre1/fs/jfs/jfs_metapage.h	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_metapage.h	Fri Apr  5 16:59:31 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,33 +84,27 @@
 	 __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 -urN linux-2.5.8-pre1/fs/jfs/jfs_mount.c linux-2.5.8-pre2/fs/jfs/jfs_mount.c
--- linux-2.5.8-pre1/fs/jfs/jfs_mount.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_mount.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_superblock.h linux-2.5.8-pre2/fs/jfs/jfs_superblock.h
--- linux-2.5.8-pre1/fs/jfs/jfs_superblock.h	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_superblock.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_txnmgr.c linux-2.5.8-pre2/fs/jfs/jfs_txnmgr.c
--- linux-2.5.8-pre1/fs/jfs/jfs_txnmgr.c	Fri Apr  5 16:59:20 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_txnmgr.c	Fri Apr  5 16:59:31 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
@@ -82,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 */
 
diff -urN linux-2.5.8-pre1/fs/jfs/jfs_txnmgr.h linux-2.5.8-pre2/fs/jfs/jfs_txnmgr.h
--- linux-2.5.8-pre1/fs/jfs/jfs_txnmgr.h	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_txnmgr.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_types.h linux-2.5.8-pre2/fs/jfs/jfs_types.h
--- linux-2.5.8-pre1/fs/jfs/jfs_types.h	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_types.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_umount.c linux-2.5.8-pre2/fs/jfs/jfs_umount.c
--- linux-2.5.8-pre1/fs/jfs/jfs_umount.c	Mon Mar 18 12:37:01 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_umount.c	Fri Apr  5 16:59:31 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
@@ -18,10 +17,6 @@
  */
 
 /*
- * Change History :
- */
-
-/*
  *	jfs_umount.c
  *
  * note: file system in transition to aggregate/fileset:
diff -urN linux-2.5.8-pre1/fs/jfs/jfs_unicode.c linux-2.5.8-pre2/fs/jfs/jfs_unicode.c
--- linux-2.5.8-pre1/fs/jfs/jfs_unicode.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_unicode.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_unicode.h linux-2.5.8-pre2/fs/jfs/jfs_unicode.h
--- linux-2.5.8-pre1/fs/jfs/jfs_unicode.h	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_unicode.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_uniupr.c linux-2.5.8-pre2/fs/jfs/jfs_uniupr.c
--- linux-2.5.8-pre1/fs/jfs/jfs_uniupr.c	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_uniupr.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_xtree.c linux-2.5.8-pre2/fs/jfs/jfs_xtree.c
--- linux-2.5.8-pre1/fs/jfs/jfs_xtree.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_xtree.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/jfs_xtree.h linux-2.5.8-pre2/fs/jfs/jfs_xtree.h
--- linux-2.5.8-pre1/fs/jfs/jfs_xtree.h	Mon Mar 18 12:37:19 2002
+++ linux-2.5.8-pre2/fs/jfs/jfs_xtree.h	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/namei.c linux-2.5.8-pre2/fs/jfs/namei.c
--- linux-2.5.8-pre1/fs/jfs/namei.c	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/fs/jfs/namei.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/jfs/super.c linux-2.5.8-pre2/fs/jfs/super.c
--- linux-2.5.8-pre1/fs/jfs/super.c	Fri Apr  5 16:59:20 2002
+++ linux-2.5.8-pre2/fs/jfs/super.c	Fri Apr  5 16:59:31 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,6 @@
 #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"
diff -urN linux-2.5.8-pre1/fs/jfs/symlink.c linux-2.5.8-pre2/fs/jfs/symlink.c
--- linux-2.5.8-pre1/fs/jfs/symlink.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/jfs/symlink.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/lockd/mon.c linux-2.5.8-pre2/fs/lockd/mon.c
--- linux-2.5.8-pre1/fs/lockd/mon.c	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/fs/lockd/mon.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/lockd/svc.c linux-2.5.8-pre2/fs/lockd/svc.c
--- linux-2.5.8-pre1/fs/lockd/svc.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/fs/lockd/svc.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/lockd/xdr.c linux-2.5.8-pre2/fs/lockd/xdr.c
--- linux-2.5.8-pre1/fs/lockd/xdr.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/lockd/xdr.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/lockd/xdr4.c linux-2.5.8-pre2/fs/lockd/xdr4.c
--- linux-2.5.8-pre1/fs/lockd/xdr4.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/lockd/xdr4.c	Fri Apr  5 16:59:31 2002
@@ -609,5 +609,7 @@
 };
 
 struct rpc_version	nlm_version4 = {
-	4, 24, nlm4_procedures,
+	number:		4,
+	nrprocs:	24,
+	procs:		nlm4_procedures,
 };
diff -urN linux-2.5.8-pre1/fs/msdos/namei.c linux-2.5.8-pre2/fs/msdos/namei.c
--- linux-2.5.8-pre1/fs/msdos/namei.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/msdos/namei.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/namei.c linux-2.5.8-pre2/fs/namei.c
--- linux-2.5.8-pre1/fs/namei.c	Mon Mar 18 12:37:11 2002
+++ linux-2.5.8-pre2/fs/namei.c	Fri Apr  5 16:59:31 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;
 }
 
@@ -1390,9 +1392,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 +1776,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 -urN linux-2.5.8-pre1/fs/ncpfs/inode.c linux-2.5.8-pre2/fs/ncpfs/inode.c
--- linux-2.5.8-pre1/fs/ncpfs/inode.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/ncpfs/inode.c	Fri Apr  5 16:59:31 2002
@@ -592,6 +592,8 @@
 
 	result = -EIO;
 
+	lock_kernel();	
+
 	server = NCP_SERVER(inode);
 	if ((!server) || !ncp_conn_valid(server))
 		goto out;
@@ -636,7 +638,8 @@
 				info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
                 } else if (!S_ISREG(inode->i_mode))
                 {
-                        return -EPERM;
+			result = -EPERM;
+			goto out;
                 }
                 else
                 {
@@ -722,7 +725,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 +739,7 @@
 			result = vmtruncate(inode, attr->ia_size);
 	}
 out:
+	unlock_kernel();
 	return result;
 }
 
diff -urN linux-2.5.8-pre1/fs/nfs/inode.c linux-2.5.8-pre2/fs/nfs/inode.c
--- linux-2.5.8-pre1/fs/nfs/inode.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/fs/nfs/inode.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfs/mount_clnt.c linux-2.5.8-pre2/fs/nfs/mount_clnt.c
--- linux-2.5.8-pre1/fs/nfs/mount_clnt.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/nfs/mount_clnt.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfs/nfs2xdr.c linux-2.5.8-pre2/fs/nfs/nfs2xdr.c
--- linux-2.5.8-pre1/fs/nfs/nfs2xdr.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/fs/nfs/nfs2xdr.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfs/nfs3proc.c linux-2.5.8-pre2/fs/nfs/nfs3proc.c
--- linux-2.5.8-pre1/fs/nfs/nfs3proc.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/nfs/nfs3proc.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfs/nfs3xdr.c linux-2.5.8-pre2/fs/nfs/nfs3xdr.c
--- linux-2.5.8-pre1/fs/nfs/nfs3xdr.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/nfs/nfs3xdr.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfs/proc.c linux-2.5.8-pre2/fs/nfs/proc.c
--- linux-2.5.8-pre1/fs/nfs/proc.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/fs/nfs/proc.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfsd/export.c linux-2.5.8-pre2/fs/nfsd/export.c
--- linux-2.5.8-pre1/fs/nfsd/export.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/fs/nfsd/export.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfsd/lockd.c linux-2.5.8-pre2/fs/nfsd/lockd.c
--- linux-2.5.8-pre1/fs/nfsd/lockd.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/fs/nfsd/lockd.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfsd/nfs3proc.c linux-2.5.8-pre2/fs/nfsd/nfs3proc.c
--- linux-2.5.8-pre1/fs/nfsd/nfs3proc.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/fs/nfsd/nfs3proc.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfsd/nfs3xdr.c linux-2.5.8-pre2/fs/nfsd/nfs3xdr.c
--- linux-2.5.8-pre1/fs/nfsd/nfs3xdr.c	Mon Mar 18 12:37:01 2002
+++ linux-2.5.8-pre2/fs/nfsd/nfs3xdr.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfsd/nfsfh.c linux-2.5.8-pre2/fs/nfsd/nfsfh.c
--- linux-2.5.8-pre1/fs/nfsd/nfsfh.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/fs/nfsd/nfsfh.c	Fri Apr  5 16:59:31 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);
@@ -546,6 +546,9 @@
 
 	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;
 		ino_t xino = 0;
diff -urN linux-2.5.8-pre1/fs/nfsd/nfsproc.c linux-2.5.8-pre2/fs/nfsd/nfsproc.c
--- linux-2.5.8-pre1/fs/nfsd/nfsproc.c	Mon Mar 18 12:37:11 2002
+++ linux-2.5.8-pre2/fs/nfsd/nfsproc.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfsd/nfssvc.c linux-2.5.8-pre2/fs/nfsd/nfssvc.c
--- linux-2.5.8-pre1/fs/nfsd/nfssvc.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/nfsd/nfssvc.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfsd/nfsxdr.c linux-2.5.8-pre2/fs/nfsd/nfsxdr.c
--- linux-2.5.8-pre1/fs/nfsd/nfsxdr.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/nfsd/nfsxdr.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nfsd/stats.c linux-2.5.8-pre2/fs/nfsd/stats.c
--- linux-2.5.8-pre1/fs/nfsd/stats.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/fs/nfsd/stats.c	Fri Apr  5 16:59:31 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 -urN linux-2.5.8-pre1/fs/nls/nls_base.c linux-2.5.8-pre2/fs/nls/nls_base.c
--- linux-2.5.8-pre1/fs/nls/nls_base.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/nls/nls_base.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_big5.c linux-2.5.8-pre2/fs/nls/nls_big5.c
--- linux-2.5.8-pre1/fs/nls/nls_big5.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/fs/nls/nls_big5.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp1251.c linux-2.5.8-pre2/fs/nls/nls_cp1251.c
--- linux-2.5.8-pre1/fs/nls/nls_cp1251.c	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp1251.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp1255.c linux-2.5.8-pre2/fs/nls/nls_cp1255.c
--- linux-2.5.8-pre1/fs/nls/nls_cp1255.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp1255.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp437.c linux-2.5.8-pre2/fs/nls/nls_cp437.c
--- linux-2.5.8-pre1/fs/nls/nls_cp437.c	Mon Mar 18 12:37:19 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp437.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp737.c linux-2.5.8-pre2/fs/nls/nls_cp737.c
--- linux-2.5.8-pre1/fs/nls/nls_cp737.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp737.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp775.c linux-2.5.8-pre2/fs/nls/nls_cp775.c
--- linux-2.5.8-pre1/fs/nls/nls_cp775.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp775.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp850.c linux-2.5.8-pre2/fs/nls/nls_cp850.c
--- linux-2.5.8-pre1/fs/nls/nls_cp850.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp850.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp852.c linux-2.5.8-pre2/fs/nls/nls_cp852.c
--- linux-2.5.8-pre1/fs/nls/nls_cp852.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp852.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp855.c linux-2.5.8-pre2/fs/nls/nls_cp855.c
--- linux-2.5.8-pre1/fs/nls/nls_cp855.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp855.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp857.c linux-2.5.8-pre2/fs/nls/nls_cp857.c
--- linux-2.5.8-pre1/fs/nls/nls_cp857.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp857.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp860.c linux-2.5.8-pre2/fs/nls/nls_cp860.c
--- linux-2.5.8-pre1/fs/nls/nls_cp860.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp860.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp861.c linux-2.5.8-pre2/fs/nls/nls_cp861.c
--- linux-2.5.8-pre1/fs/nls/nls_cp861.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp861.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp862.c linux-2.5.8-pre2/fs/nls/nls_cp862.c
--- linux-2.5.8-pre1/fs/nls/nls_cp862.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp862.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp863.c linux-2.5.8-pre2/fs/nls/nls_cp863.c
--- linux-2.5.8-pre1/fs/nls/nls_cp863.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp863.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp864.c linux-2.5.8-pre2/fs/nls/nls_cp864.c
--- linux-2.5.8-pre1/fs/nls/nls_cp864.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp864.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp865.c linux-2.5.8-pre2/fs/nls/nls_cp865.c
--- linux-2.5.8-pre1/fs/nls/nls_cp865.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp865.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp866.c linux-2.5.8-pre2/fs/nls/nls_cp866.c
--- linux-2.5.8-pre1/fs/nls/nls_cp866.c	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp866.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp869.c linux-2.5.8-pre2/fs/nls/nls_cp869.c
--- linux-2.5.8-pre1/fs/nls/nls_cp869.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp869.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp874.c linux-2.5.8-pre2/fs/nls/nls_cp874.c
--- linux-2.5.8-pre1/fs/nls/nls_cp874.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp874.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp932.c linux-2.5.8-pre2/fs/nls/nls_cp932.c
--- linux-2.5.8-pre1/fs/nls/nls_cp932.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp932.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp936.c linux-2.5.8-pre2/fs/nls/nls_cp936.c
--- linux-2.5.8-pre1/fs/nls/nls_cp936.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp936.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp949.c linux-2.5.8-pre2/fs/nls/nls_cp949.c
--- linux-2.5.8-pre1/fs/nls/nls_cp949.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp949.c	Fri Apr  5 16:59:32 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 -urN linux-2.5.8-pre1/fs/nls/nls_cp950.c linux-2.5.8-pre2/fs/nls/nls_cp950.c
--- linux-2.5.8-pre1/fs/nls/nls_cp950.c	Mon Mar 18 12:37:19 2002
+++ linux-2.5.8-pre2/fs/nls/nls_cp950.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_euc-jp.c linux-2.5.8-pre2/fs/nls/nls_euc-jp.c
--- linux-2.5.8-pre1/fs/nls/nls_euc-jp.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/nls/nls_euc-jp.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_euc-kr.c linux-2.5.8-pre2/fs/nls/nls_euc-kr.c
--- linux-2.5.8-pre1/fs/nls/nls_euc-kr.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/fs/nls/nls_euc-kr.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_gb2312.c linux-2.5.8-pre2/fs/nls/nls_gb2312.c
--- linux-2.5.8-pre1/fs/nls/nls_gb2312.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/fs/nls/nls_gb2312.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_iso8859-1.c linux-2.5.8-pre2/fs/nls/nls_iso8859-1.c
--- linux-2.5.8-pre1/fs/nls/nls_iso8859-1.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/nls/nls_iso8859-1.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_iso8859-13.c linux-2.5.8-pre2/fs/nls/nls_iso8859-13.c
--- linux-2.5.8-pre1/fs/nls/nls_iso8859-13.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/fs/nls/nls_iso8859-13.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_iso8859-14.c linux-2.5.8-pre2/fs/nls/nls_iso8859-14.c
--- linux-2.5.8-pre1/fs/nls/nls_iso8859-14.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/fs/nls/nls_iso8859-14.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_iso8859-15.c linux-2.5.8-pre2/fs/nls/nls_iso8859-15.c
--- linux-2.5.8-pre1/fs/nls/nls_iso8859-15.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/fs/nls/nls_iso8859-15.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_iso8859-2.c linux-2.5.8-pre2/fs/nls/nls_iso8859-2.c
--- linux-2.5.8-pre1/fs/nls/nls_iso8859-2.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/fs/nls/nls_iso8859-2.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_iso8859-3.c linux-2.5.8-pre2/fs/nls/nls_iso8859-3.c
--- linux-2.5.8-pre1/fs/nls/nls_iso8859-3.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/fs/nls/nls_iso8859-3.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_iso8859-4.c linux-2.5.8-pre2/fs/nls/nls_iso8859-4.c
--- linux-2.5.8-pre1/fs/nls/nls_iso8859-4.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/nls/nls_iso8859-4.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_iso8859-5.c linux-2.5.8-pre2/fs/nls/nls_iso8859-5.c
--- linux-2.5.8-pre1/fs/nls/nls_iso8859-5.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/fs/nls/nls_iso8859-5.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_iso8859-6.c linux-2.5.8-pre2/fs/nls/nls_iso8859-6.c
--- linux-2.5.8-pre1/fs/nls/nls_iso8859-6.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/fs/nls/nls_iso8859-6.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_iso8859-7.c linux-2.5.8-pre2/fs/nls/nls_iso8859-7.c
--- linux-2.5.8-pre1/fs/nls/nls_iso8859-7.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/fs/nls/nls_iso8859-7.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_iso8859-8.c linux-2.5.8-pre2/fs/nls/nls_iso8859-8.c
--- linux-2.5.8-pre1/fs/nls/nls_iso8859-8.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/fs/nls/nls_iso8859-8.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_iso8859-9.c linux-2.5.8-pre2/fs/nls/nls_iso8859-9.c
--- linux-2.5.8-pre1/fs/nls/nls_iso8859-9.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/fs/nls/nls_iso8859-9.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_koi8-r.c linux-2.5.8-pre2/fs/nls/nls_koi8-r.c
--- linux-2.5.8-pre1/fs/nls/nls_koi8-r.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/fs/nls/nls_koi8-r.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_koi8-ru.c linux-2.5.8-pre2/fs/nls/nls_koi8-ru.c
--- linux-2.5.8-pre1/fs/nls/nls_koi8-ru.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/fs/nls/nls_koi8-ru.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_koi8-u.c linux-2.5.8-pre2/fs/nls/nls_koi8-u.c
--- linux-2.5.8-pre1/fs/nls/nls_koi8-u.c	Mon Mar 18 12:37:19 2002
+++ linux-2.5.8-pre2/fs/nls/nls_koi8-u.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_sjis.c linux-2.5.8-pre2/fs/nls/nls_sjis.c
--- linux-2.5.8-pre1/fs/nls/nls_sjis.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/fs/nls/nls_sjis.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_tis-620.c linux-2.5.8-pre2/fs/nls/nls_tis-620.c
--- linux-2.5.8-pre1/fs/nls/nls_tis-620.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/fs/nls/nls_tis-620.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/nls/nls_utf8.c linux-2.5.8-pre2/fs/nls/nls_utf8.c
--- linux-2.5.8-pre1/fs/nls/nls_utf8.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/fs/nls/nls_utf8.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/ntfs/Makefile linux-2.5.8-pre2/fs/ntfs/Makefile
--- linux-2.5.8-pre1/fs/ntfs/Makefile	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/fs/ntfs/Makefile	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/ntfs/support.h linux-2.5.8-pre2/fs/ntfs/support.h
--- linux-2.5.8-pre1/fs/ntfs/support.h	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/ntfs/support.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/open.c linux-2.5.8-pre2/fs/open.c
--- linux-2.5.8-pre1/fs/open.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/open.c	Fri Apr  5 16:59:33 2002
@@ -73,20 +73,15 @@
 
 int do_truncate(struct dentry *dentry, loff_t length)
 {
-	struct inode *inode = dentry->d_inode;
-	int error;
 	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;
+	return notify_change(dentry, &newattrs);
 }
 
 static inline long do_sys_truncate(const char * path, loff_t length)
diff -urN linux-2.5.8-pre1/fs/partitions/efi.c linux-2.5.8-pre2/fs/partitions/efi.c
--- linux-2.5.8-pre1/fs/partitions/efi.c	Fri Apr  5 16:59:20 2002
+++ linux-2.5.8-pre2/fs/partitions/efi.c	Fri Apr  5 16:59:33 2002
@@ -23,6 +23,19 @@
  * 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
  *
@@ -98,10 +111,8 @@
 /* Borrowed from /usr/include/inttypes.h */
 # if BITS_PER_LONG == 64 
 #  define __PRI64_PREFIX	"l"
-#  define __PRIPTR_PREFIX	"l"
 # else
 #  define __PRI64_PREFIX	"ll"
-#  define __PRIPTR_PREFIX
 # endif
 # define PRIx64		__PRI64_PREFIX "x"
 
@@ -117,35 +128,15 @@
  * the test for invalid PMBR.  Not __initdata because reloading
  * the partition tables happens after init too.
  */
-static int forcegpt;
+static int force_gpt;
 static int __init
-force_gpt(char *str)
+force_gpt_fn(char *str)
 {
-	forcegpt = 1;
+	force_gpt = 1;
 	return 1;
 }
+__setup("gpt", force_gpt_fn);
 
-__setup("gpt", force_gpt);
-
-/**
- * le_efi_guid_to_cpus()
- * @guid
- *
- * Description: modifies @guid in situ
- *
- * This function converts a little endian efi_guid_t to the
- * native cpu representation.  The EFI Spec. declares that all 
- * on-disk structures are stored in little endian format.
- */
-static void
-le_efi_guid_to_cpus(efi_guid_t *guid)
-{
-	le32_to_cpus(guid->data1);
-	le16_to_cpus(guid->data2);
-	le16_to_cpus(guid->data3);
-	/* no need to change the rest. It's already an array of chars */
-	return;
-}
 
 /**
  * efi_crc32() - EFI version of crc32 function
@@ -166,21 +157,6 @@
 }
 
 /**
- * le_part_attributes_to_cpus(): converts LE attributes to CPU type in situ
- * @attributes - ptr to partition attributes
- * 
- * Description:  modifies attributes in situ, returns nothing.
- * Converts a little endian partition attributes struct to the
- * native cpu representation.  Good for reading attributes off of a disk.
- */
-static void
-le_part_attributes_to_cpus(gpt_entry_attributes * a)
-{
-	u64 *b = (u64 *) a;
-	*b = le64_to_cpu(*b);
-}
-
-/**
  * is_pmbr_valid(): test Protective MBR for validity
  * @mbr: pointer to a legacy mbr structure
  *
@@ -197,7 +173,8 @@
 		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) {
+		if (mbr->partition_record[i].sys_ind ==
+                    EFI_PMBR_OSTYPE_EFI_GPT) {
 			found = 1;
 			break;
 		}
@@ -272,37 +249,6 @@
 	return totalreadcount;
 }
 
-/**
- * print_gpt_header(): unparses gpt header to console
- * @gpt: gpt header
- */
-static void
-print_gpt_header(gpt_header *gpt)
-{
-	Dprintk("GUID Partition Table Header\n");
-	if (!gpt)
-		return;
-	Dprintk("signature                   : %" PRIx64 "\n", gpt->signature);
-	Dprintk("revision                    : %x\n", gpt->revision);
-	Dprintk("header_size                 : %x\n", gpt->header_size);
-	Dprintk("header_crc32                : %x\n", gpt->header_crc32);
-	Dprintk("my_lba                      : %" PRIx64 "\n", gpt->my_lba);
-	Dprintk("alternate_lba               : %" PRIx64 "\n",
-		gpt->alternate_lba);
-	Dprintk("first_usable_lba            : %" PRIx64 "\n",
-		gpt->first_usable_lba);
-	Dprintk("last_usable_lba             : %" PRIx64 "\n",
-		gpt->last_usable_lba);
-	Dprintk("partition_entry_lba         : %" PRIx64 "\n",
-		gpt->partition_entry_lba);
-	Dprintk("num_partition_entries       : %x\n",
-		gpt->num_partition_entries);
-	Dprintk("sizeof_partition_entry      : %x\n",
-		gpt->sizeof_partition_entry);
-	Dprintk("partition_entry_array_crc32 : %x\n",
-		gpt->partition_entry_array_crc32);
-	return;
-}
 
 /**
  * alloc_read_gpt_entries(): reads partition entries from disk
@@ -318,13 +264,13 @@
 alloc_read_gpt_entries(struct gendisk *hd,
 		       struct block_device *bdev, gpt_header *gpt)
 {
-	u32 i, j;
 	size_t count;
 	gpt_entry *pte;
 	if (!hd || !bdev || !gpt)
 		return NULL;
 
-	count = gpt->num_partition_entries * gpt->sizeof_partition_entry;
+	count = le32_to_cpu(gpt->num_partition_entries) *
+                le32_to_cpu(gpt->sizeof_partition_entry);
 	if (!count)
 		return NULL;
 	pte = kmalloc(count, GFP_KERNEL);
@@ -332,23 +278,13 @@
 		return NULL;
 	memset(pte, 0, count);
 
-	if (read_lba(hd, bdev, gpt->partition_entry_lba, (u8 *) pte,
+	if (read_lba(hd, bdev, le64_to_cpu(gpt->partition_entry_lba),
+                     (u8 *) pte,
 		     count) < count) {
 		kfree(pte);
+                pte=NULL;
 		return NULL;
 	}
-	/* Fixup endianness */
-	for (i = 0; i < gpt->num_partition_entries; i++) {
-		le_efi_guid_to_cpus(&pte[i].partition_type_guid);
-		le_efi_guid_to_cpus(&pte[i].unique_partition_guid);
-		le64_to_cpus(pte[i].starting_lba);
-		le64_to_cpus(pte[i].ending_lba);
-		le_part_attributes_to_cpus(&pte[i].attributes);
-		for (j = 0; j < (72 / sizeof (efi_char16_t)); j++) {
-			le16_to_cpus((u16) (pte[i].partition_name[j]));
-		}
-	}
-
 	return pte;
 }
 
@@ -377,27 +313,10 @@
 	if (read_lba(hd, bdev, lba, (u8 *) gpt,
 		     sizeof (gpt_header)) < sizeof (gpt_header)) {
 		kfree(gpt);
+                gpt=NULL;
 		return NULL;
 	}
 
-	/* Fixup endianness */
-	le64_to_cpus(gpt->signature);
-	le32_to_cpus(gpt->revision);
-	le32_to_cpus(gpt->header_size);
-	le32_to_cpus(gpt->header_crc32);
-	le32_to_cpus(gpt->reserved1);
-	le64_to_cpus(gpt->my_lba);
-	le64_to_cpus(gpt->alternate_lba);
-	le64_to_cpus(gpt->first_usable_lba);
-	le64_to_cpus(gpt->last_usable_lba);
-	le_efi_guid_to_cpus(&gpt->disk_guid);
-	le64_to_cpus(gpt->partition_entry_lba);
-	le32_to_cpus(gpt->num_partition_entries);
-	le32_to_cpus(gpt->sizeof_partition_entry);
-	le32_to_cpus(gpt->partition_entry_array_crc32);
-
-	print_gpt_header(gpt);
-
 	return gpt;
 }
 
@@ -424,9 +343,9 @@
 		return 0;
 
 	/* Check the GUID Partition Table signature */
-	if ((*gpt)->signature != GPT_HEADER_SIGNATURE) {
+	if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
 		Dprintk("GUID Partition Table Header signature is wrong: %"
-			PRIx64 " != %" PRIx64 "\n", (*gpt)->signature,
+			PRIx64 " != %" PRIx64 "\n", le64_to_cpu((*gpt)->signature),
 			GPT_HEADER_SIGNATURE);
 		kfree(*gpt);
 		*gpt = NULL;
@@ -434,25 +353,25 @@
 	}
 
 	/* Check the GUID Partition Table CRC */
-	origcrc = (*gpt)->header_crc32;
+	origcrc = le32_to_cpu((*gpt)->header_crc32);
 	(*gpt)->header_crc32 = 0;
-	crc = efi_crc32((const unsigned char *) (*gpt), (*gpt)->header_size);
+	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",
-		     (*gpt)->header_crc32, origcrc);
+		     crc, origcrc);
 		kfree(*gpt);
 		*gpt = NULL;
 		return 0;
 	}
-	(*gpt)->header_crc32 = origcrc;
+	(*gpt)->header_crc32 = cpu_to_le32(origcrc);
 
 	/* Check that the my_lba entry points to the LBA that contains
 	 * the GUID Partition Table */
-	if ((*gpt)->my_lba != lba) {
+	if (le64_to_cpu((*gpt)->my_lba) != lba) {
 		Dprintk("GPT my_lba incorrect: %" PRIx64 " != %" PRIx64 "\n",
-			(*gpt)->my_lba, lba);
+			le64_to_cpu((*gpt)->my_lba), lba);
 		kfree(*gpt);
 		*gpt = NULL;
 		return 0;
@@ -466,10 +385,10 @@
 
 	/* Check the GUID Partition Entry Array CRC */
 	crc = efi_crc32((const unsigned char *) (*ptes),
-			(*gpt)->num_partition_entries *
-			(*gpt)->sizeof_partition_entry);
+			le32_to_cpu((*gpt)->num_partition_entries) *
+			le32_to_cpu((*gpt)->sizeof_partition_entry));
 
-	if (crc != (*gpt)->partition_entry_array_crc32) {
+	if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
 		Dprintk("GUID Partitition Entry Array CRC check failed.\n");
 		kfree(*gpt);
 		*gpt = NULL;
@@ -497,71 +416,81 @@
 	int error_found = 0;
 	if (!pgpt || !agpt)
 		return;
-	if (pgpt->my_lba != agpt->alternate_lba) {
+	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",
-		       pgpt->my_lba, agpt->alternate_lba);
+		       le64_to_cpu(pgpt->my_lba),
+                       le64_to_cpu(agpt->alternate_lba));
 		error_found++;
 	}
-	if (pgpt->alternate_lba != agpt->my_lba) {
+	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",
-		       pgpt->alternate_lba, agpt->my_lba);
+		       le64_to_cpu(pgpt->alternate_lba),
+                       le64_to_cpu(agpt->my_lba));
 		error_found++;
 	}
-	if (pgpt->first_usable_lba != agpt->first_usable_lba) {
+	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",
-		       pgpt->first_usable_lba, agpt->first_usable_lba);
+		       le64_to_cpu(pgpt->first_usable_lba),
+                       le64_to_cpu(agpt->first_usable_lba));
 		error_found++;
 	}
-	if (pgpt->last_usable_lba != agpt->last_usable_lba) {
+	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",
-		       pgpt->last_usable_lba, agpt->last_usable_lba);
+		       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 (pgpt->num_partition_entries != agpt->num_partition_entries) {
+	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",
-		       pgpt->num_partition_entries,
-		       agpt->num_partition_entries);
+		       le32_to_cpu(pgpt->num_partition_entries),
+		       le32_to_cpu(agpt->num_partition_entries));
 		error_found++;
 	}
-	if (pgpt->sizeof_partition_entry != agpt->sizeof_partition_entry) {
+	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", pgpt->sizeof_partition_entry,
-		       agpt->sizeof_partition_entry);
+		       "0x%x != 0x%x\n",
+                       le32_to_cpu(pgpt->sizeof_partition_entry),
+		       le32_to_cpu(agpt->sizeof_partition_entry));
 		error_found++;
 	}
-	if (pgpt->partition_entry_array_crc32 !=
-	    agpt->partition_entry_array_crc32) {
+	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", pgpt->partition_entry_array_crc32,
-		       agpt->partition_entry_array_crc32);
+		       "0x%x != 0x%x\n",
+                       le32_to_cpu(pgpt->partition_entry_array_crc32),
+		       le32_to_cpu(agpt->partition_entry_array_crc32));
 		error_found++;
 	}
-	if (pgpt->alternate_lba != lastlba) {
+	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",
-		       pgpt->alternate_lba, lastlba);
+		       le64_to_cpu(pgpt->alternate_lba), lastlba);
 		error_found++;
 	}
 
-	if (agpt->my_lba != lastlba) {
+	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",
-		       agpt->my_lba, lastlba);
+		       le64_to_cpu(agpt->my_lba), lastlba);
 		error_found++;
 	}
 
@@ -595,98 +524,95 @@
 		return 0;
 
 	lastlba = last_lba(hd, bdev);
-	/* Check the Primary GPT */
 	good_pgpt = is_gpt_valid(hd, bdev, GPT_PRIMARY_PARTITION_TABLE_LBA,
 				 &pgpt, &pptes);
-	if (good_pgpt) {
-		/* Primary GPT is OK, check the alternate and warn if bad */
-		good_agpt = is_gpt_valid(hd, bdev, pgpt->alternate_lba,
+        if (good_pgpt) {
+		good_agpt = is_gpt_valid(hd, bdev,
+                                         le64_to_cpu(pgpt->alternate_lba),
 					 &agpt, &aptes);
-		if (!good_agpt) {
-			printk(KERN_WARNING
-			       "Alternate GPT is invalid, using primary GPT.\n");
-		}
-
-		compare_gpts(pgpt, agpt, lastlba);
-
-		*gpt = pgpt;
-		*ptes = pptes;
-		if (agpt) {
-			kfree(agpt);
-			agpt = NULL;
-		}
-		if (aptes) {
-			kfree(aptes);
-			aptes = NULL;
-		}
-	} /* if primary is valid */
-	else {
-		/* Primary GPT is bad, check the Alternate GPT */
-		good_agpt = is_gpt_valid(hd, bdev, lastlba, &agpt, &aptes);
-		if (good_agpt) {
-			/* Primary is bad, alternate is good.
-			   Return values from the alternate and warn.
-			 */
-			printk(KERN_WARNING
-			       "Primary GPT is invalid, using alternate GPT.\n");
-			*gpt = agpt;
-			*ptes = 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;
+        }
 
-	/* Now test for valid PMBR */
 	/* This will be added to the EFI Spec. per Intel after v1.02. */
-	if (good_pgpt || good_agpt) {
-		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);
-		}
-		if (good_pmbr)
-			return 1;
-		if (!forcegpt) {
-			printk
-			    (" 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");
-		} else {
-			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");
-			return 1;
-		}
-	}
-
-	/* Both primary and alternate GPTs are bad, and/or PMBR is invalid.
-	 * This isn't our disk, return 0.
-	 */
-	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;
+        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;
 }
 
 /**
@@ -710,49 +636,50 @@
 {
 	gpt_header *gpt = NULL;
 	gpt_entry *ptes = NULL;
-	u32 i, nummade = 0;
+	u32 i;
 	int max_p; 
 
-	efi_guid_t unusedGuid = UNUSED_ENTRY_GUID;
-#if CONFIG_BLK_DEV_MD
-	efi_guid_t raidGuid = PARTITION_LINUX_RAID_GUID;
-#endif
-
 	if (!hd || !bdev)
 		return -1;
 
 	if (!find_valid_gpt(hd, bdev, &gpt, &ptes) || !gpt || !ptes) {
-		if (gpt)
+		if (gpt) {
 			kfree(gpt);
-		if (ptes)
+                        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 < gpt->num_partition_entries && nummade < max_p; i++) {
-		if (!efi_guidcmp(unusedGuid, ptes[i].partition_type_guid))
+	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, ptes[i].starting_lba,
-				 (ptes[i].ending_lba - ptes[i].starting_lba +
+		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(raidGuid, ptes[i].partition_type_guid)) {
+		if (!efi_guidcmp(ptes[i].partition_type_guid,
+                                 PARTITION_LINUX_RAID_GUID)) {
 			md_autodetect_dev(mk_kdev(hd->major,
                                                   nextminor));
 		}
 #endif
-		nummade++;
-		nextminor++;
-
 	}
 	kfree(ptes);
+        ptes=NULL;
 	kfree(gpt);
+        gpt=NULL;
 	printk("\n");
 	return 1;
 }
diff -urN linux-2.5.8-pre1/fs/partitions/efi.h linux-2.5.8-pre2/fs/partitions/efi.h
--- linux-2.5.8-pre1/fs/partitions/efi.h	Fri Apr  5 16:59:20 2002
+++ linux-2.5.8-pre2/fs/partitions/efi.h	Fri Apr  5 16:59:33 2002
@@ -48,22 +48,27 @@
 #define GPT_HEADER_REVISION_V1 0x00010000
 #define GPT_PRIMARY_PARTITION_TABLE_LBA 1
 
-#define UNUSED_ENTRY_GUID    \
-    ((efi_guid_t) { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }})
 #define PARTITION_SYSTEM_GUID \
-((efi_guid_t) { 0xC12A7328, 0xF81F, 0x11d2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }})
+    EFI_GUID( 0xC12A7328, 0xF81F, 0x11d2, \
+              0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B) 
 #define LEGACY_MBR_PARTITION_GUID \
-    ((efi_guid_t) { 0x024DEE41, 0x33E7, 0x11d3, { 0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F }})
+    EFI_GUID( 0x024DEE41, 0x33E7, 0x11d3, \
+              0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F)
 #define PARTITION_MSFT_RESERVED_GUID \
-    ((efi_guid_t) { 0xE3C9E316, 0x0B5C, 0x4DB8, { 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }})
+    EFI_GUID( 0xE3C9E316, 0x0B5C, 0x4DB8, \
+              0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE)
 #define PARTITION_BASIC_DATA_GUID \
-    ((efi_guid_t) { 0xEBD0A0A2, 0xB9E5, 0x4433, { 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }})
+    EFI_GUID( 0xEBD0A0A2, 0xB9E5, 0x4433, \
+              0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7)
 #define PARTITION_LINUX_RAID_GUID \
-    ((efi_guid_t) { 0xa19d880f, 0x05fc, 0x4d3b, { 0xa0, 0x06, 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e  }})
+    EFI_GUID( 0xa19d880f, 0x05fc, 0x4d3b, \
+              0xa0, 0x06, 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e)
 #define PARTITION_LINUX_SWAP_GUID \
-    ((efi_guid_t) { 0x0657fd6d, 0xa4ab, 0x43c4, { 0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f  }})
+    EFI_GUID( 0x0657fd6d, 0xa4ab, 0x43c4, \
+              0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f)
 #define PARTITION_LINUX_LVM_GUID \
-    ((efi_guid_t) { 0xe6d6d379, 0xf507, 0x44c2, { 0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28 }})
+    EFI_GUID( 0xe6d6d379, 0xf507, 0x44c2, \
+              0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)
 
 typedef struct _gpt_header {
 	u64 signature;
diff -urN linux-2.5.8-pre1/fs/proc/generic.c linux-2.5.8-pre2/fs/proc/generic.c
--- linux-2.5.8-pre1/fs/proc/generic.c	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/fs/proc/generic.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/qnx4/BUGS linux-2.5.8-pre2/fs/qnx4/BUGS
--- linux-2.5.8-pre1/fs/qnx4/BUGS	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/fs/qnx4/BUGS	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 -urN linux-2.5.8-pre1/fs/qnx4/TODO linux-2.5.8-pre2/fs/qnx4/TODO
--- linux-2.5.8-pre1/fs/qnx4/TODO	Mon Mar 18 12:37:19 2002
+++ linux-2.5.8-pre2/fs/qnx4/TODO	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 -urN linux-2.5.8-pre1/fs/reiserfs/do_balan.c linux-2.5.8-pre2/fs/reiserfs/do_balan.c
--- linux-2.5.8-pre1/fs/reiserfs/do_balan.c	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/fs/reiserfs/do_balan.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/reiserfs/file.c linux-2.5.8-pre2/fs/reiserfs/file.c
--- linux-2.5.8-pre1/fs/reiserfs/file.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/reiserfs/file.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/reiserfs/fix_node.c linux-2.5.8-pre2/fs/reiserfs/fix_node.c
--- linux-2.5.8-pre1/fs/reiserfs/fix_node.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/fs/reiserfs/fix_node.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/reiserfs/ibalance.c linux-2.5.8-pre2/fs/reiserfs/ibalance.c
--- linux-2.5.8-pre1/fs/reiserfs/ibalance.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/fs/reiserfs/ibalance.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/reiserfs/inode.c linux-2.5.8-pre2/fs/reiserfs/inode.c
--- linux-2.5.8-pre1/fs/reiserfs/inode.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/fs/reiserfs/inode.c	Fri Apr  5 16:59:33 2002
@@ -1176,7 +1176,7 @@
        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", 
@@ -1289,7 +1289,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 +1515,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
diff -urN linux-2.5.8-pre1/fs/reiserfs/item_ops.c linux-2.5.8-pre2/fs/reiserfs/item_ops.c
--- linux-2.5.8-pre1/fs/reiserfs/item_ops.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/fs/reiserfs/item_ops.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/reiserfs/namei.c linux-2.5.8-pre2/fs/reiserfs/namei.c
--- linux-2.5.8-pre1/fs/reiserfs/namei.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/fs/reiserfs/namei.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/reiserfs/prints.c linux-2.5.8-pre2/fs/reiserfs/prints.c
--- linux-2.5.8-pre1/fs/reiserfs/prints.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/fs/reiserfs/prints.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/reiserfs/procfs.c linux-2.5.8-pre2/fs/reiserfs/procfs.c
--- linux-2.5.8-pre1/fs/reiserfs/procfs.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/fs/reiserfs/procfs.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/reiserfs/stree.c linux-2.5.8-pre2/fs/reiserfs/stree.c
--- linux-2.5.8-pre1/fs/reiserfs/stree.c	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/fs/reiserfs/stree.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/reiserfs/super.c linux-2.5.8-pre2/fs/reiserfs/super.c
--- linux-2.5.8-pre1/fs/reiserfs/super.c	Fri Apr  5 16:59:21 2002
+++ linux-2.5.8-pre2/fs/reiserfs/super.c	Fri Apr  5 16:59:33 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;
 }
 
@@ -614,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 ;
@@ -1002,10 +1006,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;
     }
 
@@ -1022,8 +1032,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");
@@ -1069,8 +1079,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 ;
@@ -1078,9 +1088,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)) {
 
@@ -1105,8 +1115,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") ;
 	  }
@@ -1125,7 +1135,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 );
@@ -1135,7 +1145,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;
 
@@ -1154,6 +1164,9 @@
     if (SB_BUFFER_WITH_SB (s))
 	brelse(SB_BUFFER_WITH_SB (s));
 
+    kfree(sbi);
+    s->u.generic_sbp = NULL;
+
     return -EINVAL;
 }
 
diff -urN linux-2.5.8-pre1/fs/reiserfs/tail_conversion.c linux-2.5.8-pre2/fs/reiserfs/tail_conversion.c
--- linux-2.5.8-pre1/fs/reiserfs/tail_conversion.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/fs/reiserfs/tail_conversion.c	Fri Apr  5 16:59:33 2002
@@ -35,7 +35,7 @@
 				       tree. */
 
 
-    sb->u.reiserfs_sb.s_direct2indirect ++;
+    REISERFS_SB(sb)->s_direct2indirect ++;
 
     n_blk_size = sb->s_blocksize;
 
@@ -202,7 +202,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 -urN linux-2.5.8-pre1/fs/smbfs/inode.c linux-2.5.8-pre2/fs/smbfs/inode.c
--- linux-2.5.8-pre1/fs/smbfs/inode.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/fs/smbfs/inode.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/smbfs/proc.c linux-2.5.8-pre2/fs/smbfs/proc.c
--- linux-2.5.8-pre1/fs/smbfs/proc.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/fs/smbfs/proc.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/fs/umsdos/inode.c linux-2.5.8-pre2/fs/umsdos/inode.c
--- linux-2.5.8-pre1/fs/umsdos/inode.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/fs/umsdos/inode.c	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-alpha/cacheflush.h linux-2.5.8-pre2/include/asm-alpha/cacheflush.h
--- linux-2.5.8-pre1/include/asm-alpha/cacheflush.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-alpha/cacheflush.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-alpha/pgalloc.h linux-2.5.8-pre2/include/asm-alpha/pgalloc.h
--- linux-2.5.8-pre1/include/asm-alpha/pgalloc.h	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/include/asm-alpha/pgalloc.h	Fri Apr  5 16:59:33 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
@@ -292,4 +70,6 @@
 	__free_page(page);
 }
 
+#define check_pgt_cache()	do { } while (0)
+
 #endif /* _ALPHA_PGALLOC_H */
diff -urN linux-2.5.8-pre1/include/asm-alpha/tlbflush.h linux-2.5.8-pre2/include/asm-alpha/tlbflush.h
--- linux-2.5.8-pre1/include/asm-alpha/tlbflush.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-alpha/tlbflush.h	Fri Apr  5 16:59:33 2002
@@ -0,0 +1,155 @@
+#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 */
+
+#endif /* _ALPHA_TLBFLUSH_H */
diff -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/dma.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/dma.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/dma.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/dma.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/hardware.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/hardware.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/hardware.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/hardware.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/ide.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/ide.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/ide.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/ide.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/idp.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/idp.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/idp.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/idp.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/io.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/io.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/io.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/io.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/irq.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/irq.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/irq.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/irq.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/irqs.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/irqs.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/irqs.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/irqs.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/keyboard.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/keyboard.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/keyboard.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/keyboard.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/lubbock.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/lubbock.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/lubbock.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/lubbock.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/memory.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/memory.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/memory.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/memory.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/param.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/param.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/param.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/param.h	Fri Apr  5 16:59:33 2002
@@ -0,0 +1,3 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/param.h
+ */
diff -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/pxa-regs.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/pxa-regs.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/pxa-regs.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/pxa-regs.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/serial.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/serial.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/serial.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/serial.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/system.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/system.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/system.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/system.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/time.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/time.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/time.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/time.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/timex.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/timex.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/timex.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/timex.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/uncompress.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/uncompress.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/uncompress.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/uncompress.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/arch-pxa/vmalloc.h linux-2.5.8-pre2/include/asm-arm/arch-pxa/vmalloc.h
--- linux-2.5.8-pre1/include/asm-arm/arch-pxa/vmalloc.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-arm/arch-pxa/vmalloc.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/cpu-multi32.h linux-2.5.8-pre2/include/asm-arm/cpu-multi32.h
--- linux-2.5.8-pre1/include/asm-arm/cpu-multi32.h	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/include/asm-arm/cpu-multi32.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/cpu-single.h linux-2.5.8-pre2/include/asm-arm/cpu-single.h
--- linux-2.5.8-pre1/include/asm-arm/cpu-single.h	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/include/asm-arm/cpu-single.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/irq.h linux-2.5.8-pre2/include/asm-arm/irq.h
--- linux-2.5.8-pre1/include/asm-arm/irq.h	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/include/asm-arm/irq.h	Fri Apr  5 16:59:33 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);
@@ -38,5 +40,7 @@
 
 int set_irq_type(unsigned int irq, unsigned int type);
 
+int setup_irq(unsigned int, struct irqaction *);
+
 #endif
 
diff -urN linux-2.5.8-pre1/include/asm-arm/leds.h linux-2.5.8-pre2/include/asm-arm/leds.h
--- linux-2.5.8-pre1/include/asm-arm/leds.h	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/include/asm-arm/leds.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/mach/irq.h linux-2.5.8-pre2/include/asm-arm/mach/irq.h
--- linux-2.5.8-pre1/include/asm-arm/mach/irq.h	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/include/asm-arm/mach/irq.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/mach/pci.h linux-2.5.8-pre2/include/asm-arm/mach/pci.h
--- linux-2.5.8-pre1/include/asm-arm/mach/pci.h	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/include/asm-arm/mach/pci.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/mach/serial_sa1100.h linux-2.5.8-pre2/include/asm-arm/mach/serial_sa1100.h
--- linux-2.5.8-pre1/include/asm-arm/mach/serial_sa1100.h	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/include/asm-arm/mach/serial_sa1100.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/mman.h linux-2.5.8-pre2/include/asm-arm/mman.h
--- linux-2.5.8-pre1/include/asm-arm/mman.h	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/include/asm-arm/mman.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/pgalloc.h linux-2.5.8-pre2/include/asm-arm/pgalloc.h
--- linux-2.5.8-pre1/include/asm-arm/pgalloc.h	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/include/asm-arm/pgalloc.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/proc-armv/cache.h linux-2.5.8-pre2/include/asm-arm/proc-armv/cache.h
--- linux-2.5.8-pre1/include/asm-arm/proc-armv/cache.h	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/include/asm-arm/proc-armv/cache.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/proc-armv/domain.h linux-2.5.8-pre2/include/asm-arm/proc-armv/domain.h
--- linux-2.5.8-pre1/include/asm-arm/proc-armv/domain.h	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/include/asm-arm/proc-armv/domain.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/siginfo.h linux-2.5.8-pre2/include/asm-arm/siginfo.h
--- linux-2.5.8-pre1/include/asm-arm/siginfo.h	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/include/asm-arm/siginfo.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-arm/system.h linux-2.5.8-pre2/include/asm-arm/system.h
--- linux-2.5.8-pre1/include/asm-arm/system.h	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/include/asm-arm/system.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-generic/tlb.h linux-2.5.8-pre2/include/asm-generic/tlb.h
--- linux-2.5.8-pre1/include/asm-generic/tlb.h	Mon Mar 18 12:37:01 2002
+++ linux-2.5.8-pre2/include/asm-generic/tlb.h	Fri Apr  5 16:59:33 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 -urN linux-2.5.8-pre1/include/asm-i386/cacheflush.h linux-2.5.8-pre2/include/asm-i386/cacheflush.h
--- linux-2.5.8-pre1/include/asm-i386/cacheflush.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-i386/cacheflush.h	Fri Apr  5 16:59:34 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 -urN linux-2.5.8-pre1/include/asm-i386/highmem.h linux-2.5.8-pre2/include/asm-i386/highmem.h
--- linux-2.5.8-pre1/include/asm-i386/highmem.h	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/include/asm-i386/highmem.h	Fri Apr  5 16:59:34 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 -urN linux-2.5.8-pre1/include/asm-i386/io.h linux-2.5.8-pre2/include/asm-i386/io.h
--- linux-2.5.8-pre1/include/asm-i386/io.h	Fri Apr  5 16:59:21 2002
+++ linux-2.5.8-pre2/include/asm-i386/io.h	Fri Apr  5 16:59:34 2002
@@ -166,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
diff -urN linux-2.5.8-pre1/include/asm-i386/mmu_context.h linux-2.5.8-pre2/include/asm-i386/mmu_context.h
--- linux-2.5.8-pre1/include/asm-i386/mmu_context.h	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/include/asm-i386/mmu_context.h	Fri Apr  5 16:59:34 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 -urN linux-2.5.8-pre1/include/asm-i386/pgalloc.h linux-2.5.8-pre2/include/asm-i386/pgalloc.h
--- linux-2.5.8-pre1/include/asm-i386/pgalloc.h	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/include/asm-i386/pgalloc.h	Fri Apr  5 16:59:34 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)
 {
@@ -144,85 +45,6 @@
 #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)
 
 #endif /* _I386_PGALLOC_H */
diff -urN linux-2.5.8-pre1/include/asm-i386/pgtable.h linux-2.5.8-pre2/include/asm-i386/pgtable.h
--- linux-2.5.8-pre1/include/asm-i386/pgtable.h	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/include/asm-i386/pgtable.h	Fri Apr  5 16:59:34 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..
diff -urN linux-2.5.8-pre1/include/asm-i386/thread_info.h linux-2.5.8-pre2/include/asm-i386/thread_info.h
--- linux-2.5.8-pre1/include/asm-i386/thread_info.h	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/include/asm-i386/thread_info.h	Fri Apr  5 16:59:34 2002
@@ -47,6 +47,8 @@
 
 #endif
 
+#define PREEMPT_ACTIVE		0x4000000
+
 /*
  * macros/functions for gaining access to the thread information structure
  */
diff -urN linux-2.5.8-pre1/include/asm-i386/tlbflush.h linux-2.5.8-pre2/include/asm-i386/tlbflush.h
--- linux-2.5.8-pre1/include/asm-i386/tlbflush.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/asm-i386/tlbflush.h	Fri Apr  5 16:59:34 2002
@@ -0,0 +1,141 @@
+#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_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 */
+}
+
+#endif /* _I386_TLBFLUSH_H */
diff -urN linux-2.5.8-pre1/include/asm-ia64/efi.h linux-2.5.8-pre2/include/asm-ia64/efi.h
--- linux-2.5.8-pre1/include/asm-ia64/efi.h	Mon Mar 18 12:37:15 2002
+++ linux-2.5.8-pre2/include/asm-ia64/efi.h	Fri Apr  5 16:59:34 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;
@@ -233,6 +240,17 @@
 	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);
 extern void efi_map_pal_code (void);
 extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
diff -urN linux-2.5.8-pre1/include/asm-ia64/sal.h linux-2.5.8-pre2/include/asm-ia64/sal.h
--- linux-2.5.8-pre1/include/asm-ia64/sal.h	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/include/asm-ia64/sal.h	Fri Apr  5 16:59:34 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 -urN linux-2.5.8-pre1/include/asm-sparc64/pgtable.h linux-2.5.8-pre2/include/asm-sparc64/pgtable.h
--- linux-2.5.8-pre1/include/asm-sparc64/pgtable.h	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/include/asm-sparc64/pgtable.h	Fri Apr  5 16:59:34 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 -urN linux-2.5.8-pre1/include/linux/device.h linux-2.5.8-pre2/include/linux/device.h
--- linux-2.5.8-pre1/include/linux/device.h	Fri Apr  5 16:59:21 2002
+++ linux-2.5.8-pre2/include/linux/device.h	Fri Apr  5 16:59:34 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;
@@ -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
  */
@@ -143,4 +150,13 @@
 
 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 -urN linux-2.5.8-pre1/include/linux/ext3_fs_sb.h linux-2.5.8-pre2/include/linux/ext3_fs_sb.h
--- linux-2.5.8-pre1/include/linux/ext3_fs_sb.h	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/include/linux/ext3_fs_sb.h	Fri Apr  5 16:59:34 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 -urN linux-2.5.8-pre1/include/linux/fs.h linux-2.5.8-pre2/include/linux/fs.h
--- linux-2.5.8-pre1/include/linux/fs.h	Fri Apr  5 16:59:21 2002
+++ linux-2.5.8-pre2/include/linux/fs.h	Fri Apr  5 16:59:34 2002
@@ -651,7 +651,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;
@@ -696,7 +695,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;
diff -urN linux-2.5.8-pre1/include/linux/highmem.h linux-2.5.8-pre2/include/linux/highmem.h
--- linux-2.5.8-pre1/include/linux/highmem.h	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/include/linux/highmem.h	Fri Apr  5 16:59:35 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 -urN linux-2.5.8-pre1/include/linux/nfsd/const.h linux-2.5.8-pre2/include/linux/nfsd/const.h
--- linux-2.5.8-pre1/include/linux/nfsd/const.h	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/include/linux/nfsd/const.h	Fri Apr  5 16:59:36 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 -urN linux-2.5.8-pre1/include/linux/platform.h linux-2.5.8-pre2/include/linux/platform.h
--- linux-2.5.8-pre1/include/linux/platform.h	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/include/linux/platform.h	Fri Apr  5 16:59:36 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 -urN linux-2.5.8-pre1/include/linux/reiserfs_fs.h linux-2.5.8-pre2/include/linux/reiserfs_fs.h
--- linux-2.5.8-pre1/include/linux/reiserfs_fs.h	Mon Mar 18 12:37:11 2002
+++ linux-2.5.8-pre2/include/linux/reiserfs_fs.h	Fri Apr  5 16:59:36 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 -urN linux-2.5.8-pre1/include/linux/reiserfs_fs_sb.h linux-2.5.8-pre2/include/linux/reiserfs_fs_sb.h
--- linux-2.5.8-pre1/include/linux/reiserfs_fs_sb.h	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/include/linux/reiserfs_fs_sb.h	Fri Apr  5 16:59:36 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 -urN linux-2.5.8-pre1/include/linux/skbuff.h linux-2.5.8-pre2/include/linux/skbuff.h
--- linux-2.5.8-pre1/include/linux/skbuff.h	Fri Apr  5 16:59:22 2002
+++ linux-2.5.8-pre2/include/linux/skbuff.h	Fri Apr  5 16:59:36 2002
@@ -589,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);
@@ -738,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 -urN linux-2.5.8-pre1/include/linux/sunrpc/svc.h linux-2.5.8-pre2/include/linux/sunrpc/svc.h
--- linux-2.5.8-pre1/include/linux/sunrpc/svc.h	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/include/linux/sunrpc/svc.h	Fri Apr  5 16:59:37 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 -urN linux-2.5.8-pre1/include/net/irda/discovery.h linux-2.5.8-pre2/include/net/irda/discovery.h
--- linux-2.5.8-pre1/include/net/irda/discovery.h	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/include/net/irda/discovery.h	Fri Apr  5 16:59:37 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 -urN linux-2.5.8-pre1/include/net/irda/ircomm_tty.h linux-2.5.8-pre2/include/net/irda/ircomm_tty.h
--- linux-2.5.8-pre1/include/net/irda/ircomm_tty.h	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/include/net/irda/ircomm_tty.h	Fri Apr  5 16:59:37 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 -urN linux-2.5.8-pre1/include/net/irda/irlan_client.h linux-2.5.8-pre2/include/net/irda/irlan_client.h
--- linux-2.5.8-pre1/include/net/irda/irlan_client.h	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/include/net/irda/irlan_client.h	Fri Apr  5 16:59:37 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 -urN linux-2.5.8-pre1/include/net/irda/irlmp.h linux-2.5.8-pre2/include/net/irda/irlmp.h
--- linux-2.5.8-pre1/include/net/irda/irlmp.h	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/include/net/irda/irlmp.h	Fri Apr  5 16:59:37 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 -urN linux-2.5.8-pre1/kernel/Makefile linux-2.5.8-pre2/kernel/Makefile
--- linux-2.5.8-pre1/kernel/Makefile	Fri Apr  5 16:59:22 2002
+++ linux-2.5.8-pre2/kernel/Makefile	Fri Apr  5 16:59:37 2002
@@ -10,12 +10,12 @@
 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 capability.o ptrace.o timer.o user.o \
-	    signal.o sys.o kmod.o context.o futex.o
+	    signal.o sys.o kmod.o context.o futex.o platform.o
 
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += ksyms.o
diff -urN linux-2.5.8-pre1/kernel/exit.c linux-2.5.8-pre2/kernel/exit.c
--- linux-2.5.8-pre1/kernel/exit.c	Fri Apr  5 16:59:22 2002
+++ linux-2.5.8-pre2/kernel/exit.c	Fri Apr  5 16:59:37 2002
@@ -469,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)
diff -urN linux-2.5.8-pre1/kernel/fork.c linux-2.5.8-pre2/kernel/fork.c
--- linux-2.5.8-pre1/kernel/fork.c	Mon Mar 18 12:37:05 2002
+++ linux-2.5.8-pre2/kernel/fork.c	Fri Apr  5 16:59:37 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 -urN linux-2.5.8-pre1/kernel/module.c linux-2.5.8-pre2/kernel/module.c
--- linux-2.5.8-pre1/kernel/module.c	Mon Mar 18 12:37:07 2002
+++ linux-2.5.8-pre2/kernel/module.c	Fri Apr  5 16:59:37 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 -urN linux-2.5.8-pre1/kernel/platform.c linux-2.5.8-pre2/kernel/platform.c
--- linux-2.5.8-pre1/kernel/platform.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.8-pre2/kernel/platform.c	Fri Apr  5 16:59:37 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 -urN linux-2.5.8-pre1/kernel/sched.c linux-2.5.8-pre2/kernel/sched.c
--- linux-2.5.8-pre1/kernel/sched.c	Mon Mar 18 12:37:09 2002
+++ linux-2.5.8-pre2/kernel/sched.c	Fri Apr  5 16:59:37 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 */
 
diff -urN linux-2.5.8-pre1/kernel/sys.c linux-2.5.8-pre2/kernel/sys.c
--- linux-2.5.8-pre1/kernel/sys.c	Fri Apr  5 16:59:22 2002
+++ linux-2.5.8-pre2/kernel/sys.c	Fri Apr  5 16:59:37 2002
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/highuid.h>
 #include <linux/fs.h>
+#include <linux/device.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -298,6 +299,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;
@@ -312,6 +314,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);
@@ -319,6 +322,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);
@@ -332,6 +336,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 -urN linux-2.5.8-pre1/kernel/time.c linux-2.5.8-pre2/kernel/time.c
--- linux-2.5.8-pre1/kernel/time.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/kernel/time.c	Fri Apr  5 16:59:37 2002
@@ -25,6 +25,7 @@
  */
 
 #include <linux/timex.h>
+#include <linux/errno.h>
 #include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
diff -urN linux-2.5.8-pre1/lib/Makefile linux-2.5.8-pre2/lib/Makefile
--- linux-2.5.8-pre1/lib/Makefile	Fri Apr  5 16:59:22 2002
+++ linux-2.5.8-pre2/lib/Makefile	Fri Apr  5 16:59:37 2002
@@ -28,7 +28,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 -urN linux-2.5.8-pre1/mm/memory.c linux-2.5.8-pre2/mm/memory.c
--- linux-2.5.8-pre1/mm/memory.c	Mon Mar 18 12:37:14 2002
+++ linux-2.5.8-pre2/mm/memory.c	Fri Apr  5 16:59:38 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 -urN linux-2.5.8-pre1/mm/mmap.c linux-2.5.8-pre2/mm/mmap.c
--- linux-2.5.8-pre1/mm/mmap.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/mm/mmap.c	Fri Apr  5 16:59:38 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 -urN linux-2.5.8-pre1/mm/mprotect.c linux-2.5.8-pre2/mm/mprotect.c
--- linux-2.5.8-pre1/mm/mprotect.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/mm/mprotect.c	Fri Apr  5 16:59:38 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 -urN linux-2.5.8-pre1/mm/mremap.c linux-2.5.8-pre2/mm/mremap.c
--- linux-2.5.8-pre1/mm/mremap.c	Mon Mar 18 12:37:16 2002
+++ linux-2.5.8-pre2/mm/mremap.c	Fri Apr  5 16:59:38 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 -urN linux-2.5.8-pre1/mm/msync.c linux-2.5.8-pre2/mm/msync.c
--- linux-2.5.8-pre1/mm/msync.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/mm/msync.c	Fri Apr  5 16:59:38 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 -urN linux-2.5.8-pre1/mm/vmalloc.c linux-2.5.8-pre2/mm/vmalloc.c
--- linux-2.5.8-pre1/mm/vmalloc.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/mm/vmalloc.c	Fri Apr  5 16:59:38 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;
diff -urN linux-2.5.8-pre1/mm/vmscan.c linux-2.5.8-pre2/mm/vmscan.c
--- linux-2.5.8-pre1/mm/vmscan.c	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/mm/vmscan.c	Fri Apr  5 16:59:38 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
diff -urN linux-2.5.8-pre1/net/irda/af_irda.c linux-2.5.8-pre2/net/irda/af_irda.c
--- linux-2.5.8-pre1/net/irda/af_irda.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/net/irda/af_irda.c	Fri Apr  5 16:59:39 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 -urN linux-2.5.8-pre1/net/irda/ircomm/ircomm_tty.c linux-2.5.8-pre2/net/irda/ircomm/ircomm_tty.c
--- linux-2.5.8-pre1/net/irda/ircomm/ircomm_tty.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/net/irda/ircomm/ircomm_tty.c	Fri Apr  5 16:59:39 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 -urN linux-2.5.8-pre1/net/irda/ircomm/ircomm_tty_attach.c linux-2.5.8-pre2/net/irda/ircomm/ircomm_tty_attach.c
--- linux-2.5.8-pre1/net/irda/ircomm/ircomm_tty_attach.c	Mon Mar 18 12:37:12 2002
+++ linux-2.5.8-pre2/net/irda/ircomm/ircomm_tty_attach.c	Fri Apr  5 16:59:39 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,6 +306,7 @@
  *
  */
 static void ircomm_tty_discovery_indication(discovery_t *discovery,
+					    DISCOVERY_MODE mode,
 					    void *priv)
 {
 	struct ircomm_tty_cb *self;
@@ -312,6 +314,20 @@
 
 	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 -urN linux-2.5.8-pre1/net/irda/ircomm/ircomm_tty_ioctl.c linux-2.5.8-pre2/net/irda/ircomm/ircomm_tty_ioctl.c
--- linux-2.5.8-pre1/net/irda/ircomm/ircomm_tty_ioctl.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/net/irda/ircomm/ircomm_tty_ioctl.c	Fri Apr  5 16:59:39 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 -urN linux-2.5.8-pre1/net/irda/irlan/irlan_client.c linux-2.5.8-pre2/net/irda/irlan/irlan_client.c
--- linux-2.5.8-pre1/net/irda/irlan/irlan_client.c	Mon Mar 18 12:37:02 2002
+++ linux-2.5.8-pre2/net/irda/irlan/irlan_client.c	Fri Apr  5 16:59:40 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;
@@ -155,6 +157,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 -urN linux-2.5.8-pre1/net/irda/irlap_event.c linux-2.5.8-pre2/net/irda/irlap_event.c
--- linux-2.5.8-pre1/net/irda/irlap_event.c	Mon Mar 18 12:37:04 2002
+++ linux-2.5.8-pre2/net/irda/irlap_event.c	Fri Apr  5 16:59:40 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 -urN linux-2.5.8-pre1/net/irda/irlmp.c linux-2.5.8-pre2/net/irda/irlmp.c
--- linux-2.5.8-pre1/net/irda/irlmp.c	Mon Mar 18 12:37:18 2002
+++ linux-2.5.8-pre2/net/irda/irlmp.c	Fri Apr  5 16:59:40 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 -urN linux-2.5.8-pre1/net/irda/irlmp_event.c linux-2.5.8-pre2/net/irda/irlmp_event.c
--- linux-2.5.8-pre1/net/irda/irlmp_event.c	Mon Mar 18 12:37:08 2002
+++ linux-2.5.8-pre2/net/irda/irlmp_event.c	Fri Apr  5 16:59:40 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 -urN linux-2.5.8-pre1/net/irda/irlmp_frame.c linux-2.5.8-pre2/net/irda/irlmp_frame.c
--- linux-2.5.8-pre1/net/irda/irlmp_frame.c	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/net/irda/irlmp_frame.c	Fri Apr  5 16:59:40 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 -urN linux-2.5.8-pre1/net/irda/irnet/irnet.h linux-2.5.8-pre2/net/irda/irnet/irnet.h
--- linux-2.5.8-pre1/net/irda/irnet/irnet.h	Mon Mar 18 12:37:17 2002
+++ linux-2.5.8-pre2/net/irda/irnet/irnet.h	Fri Apr  5 16:59:40 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 -urN linux-2.5.8-pre1/net/irda/irnet/irnet_irda.c linux-2.5.8-pre2/net/irda/irnet/irnet_irda.c
--- linux-2.5.8-pre1/net/irda/irnet/irnet_irda.c	Mon Mar 18 12:37:03 2002
+++ linux-2.5.8-pre2/net/irda/irnet/irnet_irda.c	Fri Apr  5 16:59:40 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 -urN linux-2.5.8-pre1/net/irda/irnet/irnet_irda.h linux-2.5.8-pre2/net/irda/irnet/irnet_irda.h
--- linux-2.5.8-pre1/net/irda/irnet/irnet_irda.h	Mon Mar 18 12:37:06 2002
+++ linux-2.5.8-pre2/net/irda/irnet/irnet_irda.h	Fri Apr  5 16:59:40 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 -urN linux-2.5.8-pre1/net/irda/irsysctl.c linux-2.5.8-pre2/net/irda/irsysctl.c
--- linux-2.5.8-pre1/net/irda/irsysctl.c	Mon Mar 18 12:37:13 2002
+++ linux-2.5.8-pre2/net/irda/irsysctl.c	Fri Apr  5 16:59:40 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 -urN linux-2.5.8-pre1/net/irda/qos.c linux-2.5.8-pre2/net/irda/qos.c
--- linux-2.5.8-pre1/net/irda/qos.c	Mon Mar 18 12:37:10 2002
+++ linux-2.5.8-pre2/net/irda/qos.c	Fri Apr  5 16:59:40 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;
 }
 
 /*
