]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.2.20pre3 2.2.20pre3
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:23:40 +0000 (15:23 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:23:40 +0000 (15:23 -0500)
o FPU/ptrace corruption fixes (Victor Zandy)
o Resync belkin usb serial with 2.4 (Greg Kroah-Hartmann)
o Resync digiport usb serial with 2.4 (Greg Kroah-Hartmann)
o Rsync empeg usb serial with 2.4 (Greg Kroah-Hartmann)
o Resync ftdi_sio against 2.4 (Greg Kroah-Hartmann)
o Bring keyscan usb back into line with 2.4 (Greg Kroah-Hartmann)
o Resync keyspan_pda usb with 2.4 (Greg Kroah-Hartmann)
o Resync omninet usb with 2.4.5 (Greg Kroah-Hartmann)
o Resync usb-serial driver with 2.4.5 (Greg Kroah-Hartmann)
o Resync visor usb driver with 2.4.5 (Greg Kroah-Hartmann)
o Rsync whiteheat driver with 2.4.5 (Greg Kroah-Hartmann)
o Add edgeport USB serial (Greg Kroah-Hartmann)
o Add mct_u232 USB serial (Greg Kroah-Hartmann)
o Update usb storage device list (Stas Bekman, Kaz Sasayma)
o Bring usb acm driver into line with 2.4.5 (Greg Kroah-Hartmann)
o Bring bluetooth driver into line with 2.4.5 (Greg Kroah-Hartmann)
o Bring dabusb driver into line with 2.4.5 (Greg Kroah-Hartmann)
o Bring usb dc2xx driver into line with 2.4.5 (Greg Kroah-Hartmann)
o Bring mdc800 usb driver into line with 2.4.5 (Greg Kroah-Hartmann)
o Bring rio driver into line with 2.4.5 (Greg Kroah-Hartmann)
o Bring USB scanner drivers into line with 2.4.5 (Greg Kroah-Hartmann)
o Update ov511 driver to match 2.4.5 (Greg Kroah-Hartmann)
o Update PCIIOC ioctls (esp for sparc) (Dave Miller)
o General sparc bugfixes (Dave Miller)
o Fix possible oops in fbmem ioctls (Dave Miller)
o Fix reboot/halt bug on "Alcor" Alpha boxes (Tom Vier)
o Update osst driver  (Willem Riede)
o Fix syncppp negotiation bug (Bob Dunlop)
o SMBfs bug fixes from 2.4 series (Urban Widmark)
o 3ware IDE raid driver updates (Adam Radford)
o Fix incorrect use of bitops on non long types (Dave Miller)
o Fix reboot/halt bug on 'Miata' Alpha boxes (Tom Vier)
o Update Tim Waugh's contact info (Tim Waugh)
o Add TIOCGSERIAL to sun serial on PCI sparc32 (Lars Kellogg-Stedman)
o ov511 check user data more carefully (Marc McClelland)
o Fix netif_wake_queue compatibility macro (Andi Kleen)

140 files changed:
CREDITS
Documentation/ioctl-number.txt
Documentation/parport.txt
MAINTAINERS
Makefile
arch/alpha/kernel/entry.S
arch/alpha/kernel/ptrace.c
arch/alpha/kernel/signal.c
arch/alpha/kernel/sys_alcor.c
arch/alpha/kernel/sys_miata.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/signal.c
arch/i386/kernel/entry.S
arch/i386/kernel/process.c
arch/i386/kernel/ptrace.c
arch/i386/kernel/signal.c
arch/i386/kernel/traps.c
arch/i386/kernel/vm86.c
arch/i386/math-emu/fpu_entry.c
arch/m68k/kernel/ptrace.c
arch/m68k/kernel/signal.c
arch/m68k/kernel/traps.c
arch/mips/kernel/irixelf.c
arch/mips/kernel/irixsig.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/scall_o32.S
arch/mips/kernel/signal.c
arch/ppc/kernel/head.S
arch/ppc/kernel/mk_defs.c
arch/ppc/kernel/ptrace.c
arch/ppc/kernel/signal.c
arch/s390/kernel/process.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/signal.c
arch/s390/kernel/traps.c
arch/sparc/kernel/ptrace.c
arch/sparc/kernel/signal.c
arch/sparc64/kernel/binfmt_aout32.c
arch/sparc64/kernel/ioctl32.c
arch/sparc64/kernel/irq.c
arch/sparc64/kernel/process.c
arch/sparc64/kernel/psycho.c
arch/sparc64/kernel/ptrace.c
arch/sparc64/kernel/setup.c
arch/sparc64/kernel/signal.c
arch/sparc64/kernel/signal32.c
drivers/block/ide-floppy.c
drivers/misc/parport_pc.c
drivers/net/rtl8139.c
drivers/net/slip.h
drivers/net/syncppp.c
drivers/pci/proc.c
drivers/sbus/char/aurora.c
drivers/sbus/char/aurora.h
drivers/sbus/char/pcikbd.c
drivers/sbus/char/sab82532.c
drivers/sbus/char/su.c
drivers/sbus/char/zs.c
drivers/scsi/3w-xxxx.c
drivers/scsi/3w-xxxx.h
drivers/scsi/README.osst
drivers/scsi/osst.c
drivers/scsi/osst.h
drivers/scsi/osst_options.h
drivers/scsi/qlogicpti.c
drivers/usb/bluetooth.c
drivers/usb/dabusb.c
drivers/usb/dabusb.h
drivers/usb/dc2xx.c
drivers/usb/mdc800.c
drivers/usb/ov511.c
drivers/usb/rio500.c
drivers/usb/scanner.c
drivers/usb/scanner.h
drivers/usb/serial/Config.in
drivers/usb/serial/Makefile
drivers/usb/serial/belkin_sa.c
drivers/usb/serial/belkin_sa.h
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/empeg.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/io_16654.h [new file with mode: 0644]
drivers/usb/serial/io_edgeport.c [new file with mode: 0644]
drivers/usb/serial/io_edgeport.h [new file with mode: 0644]
drivers/usb/serial/io_fw_boot.h [new file with mode: 0644]
drivers/usb/serial/io_fw_boot2.h [new file with mode: 0644]
drivers/usb/serial/io_fw_down.h [new file with mode: 0644]
drivers/usb/serial/io_fw_down2.h [new file with mode: 0644]
drivers/usb/serial/io_ionsp.h [new file with mode: 0644]
drivers/usb/serial/io_tables.h [new file with mode: 0644]
drivers/usb/serial/io_usbvend.h [new file with mode: 0644]
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/keyspan_pda_fw.h
drivers/usb/serial/mct_u232.c [new file with mode: 0644]
drivers/usb/serial/mct_u232.h [new file with mode: 0644]
drivers/usb/serial/omninet.c
drivers/usb/serial/usb-serial.h
drivers/usb/serial/usbserial.c
drivers/usb/serial/visor.c
drivers/usb/serial/whiteheat.c
drivers/usb/usb-storage.c
drivers/video/fbmem.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/binfmt_misc.c
fs/exec.c
fs/proc/mem.c
fs/smbfs/ChangeLog
fs/smbfs/inode.c
fs/smbfs/proc.c
fs/super.c
include/asm-alpha/pci.h
include/asm-arm/pci.h [new file with mode: 0644]
include/asm-i386/pci.h [new file with mode: 0644]
include/asm-m68k/entry.h
include/asm-mips/offset.h
include/asm-mips/pci.h
include/asm-ppc/pci.h
include/asm-sparc/pci.h [new file with mode: 0644]
include/asm-sparc/siginfo.h
include/asm-sparc/uaccess.h
include/asm-sparc64/bitops.h
include/asm-sparc64/pbm.h
include/asm-sparc64/pci.h [new file with mode: 0644]
include/asm-sparc64/sab82532.h
include/asm-sparc64/uaccess.h
include/linux/kcomp.h
include/linux/parport.h
include/linux/pci.h
include/linux/sched.h
include/linux/sunrpc/xprt.h
kernel/exit.c
kernel/fork.c
kernel/signal.c
net/ipv4/ip_input.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_input.c
net/sunrpc/sched.c

diff --git a/CREDITS b/CREDITS
index cf422e00332804ee905f3fec74526dceed1f2159..acb8da518efde29defafdba26f692a5a299cfefc 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2299,7 +2299,7 @@ S: 1098 VA Amsterdam
 S: The Netherlands
 
 N: Tim Waugh
-E: tim@cyberelk.demon.co.uk
+E: tim@cyberelk.net
 D: Co-architect of the parallel-port sharing system
 S: 17 Curling Vale
 S: GUILDFORD
index d3978957e85d24cc96f98b22fad7a10a06583d62..4ed35f51d46292601ac9fbc1592ffb623b38fe85 100644 (file)
@@ -102,7 +102,7 @@ Code        Seq#    Include File            Comments
 'p'    00-3F   linux/mc146818rtc.h
 'p'    40-7F   linux/nvram.h
 'p'    80-9F   user-space parport      in development:
-                                       <tim@cyberelk.demon.co.uk>
+                                       <tim@cyberelk.net>
 'r'    all     linux/msdos_fs.h
 's'    all     linux/cdk.h
 't'    00-7F   linux/if_ppp.h
index 6cf09e631071d945395c18a6009ddacbcd566f28..c1331464e82b0848ab43d4fafe1e98aa2d8855fd 100644 (file)
@@ -147,4 +147,4 @@ Also:
 
 --
 Philip.Blundell@pobox.com
-tim@cyberelk.demon.co.uk
+tim@cyberelk.net
index aa1fb50a195af2a1b8b13a41d30f5a96802031a3..2194657e8af0dd988f5f485b2a74b11f0ca030ee 100644 (file)
@@ -764,13 +764,13 @@ PARALLEL PORT SUPPORT
 P:     Phil Blundell
 M:     Philip.Blundell@pobox.com
 P:     Tim Waugh
-M:     tim@cyberelk.demon.co.uk
+M:     tim@cyberelk.net
 P:     David Campbell
 M:     campbell@torque.net
 P:     Andrea Arcangeli
 M:     andrea@e-mind.com
 L:     linux-parport@torque.net
-W:     http://www.cyberelk.demon.co.uk/parport.html
+W:     http://people.redhat.com/twaugh/parport/
 S:     Maintained
 
 PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES
index be8c98cc60de94345518a90af9b262afafc862cc..96fe4de08b9c9ebe95c5683d72d8e9bb1e97c39a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 20
-EXTRAVERSION = pre2
+EXTRAVERSION = pre3
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
index fa41752abc3e010ba4ef033195f6c9eb45ce1d94..bb8ad1331693b1a3e8a264129f04bdde5b22cdf9 100644 (file)
 #define TASK_ADDR_LIMIT                24      
 #define TASK_EXEC_DOMAIN       32
 #define TASK_NEED_RESCHED      40
+#define TASK_PTRACE             48
 
 /*
  * task flags (must match include/linux/sched.h):
  */
-#define        PF_PTRACED      0x00000010
+#define        PT_PTRACED      0x00000001
 
 /*
  * This defines the normal kernel pt-regs layout.
@@ -558,7 +559,7 @@ entSys:
        ldq     $3,TASK_FLAGS($8)
        stq     $17,SP_OFF+32($30)
        s8addq  $0,$5,$5
-       and     $3,PF_PTRACED,$3
+       and     $3,PT_PTRACED,$3
        stq     $18,SP_OFF+40($30)
        bne     $3,strace
        beq     $4,1f
index b1cd849afefb1fe286ba1a190c83d90f2682a26c..b936e9747f836a5ee49656b23c4fef77b947e37d 100644 (file)
@@ -527,10 +527,10 @@ sys_ptrace(long request, long pid, long addr, long data,
        ret = -EPERM;
        if (request == PTRACE_TRACEME) {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED)
+               if (current->ptrace & PT_PTRACED)
                        goto out;
                /* set the ptrace bit in the process flags. */
-               current->flags |= PF_PTRACED;
+               current->ptrace |= PT_PTRACED;
                ret = 0;
                goto out;
        }
@@ -553,9 +553,9 @@ sys_ptrace(long request, long pid, long addr, long data,
                    && !capable(CAP_SYS_PTRACE))
                        goto out;
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED)
+               if (child->ptrace & PT_PTRACED)
                        goto out;
-               child->flags |= PF_PTRACED;
+               child->ptrace |= PT_PTRACED;
                if (child->p_pptr != current) {
                        REMOVE_LINKS(child);
                        child->p_pptr = current;
@@ -566,7 +566,7 @@ sys_ptrace(long request, long pid, long addr, long data,
                goto out;
        }
        ret = -ESRCH;
-       if (!(child->flags & PF_PTRACED)) {
+       if (!(child->ptrace & PT_PTRACED)) {
                DBG(DBG_MEM, ("child not traced\n"));
                goto out;
        }
@@ -622,9 +622,9 @@ sys_ptrace(long request, long pid, long addr, long data,
                if ((unsigned long) data > _NSIG)
                        goto out;
                if (request == PTRACE_SYSCALL)
-                       child->flags |= PF_TRACESYS;
+                       child->ptrace |= PT_TRACESYS;
                else
-                       child->flags &= ~PF_TRACESYS;
+                       child->ptrace &= ~PT_TRACESYS;
                child->exit_code = data;
                wake_up_process(child);
                /* make sure single-step breakpoint is gone. */
@@ -652,7 +652,7 @@ sys_ptrace(long request, long pid, long addr, long data,
                if ((unsigned long) data > _NSIG)
                        goto out;
                child->tss.bpt_nsaved = -1;     /* mark single-stepping */
-               child->flags &= ~PF_TRACESYS;
+               child->ptrace &= ~PT_TRACESYS;
                wake_up_process(child);
                child->exit_code = data;
                /* give it a chance to run. */
@@ -663,7 +663,7 @@ sys_ptrace(long request, long pid, long addr, long data,
                ret = -EIO;
                if ((unsigned long) data > _NSIG)
                        goto out;
-               child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+               child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
                wake_up_process(child);
                child->exit_code = data;
                REMOVE_LINKS(child);
@@ -686,8 +686,8 @@ sys_ptrace(long request, long pid, long addr, long data,
 asmlinkage void
 syscall_trace(void)
 {
-       if ((current->flags & (PF_PTRACED|PF_TRACESYS))
-           != (PF_PTRACED|PF_TRACESYS))
+       if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+           != (PT_PTRACED|PT_TRACESYS))
                return;
        current->exit_code = SIGTRAP;
        current->state = TASK_STOPPED;
index cc07dfae02845697d77cceaf6db4e7e3fab7dc73..79d71a0235ef1e3e031bfc8660953706c622b034 100644 (file)
@@ -621,7 +621,7 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
                if (!signr)
                        break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        /* Let the debugger run.  */
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
index adcc91f3493a32defedb7959accb90d18a2cb06d..662ced1e39ba0b780f56056b403299451ba57a51 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/reboot.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
@@ -186,13 +187,21 @@ alcor_pci_fixup(void)
 static void
 alcor_kill_arch (int mode, char *reboot_cmd)
 {
-       /* Who said DEC engineer's have no sense of humor? ;-)  */
-       if (alpha_using_srm) {
-               *(vuip) GRU_RESET = 0x0000dead;
-               mb();
+       switch(mode) {
+       case LINUX_REBOOT_CMD_RESTART:
+               /* Who said DEC engineer's have no sense of humor? ;-)  */
+               if (alpha_using_srm) {
+                       *(vuip) GRU_RESET = 0x0000dead;
+                       mb();
+               }
+               break;
+       case LINUX_REBOOT_CMD_HALT:
+               break;
+       case LINUX_REBOOT_CMD_POWER_OFF:
+               break;
        }
 
-       generic_kill_arch(mode, reboot_cmd);
+       halt();
 }
 
 
index 2ddc06d1208cdb20c9bccb469e12ece7adaa513a..bcec39019aa09d42b1a5d51229bdc37898cfa475 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/reboot.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
@@ -274,12 +275,22 @@ miata_pci_fixup(void)
 static void 
 miata_kill_arch (int mode, char *reboot_cmd) 
 { 
-       /* Who said DEC engineers have no sense of humor? ;-)  */ 
-       if (alpha_using_srm) { 
-               *(vuip) PYXIS_RESET = 0x0000dead; 
-               mb(); 
-       } 
-       generic_kill_arch(mode, reboot_cmd); 
+       switch(mode) {
+       case LINUX_REBOOT_CMD_HALT:
+               break;
+       case LINUX_REBOOT_CMD_RESTART:
+               /* Who said DEC engineers have no sense of humor? ;-)  */ 
+               if (alpha_using_srm) { 
+                       *(vuip) PYXIS_RESET = 0x0000dead; 
+                       mb(); 
+               } 
+               generic_kill_arch(mode, reboot_cmd); 
+               break;
+       case LINUX_REBOOT_CMD_POWER_OFF:
+               break;
+       }
+
+       halt();
 } 
 
 
index 29692c074c2fc0eddfe46bee947528d1bbd80ef8..8f0ee697db085d1fe665ec2ddcd067f4709491ed 100644 (file)
@@ -662,9 +662,9 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
                        if ((unsigned long) data > _NSIG)
                                break;
                        if (request == PTRACE_SYSCALL)
-                               child->flags |= PF_TRACESYS;
+                               child->ptrace |= PT_TRACESYS;
                        else
-                               child->flags &= ~PF_TRACESYS;
+                               child->ptrace &= ~PT_TRACESYS;
                        child->exit_code = data;
                        /* make sure single-step breakpoint is gone. */
                        ptrace_cancel_bpt(child);
@@ -697,7 +697,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
                        if ((unsigned long) data > _NSIG)
                                break;
                        child->tss.debug.nsaved = -1;
-                       child->flags &= ~PF_TRACESYS;
+                       child->ptrace &= ~PT_TRACESYS;
                        child->exit_code = data;
                        /* give it a chance to run. */
                        wake_up_process(child);
@@ -711,7 +711,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
                        ret = -EIO;
                        if ((unsigned long) data > _NSIG)
                                break;
-                       child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+                       child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
                        child->exit_code = data;
                        REMOVE_LINKS(child);
                        child->p_pptr = child->p_opptr;
@@ -799,10 +799,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
        ret = -EPERM;
        if (request == PTRACE_TRACEME) {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED)
+               if (current->ptrace & PT_PTRACED)
                        goto out;
                /* set the ptrace bit in the process flags. */
-               current->flags |= PF_PTRACED;
+               current->ptrace |= PT_PTRACED;
                ret = 0;
                goto out;
        }
@@ -826,9 +826,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out;
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED)
+               if (child->ptrace & PT_PTRACED)
                        goto out;
-               child->flags |= PF_PTRACED;
+               child->ptrace |= PT_PTRACED;
 
                if (child->p_pptr != current) {
                        REMOVE_LINKS(child);
@@ -841,7 +841,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                goto out;
        }
        ret = -ESRCH;
-       if (!(child->flags & PF_PTRACED))
+       if (!(child->ptrace & PT_PTRACED))
                goto out;
        if (child->state != TASK_STOPPED && request != PTRACE_KILL)
                goto out;
@@ -857,8 +857,8 @@ out:
 
 asmlinkage void syscall_trace(void)
 {
-       if ((current->flags & (PF_PTRACED|PF_TRACESYS))
-                       != (PF_PTRACED|PF_TRACESYS))
+       if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+                       != (PT_PTRACED|PT_TRACESYS))
                return;
        current->exit_code = SIGTRAP;
        current->state = TASK_STOPPED;
index e5ec22dca3da42e2a2f106d5e058ab3fbd6e3842..85c855a989e1246927a428fcb64fa12bfde436f9 100644 (file)
@@ -474,7 +474,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
                if (!signr)
                        break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        /* Let the debugger run.  */
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
index 419752f90834cc8d265bdfcb9329276f3d7f0008..d3bdbb73ab941e26bceab6422870d4dbf773e612 100644 (file)
@@ -76,6 +76,7 @@ sigpending    =  8
 addr_limit     = 12
 exec_domain    = 16
 need_resched   = 20
+ptrace         = 24
 
 ENOSYS = 38
 
@@ -174,7 +175,7 @@ ENTRY(system_call)
        GET_CURRENT(%ebx)
        cmpl $(NR_syscalls),%eax
        jae badsys
-       testb $0x20,flags(%ebx)         # PF_TRACESYS
+       testb $0x02,ptrace(%ebx)        # PT_TRACESYS
        jne tracesys
        call *SYMBOL_NAME(sys_call_table)(,%eax,4)
        movl %eax,EAX(%esp)             # save the return value
index 096226ab1f5c53731ad8f5c4445ec144e169524e..748d348b33f747d4cc5da24d0654bb2f50f603dc 100644 (file)
@@ -808,7 +808,7 @@ asmlinkage int sys_execve(struct pt_regs regs)
                goto out;
        error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
        if (error == 0)
-               current->flags &= ~PF_DTRACE;
+               current->ptrace &= ~PT_DTRACE;
        putname(filename);
 out:
        unlock_kernel();
index 9e46eb2cf1eeda8bcf175a4def25c0462e3671f5..620b4440acfa8e222bb2d564465c2b2463120818 100644 (file)
@@ -394,10 +394,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
        ret = -EPERM;
        if (request == PTRACE_TRACEME) {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED)
+               if (current->ptrace & PT_PTRACED)
                        goto out;
                /* set the ptrace bit in the process flags. */
-               current->flags |= PF_PTRACED;
+               current->ptrace |= PT_PTRACED;
                ret = 0;
                goto out;
        }
@@ -423,9 +423,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out;
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED)
+               if (child->ptrace & PT_PTRACED)
                        goto out;
-               child->flags |= PF_PTRACED;
+               child->ptrace |= PT_PTRACED;
 
                write_lock_irqsave(&tasklist_lock, flags);
                if (child->p_pptr != current) {
@@ -440,7 +440,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                goto out;
        }
        ret = -ESRCH;
-       if (!(child->flags & PF_PTRACED))
+       if (!(child->ptrace & PT_PTRACED))
                goto out;
        if (child->state != TASK_STOPPED) {
                if (request != PTRACE_KILL)
@@ -542,9 +542,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        if ((unsigned long) data > _NSIG)
                                goto out;
                        if (request == PTRACE_SYSCALL)
-                               child->flags |= PF_TRACESYS;
+                               child->ptrace |= PT_TRACESYS;
                        else
-                               child->flags &= ~PF_TRACESYS;
+                               child->ptrace &= ~PT_TRACESYS;
                        child->exit_code = data;
        /* make sure the single step bit is not set. */
                        tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
@@ -579,10 +579,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        ret = -EIO;
                        if ((unsigned long) data > _NSIG)
                                goto out;
-                       child->flags &= ~PF_TRACESYS;
-                       if ((child->flags & PF_DTRACE) == 0) {
+                       child->ptrace &= ~PT_TRACESYS;
+                       if ((child->ptrace & PT_DTRACE) == 0) {
                                /* Spurious delayed TF traps may occur */
-                               child->flags |= PF_DTRACE;
+                               child->ptrace |= PT_DTRACE;
                        }
                        tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
                        put_stack_long(child, EFL_OFFSET, tmp);
@@ -599,7 +599,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        ret = -EIO;
                        if ((unsigned long) data > _NSIG)
                                goto out;
-                       child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+                       child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
                        child->exit_code = data;
                        write_lock_irqsave(&tasklist_lock, flags);
                        REMOVE_LINKS(child);
@@ -710,8 +710,8 @@ out:
 
 asmlinkage void syscall_trace(void)
 {
-       if ((current->flags & (PF_PTRACED|PF_TRACESYS))
-                       != (PF_PTRACED|PF_TRACESYS))
+       if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+                       != (PT_PTRACED|PT_TRACESYS))
                return;
        current->exit_code = SIGTRAP;
        current->state = TASK_STOPPED;
index 5a7d8bbaea1fdb16e1cdd95cd940e05d367a2dc9..d0dbbcaf8f7c53525b27b0628cfa7a8674c96649 100644 (file)
@@ -629,7 +629,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                if (!signr)
                        break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        /* Let the debugger run.  */
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
index 3869f2ab42ba7e6a28341570641374b6dda3948b..a032fb41d9c4e2a706a4f0040011eb1afbfa1485 100644 (file)
@@ -375,12 +375,12 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
                 * The TF error should be masked out only if the current
                 * process is not traced and if the TRAP flag has been set
                 * previously by a tracing process (condition detected by
-                * the PF_DTRACE flag); remember that the i386 TRAP flag
+                * the PT_DTRACE flag); remember that the i386 TRAP flag
                 * can be modified by the process itself in user mode,
                 * allowing programs to debug themselves without the ptrace()
                 * interface.
                 */
-               if ((tsk->flags & (PF_DTRACE|PF_PTRACED)) == PF_DTRACE)
+               if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
                        goto clear_TF;
        }
 
index d181dc6994bd5246684bc2101de444fbd8e67a71..7c3f83e4e0ddaf5f3bdd7cf432be5ad739542f79 100644 (file)
@@ -439,7 +439,7 @@ int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno
        }
        if (trapno !=1)
                return 1; /* we let this handle by the calling routine */
-       if (current->flags & PF_PTRACED) {
+       if (current->ptrace & PT_PTRACED) {
                unsigned long flags;
                spin_lock_irqsave(&current->sigmask_lock, flags);
                sigdelset(&current->blocked, SIGTRAP);
index 1c5d30e1db394dac9b1aed518a3069228e6b5fbb..92134b445eaacc1ce1ae1f9214a9cecbe4646bf7 100644 (file)
@@ -210,7 +210,7 @@ asmlinkage void math_emulate(long arg)
     }
 
   FPU_lookahead = 1;
-  if (current->flags & PF_PTRACED)
+  if (current->ptrace & PT_PTRACED)
     FPU_lookahead = 0;
 
   if ( !valid_prefix(&byte1, (u_char **)&FPU_EIP,
index 76e166493050d9ba22aedbcf96c4beb4d8bd875e..5c01f454ca61df6e9a957f91262798334d81e322 100644 (file)
@@ -320,10 +320,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
        ret = -EPERM;
        if (request == PTRACE_TRACEME) {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED)
+               if (current->ptrace & PT_PTRACED)
                        goto out;
                /* set the ptrace bit in the process flags. */
-               current->flags |= PF_PTRACED;
+               current->ptrace |= PT_PTRACED;
                ret = 0;
                goto out;
        }
@@ -349,9 +349,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out;
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED)
+               if (child->ptrace & PT_PTRACED)
                        goto out;
-               child->flags |= PF_PTRACED;
+               child->ptrace |= PT_PTRACED;
 
                write_lock_irqsave(&tasklist_lock, flags);
                if (child->p_pptr != current) {
@@ -366,7 +366,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                goto out;
        }
        ret = -ESRCH;
-       if (!(child->flags & PF_PTRACED))
+       if (!(child->ptrace & PT_PTRACED))
                goto out;
        if (child->state != TASK_STOPPED) {
                if (request != PTRACE_KILL)
@@ -473,9 +473,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        if ((unsigned long) data > _NSIG)
                                goto out;
                        if (request == PTRACE_SYSCALL)
-                               child->flags |= PF_TRACESYS;
+                               child->ptrace |= PT_TRACESYS;
                        else
-                               child->flags &= ~PF_TRACESYS;
+                               child->ptrace &= ~PT_TRACESYS;
                        child->exit_code = data;
                        /* make sure the single step bit is not set. */
                        tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
@@ -510,7 +510,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        ret = -EIO;
                        if ((unsigned long) data > _NSIG)
                                goto out;
-                       child->flags &= ~PF_TRACESYS;
+                       child->ptrace &= ~PT_TRACESYS;
                        tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
                        put_reg(child, PT_SR, tmp);
 
@@ -527,7 +527,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        ret = -EIO;
                        if ((unsigned long) data > _NSIG)
                                goto out;
-                       child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+                       child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
                        child->exit_code = data;
                        write_lock_irqsave(&tasklist_lock, flags);
                        REMOVE_LINKS(child);
@@ -607,8 +607,8 @@ out:
 asmlinkage void syscall_trace(void)
 {
        lock_kernel();
-       if ((current->flags & (PF_PTRACED|PF_TRACESYS))
-                       != (PF_PTRACED|PF_TRACESYS))
+       if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+                       != (PT_PTRACED|PT_TRACESYS))
                goto out;
        current->exit_code = SIGTRAP;
        current->state = TASK_STOPPED;
index e635e3447e6e207f9c52991304f7869d8bd2e98c..301de71a0b0ca74e87496ac5343c1f53d018b5ef 100644 (file)
@@ -1007,7 +1007,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
                if (!signr)
                        break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
                        regs->sr &= ~PS_T;
index d25f28a5f11cda0f8d647f1ee4c8a4d590e41e68..4008de6061b59ddc0b5b88e2ac444892ced53aec 100644 (file)
@@ -921,7 +921,7 @@ asmlinkage void trap_c(struct frame *fp)
        if (fp->ptregs.sr & PS_S) {
                if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
                        /* traced a trapping instruction */
-                       current->flags |= PF_DTRACE;
+                       current->ptrace |= PT_DTRACE;
                } else
                        bad_super_trap(fp);
                return;
index 96856761c2b043adc8aaadc5a3cf96c3a3d68458..08b025a5500f733d7f7cd08c6fd7332bd81a71d8 100644 (file)
@@ -806,7 +806,7 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm,
 #endif
 
        start_thread(regs, elf_entry, bprm->p);
-       if (current->flags & PF_PTRACED)
+       if (current->ptrace & PT_PTRACED)
                send_sig(SIGTRAP, current, 0);
        return 0;
 
index 4ace7f17141b918b3ea4d2bafe14f3f5bcdefec5..f41c8b9fc4b4e6acf4dcfdc82e5142e4a0477b0c 100644 (file)
@@ -193,7 +193,7 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
                if (!signr)
                        break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        /* Let the debugger run.  */
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
@@ -707,7 +707,7 @@ repeat:
                                if (!p->exit_code)
                                        continue;
                                if (!(options & (W_TRAPPED|W_STOPPED)) &&
-                                   !(p->flags & PF_PTRACED))
+                                   !(p->ptrace & PT_PTRACED))
                                        continue;
                                if (ru != NULL)
                                        getrusage(p, RUSAGE_BOTH, ru);
index 76c00bf94e6cf5c9f3ddf506a9c4ff15fd1b3abc..af05eaafed73ade98b3c5eb39ec9cef912d0efbb 100644 (file)
@@ -270,12 +270,12 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 #endif
        if (request == PTRACE_TRACEME) {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED) {
+               if (current->ptrace & PT_PTRACED) {
                        res = -EPERM;
                        goto out;
                }
                /* set the ptrace bit in the process flags. */
-               current->flags |= PF_PTRACED;
+               current->ptrace |= PT_PTRACED;
                res = 0;
                goto out;
        }
@@ -306,9 +306,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        goto out;
                }
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED)
+               if (child->ptrace & PT_PTRACED)
                        goto out;
-               child->flags |= PF_PTRACED;
+               child->ptrace |= PT_PTRACED;
 
                write_lock_irqsave(&tasklist_lock, flags);
                if (child->p_pptr != current) {
@@ -322,7 +322,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                res = 0;
                goto out;
        }
-       if (!(child->flags & PF_PTRACED)) {
+       if (!(child->ptrace & PT_PTRACED)) {
                res = -ESRCH;
                goto out;
        }
@@ -473,9 +473,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        goto out;
                }
                if (request == PTRACE_SYSCALL)
-                       child->flags |= PF_TRACESYS;
+                       child->ptrace |= PT_TRACESYS;
                else
-                       child->flags &= ~PF_TRACESYS;
+                       child->ptrace &= ~PT_TRACESYS;
                child->exit_code = data;
                wake_up_process(child);
                res = data;
@@ -501,7 +501,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        res = -EIO;
                        goto out;
                }
-               child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+               child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
                child->exit_code = data;
                REMOVE_LINKS(child);
                child->p_pptr = child->p_opptr;
@@ -522,8 +522,8 @@ out:
 
 asmlinkage void syscall_trace(void)
 {
-       if ((current->flags & (PF_PTRACED|PF_TRACESYS))
-                       != (PF_PTRACED|PF_TRACESYS))
+       if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+                       != (PT_PTRACED|PT_TRACESYS))
                return;
        current->exit_code = SIGTRAP;
        current->state = TASK_STOPPED;
index b31a8b18e68ee9066a52325be37f2d4375bbcb8d..b3bb80a0175389202ded17a9385279c69d1f4e2b 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/unistd.h>
 
 /* This duplicates the definition from <linux/sched.h> */
-#define PF_TRACESYS    0x00000020      /* tracing system calls */
+#define PT_TRACESYS    0x00000002      /* tracing system calls */
 
 /* This duplicates the definition from <asm/signal.h> */
 #define SIGILL         4               /* Illegal instruction (ANSI).  */
@@ -48,8 +48,8 @@ NESTED(handle_sys, PT_SIZE, sp)
        bgez    t0, stackargs
 
 stack_done:
-       lw      t0, TASK_FLAGS($28)     # syscall tracing enabled?
-       andi    t0, PF_TRACESYS
+       lw      t0, TASK_PTRACE($28)    # syscall tracing enabled?
+       andi    t0, PT_TRACESYS
        bnez    t0, trace_a_syscall
 
        jalr    t2                      # Do The Real Thing (TM)
index c019f778b4b2bd1376a274ceb72efa375ea40597..bc29add01f53d77acb2b4a960d1c73fd64acdd2a 100644 (file)
@@ -424,7 +424,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
                if (!signr)
                        break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        /* Let the debugger run.  */
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
index f379077776c60853e0436b778ba4c302926c0079..323bdd2ced89b8490ef39d0e7ccc3bf22ec3d042 100644 (file)
@@ -2129,8 +2129,8 @@ DoSyscall:
         cmpi    1,r0,0x6666     /* Special case for 'sys_rt_sigreturn' */
        beq-    10f
         beq-    cr1,16f
-       lwz     r10,TASK_FLAGS(r2)
-       andi.   r10,r10,PF_TRACESYS
+       lwz     r10,TASK_PTRACE(r2)
+       andi.   r10,r10,PT_TRACESYS
        bne-    50f
        cmpli   0,r0,NR_syscalls
        bge-    66f
index 9cf0eb8349deeff254e3878c0ce79eb276a004fd..f4b0cc5b9e8342009bcca65361b725f17121454e 100644 (file)
@@ -43,8 +43,9 @@ main(void)
        DEFINE(PGD, offsetof(struct mm_struct, pgd));
        DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall));
        DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
-       DEFINE(PF_TRACESYS, PF_TRACESYS);
+       DEFINE(PT_TRACESYS, PT_TRACESYS);
        DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+       DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
        DEFINE(NEED_RESCHED, offsetof(struct task_struct, need_resched));
        DEFINE(TSS_FPR0, offsetof(struct thread_struct, fpr[0]));
        DEFINE(TSS_FPSCR, offsetof(struct thread_struct, fpscr));
index 19e1c3fbab147b54a2194007c576babaf2f1505a..ef45cc70562e0595047549e2d6d8e7d3be07bd69 100644 (file)
@@ -341,10 +341,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
        lock_kernel();
        if (request == PTRACE_TRACEME) {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED)
+               if (current->ptrace & PT_PTRACED)
                        goto out;
                /* set the ptrace bit in the process flags. */
-               current->flags |= PF_PTRACED;
+               current->ptrace |= PT_PTRACED;
                ret = 0;
                goto out;
        }
@@ -370,9 +370,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out;
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED)
+               if (child->ptrace & PT_PTRACED)
                        goto out;
-               child->flags |= PF_PTRACED;
+               child->ptrace |= PT_PTRACED;
 
                write_lock_irqsave(&tasklist_lock, flags);
                if (child->p_pptr != current) {
@@ -387,7 +387,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                goto out;
        }
        ret = -ESRCH;
-       if (!(child->flags & PF_PTRACED))
+       if (!(child->ptrace & PT_PTRACED))
                goto out;
        if (child->state != TASK_STOPPED) {
                if (request != PTRACE_KILL)
@@ -472,9 +472,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        if ((unsigned long) data > _NSIG)
                                goto out;
                        if (request == PTRACE_SYSCALL)
-                               child->flags |= PF_TRACESYS;
+                               child->ptrace |= PT_TRACESYS;
                        else
-                               child->flags &= ~PF_TRACESYS;
+                               child->ptrace &= ~PT_TRACESYS;
                        child->exit_code = data;
                        /* make sure the single step bit is not set. */
                        clear_single_step(child);
@@ -503,7 +503,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        ret = -EIO;
                        if ((unsigned long) data > _NSIG)
                                goto out;
-                       child->flags &= ~PF_TRACESYS;
+                       child->ptrace &= ~PT_TRACESYS;
                        set_single_step(child);
                        child->exit_code = data;
                        /* give it a chance to run. */
@@ -516,7 +516,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        ret = -EIO;
                        if ((unsigned long) data > _NSIG)
                                goto out;
-                       child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+                       child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
                        child->exit_code = data;
                        write_lock_irqsave(&tasklist_lock, flags);
                        REMOVE_LINKS(child);
@@ -541,8 +541,8 @@ out:
 
 asmlinkage void syscall_trace(void)
 {
-       if ((current->flags & (PF_PTRACED|PF_TRACESYS))
-                       != (PF_PTRACED|PF_TRACESYS))
+       if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+                       != (PT_PTRACED|PT_TRACESYS))
                return;
        current->exit_code = SIGTRAP;
        current->state = TASK_STOPPED;
index 20c3b1115a6d1740ee2789965583d5acd12aec85..5ce57e7bf2863efb82acfad025c3011cd8b2d5f6 100644 (file)
@@ -558,7 +558,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
                if (!signr)
                        break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        /* Let the debugger run.  */
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
index 7f9a9454644120df63266b16020a265ea0a62e9c..248f2b62e1008d58f0459789647b2656436c1f13 100644 (file)
@@ -404,7 +404,7 @@ asmlinkage int sys_execve(struct pt_regs regs)
         error = do_execve(filename, (char **) regs.gprs[3], (char **) regs.gprs[4], &regs);
        if (error == 0)
        {
-               current->flags &= ~PF_DTRACE;
+               current->ptrace &= ~PT_DTRACE;
                current->tss.fp_regs.fpc=0;
                if(MACHINE_HAS_IEEE)
                {
index 2b81c03f165007040a2eecd3433f8c78ffdf7b48..9e7fc810f5962ed363c4b6cafd6f3eb39ba28ef6 100644 (file)
@@ -435,10 +435,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
        if (request == PTRACE_TRACEME) 
        {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED)
+               if (current->ptrace & PT_PTRACED)
                        goto out;
                /* set the ptrace bit in the process flags. */
-               current->flags |= PF_PTRACED;
+               current->ptrace |= PT_PTRACED;
                ret = 0;
                goto out;
        }
@@ -459,9 +459,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                     (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out;
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED)
+               if (child->ptrace & PT_PTRACED)
                        goto out;
-               child->flags |= PF_PTRACED;
+               child->ptrace |= PT_PTRACED;
                if (child->p_pptr != current) 
                {
                        REMOVE_LINKS(child);
@@ -478,7 +478,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
        /* ieee_instruction_pointer from the user structure DJB */
        if(child!=current)
        {
-               if (!(child->flags & PF_PTRACED))
+               if (!(child->ptrace & PT_PTRACED))
                        goto out;
                if (child->state != TASK_STOPPED) 
                {
@@ -524,9 +524,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                if ((unsigned long) data >= _NSIG)
                        break;
                if (request == PTRACE_SYSCALL)
-                       child->flags |= PF_TRACESYS;
+                       child->ptrace |= PT_TRACESYS;
                else
-                       child->flags &= ~PF_TRACESYS;
+                       child->ptrace &= ~PT_TRACESYS;
                child->exit_code = data;
                /* make sure the single step bit is not set. */
                clear_single_step(child);
@@ -553,7 +553,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                ret = -EIO;
                if ((unsigned long) data >= _NSIG)
                        break;
-               child->flags &= ~PF_TRACESYS;
+               child->ptrace &= ~PT_TRACESYS;
                child->exit_code = data;
                set_single_step(child);
                /* give it a chance to run. */
@@ -565,7 +565,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                ret = -EIO;
                if ((unsigned long) data >= _NSIG)
                        break;
-               child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+               child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
                wake_up_process(child);
                child->exit_code = data;
                REMOVE_LINKS(child);
@@ -593,8 +593,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 asmlinkage void syscall_trace(void)
 {
        lock_kernel();
-       if ((current->flags & (PF_PTRACED|PF_TRACESYS))
-           != (PF_PTRACED|PF_TRACESYS))
+       if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+           != (PT_PTRACED|PT_TRACESYS))
                goto out;
        current->exit_code = SIGTRAP;
        current->state = TASK_STOPPED;
index af7f4b35336d6e3e4719fe6f0435a1f020fb8fa7..904bacf66285d378206c298ce8468ede3baaef1e 100644 (file)
@@ -461,7 +461,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                if (!signr)
                        break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        /* Let the debugger run.  */
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
index 9233188885991b994c5ec0a63cbc587a55012165..27b210e1ffd27fcfb92d990904b7babbd8dfac26 100644 (file)
@@ -94,7 +94,7 @@ int do_debugger_trap(struct pt_regs *regs,int signal)
 {
        if(regs->psw.mask&PSW_PROBLEM_STATE)
        {
-               if(current->flags & PF_PTRACED)
+               if(current->ptrace & PT_PTRACED)
                        force_sig(signal,current);
                else
                        return(TRUE);
index a4a296cf3f426ec2fdf939c2798f8d0ff6ba18ec..1107387eba3f61cba4a4f209896a36463c747a84 100644 (file)
@@ -535,12 +535,12 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
 #endif
        if(request == PTRACE_TRACEME) {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED) {
+               if (current->ptrace & PT_PTRACED) {
                        pt_error_return(regs, EPERM);
                        goto out;
                }
                /* set the ptrace bit in the process flags. */
-               current->flags |= PF_PTRACED;
+               current->ptrace |= PT_PTRACED;
                pt_succ_return(regs, 0);
                goto out;
        }
@@ -578,11 +578,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
                        goto out;
                }
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED) {
+               if (child->ptrace & PT_PTRACED) {
                        pt_error_return(regs, EPERM);
                        goto out;
                }
-               child->flags |= PF_PTRACED;
+               child->ptrace |= PT_PTRACED;
                write_lock_irqsave(&tasklist_lock, flags);
                if(child->p_pptr != current) {
                        REMOVE_LINKS(child);
@@ -594,7 +594,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
                pt_succ_return(regs, 0);
                goto out;
        }
-       if (!(child->flags & PF_PTRACED)
+       if (!(child->ptrace & PT_PTRACED)
            && ((current->personality & PER_BSD) && (request != PTRACE_SUNATTACH))
            && (!(current->personality & PER_BSD) && (request != PTRACE_ATTACH))) {
                pt_error_return(regs, ESRCH);
@@ -861,9 +861,9 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
                }
 
                if (request == PTRACE_SYSCALL)
-                       child->flags |= PF_TRACESYS;
+                       child->ptrace |= PT_TRACESYS;
                else
-                       child->flags &= ~PF_TRACESYS;
+                       child->ptrace &= ~PT_TRACESYS;
 
                child->exit_code = data;
 #ifdef DEBUG_PTRACE
@@ -900,7 +900,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
                        pt_error_return(regs, EIO);
                        goto out;
                }
-               child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+               child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
                wake_up_process(child);
                child->exit_code = data;
                write_lock_irqsave(&tasklist_lock, flags);
@@ -927,8 +927,8 @@ asmlinkage void syscall_trace(void)
 #ifdef DEBUG_PTRACE
        printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
 #endif
-       if ((current->flags & (PF_PTRACED|PF_TRACESYS))
-                       != (PF_PTRACED|PF_TRACESYS))
+       if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+                       != (PT_PTRACED|PT_TRACESYS))
                return;
        current->exit_code = SIGTRAP;
        current->state = TASK_STOPPED;
index bf42234900be895dcd2c1aeba31549517e151e3c..5401c0e24e60fb5ca82cd0e1e76c85a088825b2c 100644 (file)
@@ -1139,7 +1139,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
 
                if (!signr) break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
 
@@ -1203,7 +1203,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
                                        continue;
 
                        case SIGSTOP:
-                               if (current->flags & PF_PTRACED)
+                               if (current->ptrace & PT_PTRACED)
                                        continue;
                                current->state = TASK_STOPPED;
                                current->exit_code = signr;
index 98c533d88b578bdd39526874308d030e8b79fae4..c110ee9081a95f76025606f7a723502bc60cfe4e 100644 (file)
@@ -375,7 +375,7 @@ beyond_if:
        p = (unsigned long) create_aout32_tables((char *)p, bprm);
        current->mm->start_stack = p;
        start_thread32(regs, ex.a_entry, p);
-       if (current->flags & PF_PTRACED)
+       if (current->ptrace & PT_PTRACED)
                send_sig(SIGTRAP, current, 0);
        return 0;
 }
index 3531ae1868e023088b48503c1663763a02a6e5f4..0b04b95157d6bb7146819252172d7e74194fea1f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.62.2.18 2001/01/26 22:26:07 davem Exp $
+/* $Id: ioctl32.c,v 1.62.2.20 2001/05/16 07:28:40 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997  Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
@@ -43,6 +43,7 @@
 #include <linux/blkdev.h>
 #include <linux/in6.h>
 #include <linux/ipv6_route.h>
+#include <linux/pci.h>
 #include <net/sock.h>
 
 #include <scsi/scsi.h>
@@ -492,10 +493,19 @@ static inline int dev_ifconf(unsigned int fd, unsigned long arg)
                        }
                }
                if (!err) {
-                       if (i <= ifc32.ifc_len)
+                       if (ifc32.ifcbuf == 0) {
+                               /* Translate from 64-bit structure multiple to
+                                * a 32-bit one.
+                                */
+                               i = ifc.ifc_len;
+                               i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32));
                                ifc32.ifc_len = i;
-                       else
-                               ifc32.ifc_len = i - sizeof (struct ifreq32);
+                       } else {
+                               if (i <= ifc32.ifc_len)
+                                       ifc32.ifc_len = i;
+                               else
+                                       ifc32.ifc_len = i - sizeof (struct ifreq32);
+                       }
                        if (copy_to_user((struct ifconf32 *)arg, &ifc32, sizeof(struct ifconf32)))
                                err = -EFAULT;
                }
@@ -3136,6 +3146,13 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
        case DRM_IOCTL_FINISH:
 #endif /* DRM */
 
+       /* Misc. */
+       case 0x41545900:                /* ATYIO_CLKR */
+       case 0x41545901:                /* ATYIO_CLKW */
+       case PCIIOC_CONTROLLER:
+       case PCIIOC_MMAP_IS_IO:
+       case PCIIOC_MMAP_IS_MEM:
+       case PCIIOC_WRITE_COMBINE:
 
                error = sys_ioctl (fd, cmd, arg);
                goto out;
index 4e605a57fcc0c52bfb895ae2253d5252e8e793cc..fc5597f844f74318d3bd4aa30b6a84343af6df7f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.76.2.3 2000/03/02 02:03:27 davem Exp $
+/* $Id: irq.c,v 1.76.2.4 2001/06/04 06:51:17 ecd Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
@@ -1048,6 +1048,8 @@ void handler_irq(int irq, struct pt_regs *regs)
                unsigned char flags = bp->flags;
 
                nbp = __bucket(bp->irq_chain);
+               bp->irq_chain = 0;
+
                if((flags & IBF_ACTIVE) != 0) {
                        if((flags & IBF_MULTI) == 0) {
                                struct irqaction *ap = bp->irq_info;
index 6005b969e6662bbcd410c6ca7c8aca32d37130f6..43c7a2871ca90ef241bfbc88c3f0e5820d6fb910 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.92.2.3 1999/12/05 07:24:38 davem Exp $
+/*  $Id: process.c,v 1.92.2.4 2001/06/03 13:41:48 ecd Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -116,6 +116,7 @@ extern char reboot_command [];
 extern void (*prom_palette)(int);
 extern int serial_console;
 #endif
+extern void (*prom_keyboard)(void);
 
 void machine_halt(void)
 {
@@ -126,6 +127,8 @@ void machine_halt(void)
        if (!serial_console && prom_palette)
                prom_palette (1);
 #endif
+       if (prom_keyboard)
+               prom_keyboard();
        prom_halt();
        panic("Halt failed!");
 }
@@ -144,6 +147,8 @@ void machine_restart(char * cmd)
        if (!serial_console && prom_palette)
                prom_palette (1);
 #endif
+       if (prom_keyboard)
+               prom_keyboard();
        if (cmd)
                prom_reboot(cmd);
        if (*reboot_command)
index c64797d180cfee1eb0fc5b59dcb8402a7fd778ce..36c26a32de61c94256da2572b37ca22afb5e7341 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: psycho.c,v 1.85.2.11 2000/10/24 21:00:53 davem Exp $
+/* $Id: psycho.c,v 1.85.2.12 2001/05/16 07:28:41 davem Exp $
  * psycho.c: Ultra/AX U2P PCI controller support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu)
@@ -682,12 +682,26 @@ static inline void pci_add_vma(struct linux_pbm_info *pbm, struct pci_vma *new,
 
 static inline struct pci_vma *pci_vma_alloc(void)
 {
-       return kmalloc(sizeof(struct pci_vma), GFP_ATOMIC);
+       struct pci_vma *vma = kmalloc(sizeof(struct pci_vma), GFP_ATOMIC);
+
+       if (!vma) {
+               prom_printf("PCI: Critical error, cannot allocate PCI_VMA.\n");
+               prom_halt();
+       }
+
+       return vma;
 }
 
 static inline struct pcidev_cookie *pci_devcookie_alloc(void)
 {
-       return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC);
+       struct pcidev_cookie *cookie = kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC);
+
+       if (!cookie) {
+               prom_printf("PCI: Critical error, cannot allocate PCIDEV_COOKIE.\n");
+               prom_halt();
+       }
+
+       return cookie;
 }
 
 
@@ -804,18 +818,48 @@ static void __init apb_init(struct linux_psycho *sabre)
        }
 }
 
+static void __init pci_fixup_host_bridge_self(struct pci_bus *pbus)
+{
+       struct pci_dev *pdev;
+
+       for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+               if (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) {
+                       pbus->self = pdev;
+                       return;
+               }
+       }
+
+       prom_printf("PCI: Critical error, cannot find host bridge PDEV.\n");
+       prom_halt();
+}
+
+static struct pcidev_cookie * __init pci_alloc_hostbridge_cookie(struct linux_pbm_info *pbm)
+{
+       struct pcidev_cookie *cookie = pci_devcookie_alloc();
+
+       memset(cookie, 0, sizeof(*cookie));
+       cookie->pbm = pbm;
+
+       return cookie;
+}
+
 static void __init sabre_probe(struct linux_psycho *sabre)
 {
        struct pci_bus *pbus = sabre->pci_bus;
        static unsigned char busno = 0;
 
+       sabre->pbms_same_domain = 1;
+
        pbus->number = pbus->secondary = busno;
        pbus->sysdata = sabre;
 
        pbus->subordinate = pci_scan_bus(pbus);
        busno = pbus->subordinate + 1;
 
-       for(pbus = pbus->children; pbus; pbus = pbus->next) {
+       pci_fixup_host_bridge_self(pbus);
+       pbus->self->sysdata = pci_alloc_hostbridge_cookie(&sabre->pbm_A);
+
+       for (pbus = pbus->children; pbus; pbus = pbus->next) {
                if (pbus->number == sabre->pbm_A.pci_first_busno)
                        memcpy(&sabre->pbm_A.pci_bus, pbus, sizeof(*pbus));
                if (pbus->number == sabre->pbm_B.pci_first_busno)
@@ -845,6 +889,9 @@ static void __init pbm_probe(struct linux_pbm_info *pbm)
 
        pbus->subordinate = pci_scan_bus(pbus);
 
+       pci_fixup_host_bridge_self(pbus);
+       pbus->self->sysdata = pci_alloc_hostbridge_cookie(pbm);
+
        /*
         * Set the maximum subordinate bus of this pbm.
         */
@@ -2082,6 +2129,8 @@ void __init pcibios_fixup(void)
                if (apb_present(psycho)) {
                        sabre_probe(psycho);
                } else {
+                       psycho->pbms_same_domain = 0;
+
                        /* Probe busses under PBM B. */
                        pbm_probe(&psycho->pbm_B);
 
@@ -2656,4 +2705,148 @@ char * __init pcibios_setup(char *str)
        return str;
 }
 
+/* Platform support for /proc/bus/pci/X/Y mmap()s. */
+
+/* Adjust vm_offset of VMA such that it is the physical page offset corresponding
+ * to the 32-bit pci bus offset for DEV requested by the user.
+ *
+ * Basically, the user finds the base address for his device which he wishes
+ * to mmap.  They read the 32-bit value from the config space base register,
+ * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
+ * offset parameter of mmap on /proc/bus/pci/XXX for that device.
+ *
+ * Returns negative error code on failure, zero on success.
+ */
+static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
+                                            enum pci_mmap_state mmap_state)
+{
+       unsigned long user_offset = vma->vm_offset;
+       unsigned long user32 = user_offset & 0xffffffffUL;
+       unsigned long largest_base, this_base, addr32;
+       int i;
+
+       /* Figure out which base address this is for. */
+       largest_base = 0UL;
+       for (i = 0; i <= 6; i++) {
+               unsigned long base = dev->base_address[i];
+
+               /* Active? */
+               if (!base)
+                       continue;
+
+               /* Same type? */
+               if (i == 6) {
+                       if (mmap_state != pci_mmap_mem)
+                               continue;
+               } else {
+                       if ((mmap_state == pci_mmap_io &&
+                            (base & PCI_BASE_ADDRESS_SPACE_IO) == 0) ||
+                           (mmap_state == pci_mmap_mem &&
+                            (base & PCI_BASE_ADDRESS_SPACE_IO) != 0))
+                               continue;
+               }
+
+               this_base = base;
+
+               addr32 = (this_base & PAGE_MASK) & 0xffffffffUL;
+
+               if (mmap_state == pci_mmap_io)
+                       addr32 &= 0xffffff;
+
+               if (addr32 <= user32 && this_base > largest_base)
+                       largest_base = this_base;
+       }
+
+       if (largest_base == 0UL)
+               return -EINVAL;
+
+       largest_base = __pa(largest_base);
+
+       /* Now construct the final physical address. */
+       if (mmap_state == pci_mmap_io)
+               vma->vm_offset = (((largest_base & ~0xffffffUL) | user32) & PAGE_MASK);
+       else
+               vma->vm_offset = (((largest_base & ~0xffffffffUL) | user32) & PAGE_MASK);
+
+       return 0;
+}
+
+/* Set vm_flags of VMA, as appropriate for this architecture, for a pci device
+ * mapping.
+ */
+static __inline__ void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
+                                           enum pci_mmap_state mmap_state)
+{
+       vma->vm_flags |= (VM_SHM | VM_LOCKED);
+}
+
+/* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
+ * device mapping.
+ */
+static __inline__ void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
+                                            enum pci_mmap_state mmap_state)
+{
+       /* Our io_remap_page_range takes care of this, do nothing. */
+}
+
+extern int io_remap_page_range(unsigned long from, unsigned long offset,
+                              unsigned long size, pgprot_t prot, int space);
+
+/* Perform the actual remap of the pages for a PCI device mapping, as appropriate
+ * for this architecture.  The region in the process to map is described by vm_start
+ * and vm_end members of VMA, the base physical address is found in vm_pgoff.
+ * The pci device structure is provided so that architectures may make mapping
+ * decisions on a per-device or per-bus basis.
+ *
+ * Returns a negative error code on failure, zero on success.
+ */
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+                       enum pci_mmap_state mmap_state,
+                       int write_combine)
+{
+       int ret;
+
+       ret = __pci_mmap_make_offset(dev, vma, mmap_state);
+       if (ret < 0)
+               return ret;
+
+       __pci_mmap_set_flags(dev, vma, mmap_state);
+       __pci_mmap_set_pgprot(dev, vma, mmap_state);
+
+       ret = io_remap_page_range(vma->vm_start,
+                                 (vma->vm_offset |
+                                  (write_combine ? 0x1UL : 0x0UL)),
+                                 vma->vm_end - vma->vm_start, vma->vm_page_prot, 0);
+       if (ret)
+               return ret;
+
+       vma->vm_flags |= VM_IO;
+       return 0;
+}
+
+/* Return the index of the PCI controller for device PDEV. */
+
+int pci_controller_num(struct pci_dev *pdev)
+{
+       struct pcidev_cookie *cookie = pdev->sysdata;
+       int ret;
+
+       if (cookie != NULL) {
+               struct linux_pbm_info *pbm = cookie->pbm;
+
+               if (pbm == NULL || pbm->parent == NULL) {
+                       ret = -ENXIO;
+               } else {
+                       ret = pbm->parent->index;
+                       if (!pbm->parent->pbms_same_domain)
+                               ret = ((ret << 1) +
+                                      ((pbm == &pbm->parent->pbm_B) ? 1 : 0));
+               }
+       } else {
+               ret = -ENXIO;
+       }
+
+       return ret;
+}
+
 #endif
index 9faca032d3adb43f643a8dc1420fa220f64baaf1..c8f0ca0523b0fdce4c0e925675c0407583aa3567 100644 (file)
@@ -569,12 +569,12 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
 #endif
        if(request == PTRACE_TRACEME) {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED) {
+               if (current->ptrace & PT_PTRACED) {
                        pt_error_return(regs, EPERM);
                        goto out;
                }
                /* set the ptrace bit in the process flags. */
-               current->flags |= PF_PTRACED;
+               current->ptrace |= PT_PTRACED;
                pt_succ_return(regs, 0);
                goto out;
        }
@@ -616,11 +616,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
                        goto out;
                }
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED) {
+               if (child->ptrace & PT_PTRACED) {
                        pt_error_return(regs, EPERM);
                        goto out;
                }
-               child->flags |= PF_PTRACED;
+               child->ptrace |= PT_PTRACED;
                write_lock_irqsave(&tasklist_lock, flags);
                if(child->p_pptr != current) {
                        REMOVE_LINKS(child);
@@ -632,7 +632,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
                pt_succ_return(regs, 0);
                goto out;
        }
-       if (!(child->flags & PF_PTRACED)
+       if (!(child->ptrace & PT_PTRACED)
            && ((current->personality & PER_BSD) && (request != PTRACE_SUNATTACH))
            && (!(current->personality & PER_BSD) && (request != PTRACE_ATTACH))) {
                pt_error_return(regs, ESRCH);
@@ -1064,9 +1064,9 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
                }
 
                if (request == PTRACE_SYSCALL)
-                       child->flags |= PF_TRACESYS;
+                       child->ptrace |= PT_TRACESYS;
                else
-                       child->flags &= ~PF_TRACESYS;
+                       child->ptrace &= ~PT_TRACESYS;
 
                child->exit_code = data;
 #ifdef DEBUG_PTRACE
@@ -1104,7 +1104,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
                        pt_error_return(regs, EIO);
                        goto out;
                }
-               child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+               child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
                child->exit_code = data;
 
                write_lock_irqsave(&tasklist_lock, flags);
@@ -1139,8 +1139,8 @@ asmlinkage void syscall_trace(void)
 #ifdef DEBUG_PTRACE
        printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
 #endif
-       if ((current->flags & (PF_PTRACED|PF_TRACESYS))
-                       != (PF_PTRACED|PF_TRACESYS))
+       if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+                       != (PT_PTRACED|PT_TRACESYS))
                return;
        current->exit_code = SIGTRAP;
        current->state = TASK_STOPPED;
index aee6f94651dc50fa49c5d245968505dd5650da1d..c9a2c44a7a418debc841eff7c88fcc0e323bc556 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.43.2.6 2001/04/24 21:58:20 davem Exp $
+/*  $Id: setup.c,v 1.43.2.7 2001/06/03 13:41:48 ecd Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
@@ -65,6 +65,7 @@ struct screen_info screen_info = {
 #if CONFIG_SUN_CONSOLE
 void (*prom_palette)(int);
 #endif
+void (*prom_keyboard)(void);
 asmlinkage void sys_sync(void);        /* it's really int */
 
 static void
index 7ac8f8a4ab7bd5c4e352a3587af8f4cb706894e4..8ad3e71ce343d5976d6f2986fa3e7ef5ea991afc 100644 (file)
@@ -850,7 +850,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
                
                if (!signr) break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
                        notify_parent(current, SIGCHLD);
@@ -906,7 +906,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
                                        continue;
 
                        case SIGSTOP:
-                               if (current->flags & PF_PTRACED)
+                               if (current->ptrace & PT_PTRACED)
                                        continue;
                                current->state = TASK_STOPPED;
                                current->exit_code = signr;
index a61a06c9081bd668f1cc4f68002f8d9ee592955b..688e4b6ee9c1a99cc5dd701710a973cebac84d3b 100644 (file)
@@ -1279,7 +1279,7 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs * regs,
                
                if (!signr) break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
                        notify_parent(current, SIGCHLD);
@@ -1335,7 +1335,7 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs * regs,
                                        continue;
 
                        case SIGSTOP:
-                               if (current->flags & PF_PTRACED)
+                               if (current->ptrace & PT_PTRACED)
                                        continue;
                                current->state = TASK_STOPPED;
                                current->exit_code = signr;
index e64932fe6d6acef2d4d9a316c92a3e106a165a59..5ae03bcc77fc9736189a6077081d82d3c0e61eb0 100644 (file)
@@ -125,7 +125,7 @@ typedef struct idefloppy_packet_command_s {
        byte *current_position;                 /* Pointer into the above buffer */
        void (*callback) (ide_drive_t *);       /* Called when this packet command is completed */
        byte pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE];       /* Temporary buffer */
-       unsigned int flags;                     /* Status/Action bit flags */
+       unsigned long flags;                    /* Status/Action bit flags */
 } idefloppy_pc_t;
 
 /*
@@ -259,7 +259,7 @@ typedef struct {
        idefloppy_flexible_disk_page_t flexible_disk_page;      /* Copy of the flexible disk page */
        int wp;                                                 /* Write protect */
 
-       unsigned int flags;                     /* Status/Action flags */
+       unsigned long flags;                    /* Status/Action flags */
 } idefloppy_floppy_t;
 
 /*
index 2da87e63b96c9a676f720e96c87db70f82185670..750c45bbb23541f391f5ece7138dfcf1725cceed 100644 (file)
@@ -966,7 +966,7 @@ static int parport_pc_init_pci (int irq, int dma)
                printk (KERN_INFO
                        "Unknown PCI parallel I/O card (%04x/%04x)\n"
                        "Please send 'lspci' output to "
-                       "tim@cyberelk.demon.co.uk\n",
+                       "tim@cyberelk.net\n",
                        pcidev->vendor, pcidev->device);
        }
 #endif
index 03270e5725c8a606ec84ad441bc68d792f6dadfe..5b0db5de897e1af019c964945308b6c232bdcf5a 100644 (file)
@@ -1425,8 +1425,11 @@ static void set_rx_mode(struct device *dev)
                rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
                mc_filter[1] = mc_filter[0] = 0;
                for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
-                        i++, mclist = mclist->next)
-                       set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26, mc_filter);
+                        i++, mclist = mclist->next) {
+                       int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
+
+                       mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));
+               }
        }
        /* We can safely update without stopping the chip. */
        outb(rx_mode, ioaddr + RxConfig);
index a5043a7f41ac653e7740ea074ba2818f5127bf69..fd5129ab1c0f2f45af450623834d572835e32a12 100644 (file)
@@ -89,7 +89,7 @@ struct slip {
   int                  xdata, xbits;   /* 6 bit slip controls          */
 #endif
 
-  unsigned int         flags;          /* Flag values/ mode etc        */
+  unsigned long                flags;          /* Flag values/ mode etc        */
 #define SLF_INUSE      0               /* Channel in use               */
 #define SLF_ESCAPE     1               /* ESC received                 */
 #define SLF_ERROR      2               /* Parity, etc. error           */
index 0a2da1802c38a27e429ce721c550249ffcb15b95..4b0870e42e9f0806222efcc0242080c7de23225f 100644 (file)
@@ -505,8 +505,10 @@ badreq:
                }
                /* Send Configure-Ack packet. */
                sp->pp_loopcnt = 0;
-               sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK,
-                               h->ident, len-4, h+1);
+               if (sp->lcp.state != LCP_STATE_OPENED) {
+                       sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK,
+                                       h->ident, len-4, h+1);
+               }
                /* Change the state. */
                switch (sp->lcp.state) {
                case LCP_STATE_CLOSED:
@@ -522,7 +524,9 @@ badreq:
                        sp->ipcp.state = IPCP_STATE_CLOSED;
                        /* Initiate renegotiation. */
                        sppp_lcp_open (sp);
-                       /* An ACK has already been sent. */
+                       /* Send ACK after our REQ in attempt to break loop */
+                       sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK,
+                                       h->ident, len-4, h+1);
                        sp->lcp.state = LCP_STATE_ACK_SENT;
                        break;
                }
index d1a78fe53feb9364c6e395749b078daf8e33b746..6472da1b65c9c20fccb7c9a04d5bb2ed8147d1c5 100644 (file)
@@ -195,18 +195,117 @@ proc_bus_pci_write(struct file *file, const char *buf, size_t nbytes, loff_t *pp
        return nbytes;
 }
 
+struct pci_filp_private {
+       enum pci_mmap_state mmap_state;
+       int write_combine;
+};
+
+static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       const struct proc_dir_entry *dp = inode->u.generic_ip;
+       struct pci_dev *dev = dp->data;
+#ifdef HAVE_PCI_MMAP
+       struct pci_filp_private *fpriv = file->private_data;
+#endif /* HAVE_PCI_MMAP */
+       int ret = 0;
+
+       switch (cmd) {
+       case PCIIOC_CONTROLLER:
+               ret = pci_controller_num(dev);
+               break;
+
+#ifdef HAVE_PCI_MMAP
+       case PCIIOC_MMAP_IS_IO:
+               fpriv->mmap_state = pci_mmap_io;
+               break;
+
+       case PCIIOC_MMAP_IS_MEM:
+               fpriv->mmap_state = pci_mmap_mem;
+               break;
+
+       case PCIIOC_WRITE_COMBINE:
+               if (arg)
+                       fpriv->write_combine = 1;
+               else
+                       fpriv->write_combine = 0;
+               break;
+
+#endif /* HAVE_PCI_MMAP */
+
+       default:
+               ret = -EINVAL;
+               break;
+       };
+
+       return ret;
+}
+
+#ifdef HAVE_PCI_MMAP
+static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct inode *inode = file->f_dentry->d_inode;
+       const struct proc_dir_entry *dp = inode->u.generic_ip;
+       struct pci_dev *dev = dp->data;
+       struct pci_filp_private *fpriv = file->private_data;
+       int ret;
+
+       if (!capable(CAP_SYS_RAWIO))
+               return -EPERM;
+
+       ret = pci_mmap_page_range(dev, vma,
+                                 fpriv->mmap_state,
+                                 fpriv->write_combine);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int proc_bus_pci_open(struct inode *inode, struct file *file)
+{
+       struct pci_filp_private *fpriv = kmalloc(sizeof(*fpriv), GFP_KERNEL);
+
+       if (!fpriv)
+               return -ENOMEM;
+
+       fpriv->mmap_state = pci_mmap_io;
+       fpriv->write_combine = 0;
+
+       file->private_data = fpriv;
+
+       return 0;
+}
+
+static int proc_bus_pci_release(struct inode *inode, struct file *file)
+{
+       kfree(file->private_data);
+       file->private_data = NULL;
+
+       return 0;
+}
+#endif /* HAVE_PCI_MMAP */
+
 static struct file_operations proc_bus_pci_operations = {
        proc_bus_pci_lseek,
        proc_bus_pci_read,
        proc_bus_pci_write,
-       NULL,           /* readdir */
-       NULL,           /* poll */
-       NULL,           /* ioctl */
-       NULL,           /* mmap */
-       NULL,           /* no special open code */
-       NULL,           /* flush */
-       NULL,           /* no special release code */
-       NULL            /* can't fsync */
+       NULL,                           /* readdir */
+       NULL,                           /* poll */
+       proc_bus_pci_ioctl,             /* ioctl */
+#ifdef HAVE_PCI_MMAP
+       proc_bus_pci_mmap,              /* mmap */
+       proc_bus_pci_open,              /* open code */
+#else
+       NULL,                           /* mmap */
+       NULL,                           /* no special open code */
+#endif
+       NULL,                           /* flush */
+#ifdef HAVE_PCI_MMAP
+       proc_bus_pci_release,           /* release code */
+#else
+       NULL,                           /* no special release code */
+#endif
+       NULL                            /* can't fsync */
 };
 
 static struct inode_operations proc_bus_pci_inode_operations = {
index 1998d43badeb154ead20796c1226f64ca5b3f144..e06f2a4d16387211d3ebafb6b3dc8d97bbdda2c7 100644 (file)
@@ -1556,33 +1556,58 @@ printk("aurora_write: start %d\n",count);
        if (!tty || !port->xmit_buf || !tmp_buf)
                return 0;
 
-       if (from_user)
+       save_flags(flags);
+       if (from_user) {
                down(&tmp_buf_sem);
+               while (1) {
+                       c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+                                          SERIAL_XMIT_SIZE - port->xmit_head));
+                       if (c <= 0)
+                               break;
 
-       save_flags(flags);
-       while (1) {
-               cli();          
-               c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-                                  SERIAL_XMIT_SIZE - port->xmit_head));
-               if (c <= 0)
-                       break;
+                       c -= copy_from_user(tmp_buf, buf, c);
+                       if (!c) {
+                               if (!total)
+                                       total = -EFAULT;
+                               break;
+                       }
 
-               if (from_user) {
-                       copy_from_user(tmp_buf, buf, c);
+                       cli();          
                        c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
                                       SERIAL_XMIT_SIZE - port->xmit_head));
                        memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
-               } else
+                       port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+                       port->xmit_cnt += c;
+                       restore_flags(flags);
+
+                       buf += c;
+                       count -= c;
+                       total += c;
+               }
+               up(&tmp_buf_sem);
+       } else {
+               while (1) {
+                       cli();          
+                       c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+                                          SERIAL_XMIT_SIZE - port->xmit_head));
+                       if (c <= 0) {
+                               restore_flags(flags);
+                               break;
+                       }
+
                        memcpy(port->xmit_buf + port->xmit_head, buf, c);
-               port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-               port->xmit_cnt += c;
-               restore_flags(flags);
-               buf += c;
-               count -= c;
-               total += c;
+                       port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+                       port->xmit_cnt += c;
+                       restore_flags(flags);
+
+                       buf += c;
+                       count -= c;
+                       total += c;
+               }
        }
-       if (from_user)
-               up(&tmp_buf_sem);
+
+
+       cli();
        if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
            !(port->SRER & SRER_TXRDY)) {
                port->SRER |= SRER_TXRDY;
index 1cd1ea50ad84f8de33ee45761067abac7f339e47..25c576c9a2ee38c414f0137726cf22b8da1d0a9e 100644 (file)
@@ -243,7 +243,7 @@ struct Aurora_port {
        struct tty_struct       * tty;
        int                     count;
        int                     blocked_open;
-       int                     event;
+       long                    event;
        int                     timeout;
        int                     close_delay;
        long                    session;
index abc0dfd1873b3a809b6ae1af6709e26fb413fa38..ee849b5bc2b708ded58f760c4d2fd0673cb77a33 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.27.2.2 2000/01/21 01:05:45 davem Exp $
+/* $Id: pcikbd.c,v 1.27.2.4 2001/06/03 13:41:48 ecd Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -48,6 +48,7 @@
 static int pcikbd_mrcoffee = 0;
 #else
 #define pcikbd_mrcoffee 0
+extern void (*prom_keyboard)(void);
 #endif
 
 static unsigned long pcikbd_iobase = 0;
@@ -58,6 +59,9 @@ static volatile unsigned char reply_expected = 0;
 static volatile unsigned char acknowledge = 0;
 static volatile unsigned char resend = 0;
 
+static void pcikbd_write(int address, int data);
+static int pcikbd_wait_for_input(void);
+
 unsigned char pckbd_read_mask = KBD_STAT_OBF;
 
 extern int pcikbd_init(void);
@@ -250,7 +254,7 @@ int pcikbd_getkeycode(unsigned int scancode)
                e0_keys[scancode - 128];
 }
 
-int do_acknowledge(unsigned char scancode)
+static int do_acknowledge(unsigned char scancode)
 {
        if(reply_expected) {
                if(scancode == KBD_REPLY_ACK) {
@@ -266,10 +270,87 @@ int do_acknowledge(unsigned char scancode)
        return 1;
 }
 
+#ifdef __sparc_v9__
+static void pcikbd_enter_prom(void)
+{
+       pcikbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);
+       if(pcikbd_wait_for_input() != KBD_REPLY_ACK)
+               printk("Prom Enter: Disable keyboard: no ACK\n");
+
+       /* Disable PC scancode translation */
+       pcikbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);
+       pcikbd_write(KBD_DATA_REG, KBD_MODE_SYS);
+       pcikbd_write(KBD_DATA_REG, KBD_CMD_ENABLE);
+       if (pcikbd_wait_for_input() != KBD_REPLY_ACK)
+               printk("Prom Enter: Enable Keyboard: no ACK\n");
+}
+#endif
+
+static void ctrl_break(void)
+{
+       extern int stop_a_enabled;
+       unsigned long timeout;
+       int status, data;
+       int mode;
+
+       if (!stop_a_enabled)
+               return;
+
+       pcikbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);
+       if(pcikbd_wait_for_input() != KBD_REPLY_ACK)
+               printk("Prom Enter: Disable keyboard: no ACK\n");
+
+       /* Save current mode register settings */
+       pcikbd_write(KBD_CNTL_REG, KBD_CCMD_READ_MODE);
+       if ((mode = pcikbd_wait_for_input()) == -1)
+               printk("Prom Enter: Read Mode: no ACK\n");
+
+       /* Disable PC scancode translation */
+       pcikbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);
+       pcikbd_write(KBD_DATA_REG, mode & ~(KBD_MODE_KCC));
+       pcikbd_write(KBD_DATA_REG, KBD_CMD_ENABLE);
+       if (pcikbd_wait_for_input() != KBD_REPLY_ACK)
+               printk("Prom Enter: Enable Keyboard: no ACK\n");
+
+       /* Drop into OBP.
+        * Note that we must flush the user windows
+        * first before giving up control.
+        */
+        flush_user_windows();
+       prom_cmdline();
+
+       /* Read prom's key up event (use short timeout) */
+       do {
+               timeout = 10;
+               do {
+                       mdelay(1);
+                       status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
+                       if (!(status & KBD_STAT_OBF))
+                               continue;
+                       data = pcikbd_inb(pcikbd_iobase + KBD_DATA_REG);
+                       if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
+                               continue;
+                       break;
+               } while (--timeout > 0);
+       } while (timeout > 0);
+
+       /* Reenable PC scancode translation */
+       pcikbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);
+       if(pcikbd_wait_for_input() != KBD_REPLY_ACK)
+               printk("Prom Leave: Disable keyboard: no ACK\n");
+
+       pcikbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);
+       pcikbd_write(KBD_DATA_REG, mode);
+       pcikbd_write(KBD_DATA_REG, KBD_CMD_ENABLE);
+       if (pcikbd_wait_for_input() != KBD_REPLY_ACK)
+               printk("Prom Enter: Enable Keyboard: no ACK\n");
+}
+
 int pcikbd_translate(unsigned char scancode, unsigned char *keycode,
                     char raw_mode)
 {
        static int prev_scancode = 0;
+       int down = scancode & 0x80 ? 0 : 1;
 
        if (scancode == 0xe0 || scancode == 0xe1) {
                prev_scancode = scancode;
@@ -308,6 +389,18 @@ int pcikbd_translate(unsigned char scancode, unsigned char *keycode,
 
        } else
                *keycode = scancode;
+
+       if (*keycode == E0_BREAK) {
+               if (down)
+                       return 0;
+
+               /* Handle ctrl-break event */
+               ctrl_break();
+
+               /* Send ctrl up event to the keyboard driver */
+               *keycode = 0x1d;
+       }
+
        return 1;
 }
 
@@ -367,7 +460,7 @@ void pcikbd_leds(unsigned char leds)
                
 }
 
-__initfunc(static int pcikbd_wait_for_input(void))
+static int pcikbd_wait_for_input(void)
 {
        int status, data;
        unsigned long start = jiffies;
@@ -384,7 +477,7 @@ __initfunc(static int pcikbd_wait_for_input(void))
        return -1;
 }
 
-__initfunc(static void pcikbd_write(int address, int data))
+static void pcikbd_write(int address, int data)
 {
        int status;
 
@@ -570,6 +663,8 @@ ebus_done:
                printk("8042(speaker): iobase[%016lx]%s\n", pcibeep_iobase,
                       edev ? "" : " (forced)");
        }
+
+       prom_keyboard = pcikbd_enter_prom;
 #endif
 
        disable_irq(pcikbd_irq);
index c1b8131b82ee0352669688264cf8231bed589a38..4a8e7b55b61069760c7b6850b82610220d366448 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.30.2.4 2000/05/27 04:46:34 davem Exp $
+/* $Id: sab82532.c,v 1.30.2.7 2001/05/29 06:17:24 ecd Exp $
  * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -54,9 +54,12 @@ static int sab82532_refcount;
 /* Set of debugging defines */
 #undef SERIAL_DEBUG_OPEN
 #undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_MODEM
 #undef SERIAL_DEBUG_WAIT_UNTIL_SENT
 #undef SERIAL_DEBUG_SEND_BREAK
 #undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_FIFO
+#define SERIAL_DEBUG_OVERFLOW 1
 
 /* Trace things on serial device, useful for console debugging: */
 #undef SERIAL_LOG_DEVICE
@@ -194,10 +197,14 @@ static __inline__ void sab82532_start_tx(struct sab82532 *info)
        if (info->xmit_cnt <= 0)
                goto out;
 
-       if (!(info->regs->r.star & SAB82532_STAR_XFW))
+       if (!test_bit(SAB82532_XPR, &info->irqflags))
                goto out;
 
-       info->all_sent = 0;
+       info->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS);
+       info->regs->w.imr1 = info->interrupt_mask1;
+       clear_bit(SAB82532_ALLS, &info->irqflags);
+
+       clear_bit(SAB82532_XPR, &info->irqflags);
        for (i = 0; i < info->xmit_fifo_size; i++) {
                info->regs->w.xfifo[i] = info->xmit_buf[info->xmit_tail++];
                info->xmit_tail &= (SERIAL_XMIT_SIZE - 1);
@@ -318,15 +325,15 @@ static void batten_down_hatches(struct sab82532 *info)
  * This routine is used by the interrupt handler to schedule
  * processing in the software interrupt portion of the driver.
  */
-static inline void sab82532_sched_event(struct sab82532 *info, int event)
+static void sab82532_sched_event(struct sab82532 *info, int event)
 {
        info->event |= 1 << event;
        queue_task(&info->tqueue, &tq_serial);
        mark_bh(SERIAL_BH);
 }
 
-static inline void receive_chars(struct sab82532 *info,
-                                union sab82532_irq_status *stat)
+static void receive_chars(struct sab82532 *info,
+                         union sab82532_irq_status *stat)
 {
        struct tty_struct *tty = info->tty;
        unsigned char buf[32];
@@ -353,7 +360,7 @@ static inline void receive_chars(struct sab82532 *info,
        }
 
        if (stat->sreg.isr0 & SAB82532_ISR0_RFO) {
-#if 1
+#ifdef SERIAL_DEBUG_OVERFLOW
                printk("sab82532: receive_chars: RFO");
 #endif
                free_fifo++;
@@ -377,7 +384,7 @@ static inline void receive_chars(struct sab82532 *info,
 
        for (i = 0; i < count; ) {
                if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-#if 1
+#ifdef SERIAL_DEBUG_OVERFLOW
                        printk("sab82532: receive_chars: tty overrun\n");
 #endif
                        info->icount.buf_overrun++;
@@ -411,16 +418,29 @@ static inline void receive_chars(struct sab82532 *info,
        queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-static inline void transmit_chars(struct sab82532 *info,
-                                 union sab82532_irq_status *stat)
+static void transmit_chars(struct sab82532 *info,
+                          union sab82532_irq_status *stat)
 {
        int i;
 
-       if (stat->sreg.isr1 & SAB82532_ISR1_ALLS)
-               info->all_sent = 1;
-       if (!(info->regs->r.star & SAB82532_STAR_XFW))
+       if (stat->sreg.isr1 & SAB82532_ISR1_ALLS) {
+               info->interrupt_mask1 |= SAB82532_IMR1_ALLS;
+               info->regs->w.imr1 = info->interrupt_mask1;
+               set_bit(SAB82532_ALLS, &info->irqflags);
+       }
+
+       if (!(stat->sreg.isr1 & SAB82532_ISR1_XPR))
                return;
 
+       if (!(info->regs->r.star & SAB82532_STAR_XFW)) {
+#ifdef SERIAL_DEBUG_FIFO
+               printk("%s: XPR, but no XFW (???)\n", __FUNCTION__);
+#endif
+               return;
+       }
+
+       set_bit(SAB82532_XPR, &info->irqflags);
+
        if (!info->tty) {
                info->interrupt_mask1 |= SAB82532_IMR1_XPR;
                info->regs->w.imr1 = info->interrupt_mask1;
@@ -434,8 +454,12 @@ static inline void transmit_chars(struct sab82532 *info,
                return;
        }
 
+       info->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS);
+       info->regs->w.imr1 = info->interrupt_mask1;
+       clear_bit(SAB82532_ALLS, &info->irqflags);
+
        /* Stuff 32 bytes into Transmit FIFO. */
-       info->all_sent = 0;
+       clear_bit(SAB82532_XPR, &info->irqflags);
        for (i = 0; i < info->xmit_fifo_size; i++) {
                info->regs->w.xfifo[i] = info->xmit_buf[info->xmit_tail++];
                info->xmit_tail &= (SERIAL_XMIT_SIZE - 1);
@@ -455,14 +479,10 @@ static inline void transmit_chars(struct sab82532 *info,
 #ifdef SERIAL_DEBUG_INTR
        printk("THRE...");
 #endif
-       if (info->xmit_cnt <= 0) {
-               info->interrupt_mask1 |= SAB82532_IMR1_XPR;
-               info->regs->w.imr1 = info->interrupt_mask1;
-       }
 }
 
-static inline void check_status(struct sab82532 *info,
-                               union sab82532_irq_status *stat)
+static void check_status(struct sab82532 *info,
+                        union sab82532_irq_status *stat)
 {
        struct tty_struct *tty = info->tty;
        int modem_change = 0;
@@ -501,7 +521,7 @@ check_modem:
                info->dcd = (info->regs->r.vstr & SAB82532_VSTR_CD) ? 0 : 1;
                info->icount.dcd++;
                modem_change++;
-#if 0
+#ifdef SERIAL_DEBUG_MODEM
                printk("DCD change: %d\n", info->icount.dcd);
 #endif
        }
@@ -509,7 +529,7 @@ check_modem:
                info->cts = info->regs->r.star & SAB82532_STAR_CTS;
                info->icount.cts++;
                modem_change++;
-#if 0
+#ifdef SERIAL_DEBUG_MODEM
                printk("CTS change: %d, CTS %s\n", info->icount.cts, info->cts ? "on" : "off");
 #endif
        }
@@ -517,7 +537,7 @@ check_modem:
                info->dsr = (info->regs->r.pvr & info->pvr_dsr_bit) ? 0 : 1;
                info->icount.dsr++;
                modem_change++;
-#if 0
+#ifdef SERIAL_DEBUG_MODEM
                printk("DSR change: %d\n", info->icount.dsr);
 #endif
        }
@@ -808,15 +828,19 @@ static int startup(struct sab82532 *info)
        info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
                                SAB82532_IMR0_PLLA;
        info->regs->w.imr0 = info->interrupt_mask0;
-       info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_XOFF |
-                               SAB82532_IMR1_TIN | SAB82532_IMR1_XON |
+       info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS |
+                               SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN |
+                               SAB82532_IMR1_CSC | SAB82532_IMR1_XON |
                                SAB82532_IMR1_XPR;
        info->regs->w.imr1 = info->interrupt_mask1;
+       set_bit(SAB82532_ALLS, &info->irqflags);
 
        if (info->tty)
                clear_bit(TTY_IO_ERROR, &info->tty->flags);
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 
+       set_bit(SAB82532_XPR, &info->irqflags);
+
        /*
         * and set the speed of the serial port
         */
@@ -1019,10 +1043,14 @@ static void change_speed(struct sab82532 *info)
                info->regs->rw.mode &= ~(SAB82532_MODE_RTS);
                info->regs->rw.mode |= SAB82532_MODE_FRTS;
                info->regs->rw.mode &= ~(SAB82532_MODE_FCTS);
+               info->interrupt_mask1 &= ~(SAB82532_IMR1_CSC);
+               info->regs->w.imr1 = info->interrupt_mask1;
        } else {
                info->regs->rw.mode |= SAB82532_MODE_RTS;
                info->regs->rw.mode &= ~(SAB82532_MODE_FRTS);
                info->regs->rw.mode |= SAB82532_MODE_FCTS;
+               info->interrupt_mask1 |= SAB82532_IMR1_CSC;
+               info->regs->w.imr1 = info->interrupt_mask1;
        }
        info->regs->rw.mode |= SAB82532_MODE_RAC;
        restore_flags(flags);
@@ -1204,10 +1232,11 @@ static void sab82532_throttle(struct tty_struct * tty)
        
        if (I_IXOFF(tty))
                sab82532_send_xchar(tty, STOP_CHAR(tty));
-#if 0
-       if (tty->termios->c_cflag & CRTSCTS)
-               info->regs->rw.mode |= SAB82532_MODE_RTS;
-#endif
+
+       if (tty->termios->c_cflag & CRTSCTS) {
+               info->regs->rw.mode &= ~(SAB82532_MODE_FRTS |
+                                        SAB82532_MODE_RTS);
+       }
 }
 
 static void sab82532_unthrottle(struct tty_struct * tty)
@@ -1230,10 +1259,12 @@ static void sab82532_unthrottle(struct tty_struct * tty)
                        sab82532_send_xchar(tty, START_CHAR(tty));
        }
 
-#if 0
-       if (tty->termios->c_cflag & CRTSCTS)
-               info->regs->rw.mode &= ~(SAB82532_MODE_RTS);
-#endif
+       if (tty->termios->c_cflag & CRTSCTS) {
+               u8 mode = info->regs->r.mode;
+               mode &= ~(SAB82532_MODE_RTS);
+               mode |= SAB82532_MODE_FRTS;
+               info->regs->w.mode = mode;
+       }
 }
 
 /*
@@ -1287,7 +1318,8 @@ static int get_lsr_info(struct sab82532 * info, unsigned int *value)
 {
        unsigned int result;
 
-       result = (!info->xmit_buf && info->all_sent) ? TIOCSER_TEMT : 0;
+       result = (!info->xmit_buf && test_bit(SAB82532_ALLS, &info->irqflags))
+                                                       ? TIOCSER_TEMT : 0;
        return put_user(result, value);
 }
 
@@ -1515,10 +1547,19 @@ static void sab82532_set_termios(struct tty_struct *tty,
        if (!(old_termios->c_cflag & CBAUD) &&
            (tty->termios->c_cflag & CBAUD)) {
                info->regs->w.pvr &= ~(info->pvr_dtr_bit);
-               if (!tty->hw_stopped ||
-                   !(tty->termios->c_cflag & CRTSCTS)) {
-                       info->regs->w.mode &= ~(SAB82532_MODE_FRTS);
-                       info->regs->w.mode |= SAB82532_MODE_RTS;
+               if (!tty->hw_stopped) {
+                       u8 mode = info->regs->r.mode;
+                       if (tty->termios->c_cflag & CRTSCTS) {
+                               mode &= ~(SAB82532_MODE_RTS);
+                               mode |= SAB82532_MODE_FRTS;
+                       } else if (test_bit(TTY_THROTTLED, &tty->flags)) {
+                               mode &= ~(SAB82532_MODE_FRTS |
+                                         SAB82532_MODE_RTS);
+                       } else {
+                               mode &= ~(SAB82532_MODE_FRTS);
+                               mode |= SAB82532_MODE_RTS;
+                       }
+                       info->regs->w.mode = mode;
                }
        }
        
@@ -1528,18 +1569,6 @@ static void sab82532_set_termios(struct tty_struct *tty,
                tty->hw_stopped = 0;
                sab82532_start(tty);
        }
-
-#if 0
-       /*
-        * No need to wake up processes in open wait, since they
-        * sample the CLOCAL flag once, and don't recheck it.
-        * XXX  It's not clear whether the current behavior is correct
-        * or not.  Hence, this may change.....
-        */
-       if (!(old_termios->c_cflag & CLOCAL) &&
-           (tty->termios->c_cflag & CLOCAL))
-               wake_up_interruptible(&info->open_wait);
-#endif
 }
 
 /*
@@ -1617,9 +1646,6 @@ static void sab82532_close(struct tty_struct *tty, struct file * filp)
         */
        info->interrupt_mask0 |= SAB82532_IMR0_TCD;
        info->regs->w.imr0 = info->interrupt_mask0;
-#if 0
-       info->regs->rw.mode &= ~(SAB82532_MODE_RAC);
-#endif
        if (info->flags & ASYNC_INITIALIZED) {
                /*
                 * Before we drop DTR, make sure the UART transmitter
@@ -1661,7 +1687,6 @@ static void sab82532_wait_until_sent(struct tty_struct *tty, int timeout)
        if (serial_paranoia_check(info,tty->device,"sab82532_wait_until_sent"))
                return;
 
-       orig_jiffies = jiffies;
        /*
         * Set the check interval to be 1/5 of the estimated time to
         * send a single character, and make it at least 1.  The check
@@ -1677,10 +1702,14 @@ static void sab82532_wait_until_sent(struct tty_struct *tty, int timeout)
        if (timeout)
          char_time = MIN(char_time, timeout);
 #ifdef SERIAL_DEBUG_WAIT_UNTIL_SENT
-       printk("In sab82532_wait_until_sent(%d) check=%lu...", timeout, char_time);
-       printk("jiff=%lu...", jiffies);
+       printk("In sab82532_wait_until_sent(%d) check=%lu "
+              "xmit_cnt = %ld, alls = %d (jiff=%lu)...\n",
+              timeout, char_time, info->xmit_cnt,
+              test_bit(SAB82532_ALLS, &info->irqflags), jiffies);
 #endif
-       while (info->xmit_cnt || !info->all_sent) {
+       orig_jiffies = jiffies;
+       while (info->xmit_cnt ||
+              !test_bit(SAB82532_ALLS, &info->irqflags)) {
                current->state = TASK_INTERRUPTIBLE;
                current->counter = 0;
                schedule_timeout(char_time);
@@ -1691,7 +1720,9 @@ static void sab82532_wait_until_sent(struct tty_struct *tty, int timeout)
        }
        current->state = TASK_RUNNING;
 #ifdef SERIAL_DEBUG_WAIT_UNTIL_SENT
-       printk("xmit_cnt = %d, alls = %d (jiff=%lu)...done\n", info->xmit_cnt, info->all_sent, jiffies);
+       printk("xmit_cnt = %d, alls = %d (jiff=%lu)...done\n",
+              info->xmit_cnt, test_bit(SAB82532_ALLS, &info->irqflags),
+              jiffies);
 #endif
 }
 
@@ -2146,7 +2177,7 @@ sab82532_kgdb_hook(int line))
 
 __initfunc(static inline void show_serial_version(void))
 {
-       char *revision = "$Revision: 1.30.2.4 $";
+       char *revision = "$Revision: 1.30.2.7 $";
        char *version, *p;
 
        version = strchr(revision, ' ');
index 7a19ea21401147c08e16c3e38a18d3e5e3df8cc7..779ed14f5679c83d4a0dfe235e69164b4200b681 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.18.2.7 2000/05/27 04:46:34 davem Exp $
+/* $Id: su.c,v 1.18.2.8 2001/05/16 08:37:26 davem Exp $
  * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -1410,6 +1410,41 @@ su_unthrottle(struct tty_struct * tty)
  * ------------------------------------------------------------
  */
 
+/*
+ * get_serial_info - handle TIOCGSERIAL ioctl()
+ *
+ * Purpose: Return standard serial struct information about
+ *          a serial port handled by this driver.
+ *
+ * Added:   11-May-2001 Lars Kellogg-Stedman <lars@larsshack.org>
+ */
+static int get_serial_info(struct su_struct * info,
+                          struct serial_struct * retinfo)
+{
+       struct serial_struct    tmp;
+
+       if (!retinfo)
+               return -EFAULT;
+       memset(&tmp, 0, sizeof(tmp));
+
+       tmp.type                = info->type;
+       tmp.line                = info->line;
+       tmp.port                = info->port;
+       tmp.irq                 = info->irq;
+       tmp.flags               = info->flags;
+       tmp.xmit_fifo_size      = info->xmit_fifo_size;
+       tmp.baud_base           = info->baud_base;
+       tmp.close_delay         = info->close_delay;
+       tmp.closing_wait        = info->closing_wait;
+       tmp.custom_divisor      = info->custom_divisor;
+       tmp.hub6                = 0;
+
+       if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+               return -EFAULT;
+
+       return 0;
+}
+
 /*
  * get_lsr_info - get line status register info
  *
@@ -1568,6 +1603,9 @@ su_ioctl(struct tty_struct *tty, struct file * file,
                case TIOCMSET:
                        return set_modem_info(info, cmd, (unsigned int *) arg);
 
+               case TIOCGSERIAL:
+                       return get_serial_info(info, (struct serial_struct *)arg);
+
                case TIOCSERGETLSR: /* Get line status register */
                        return get_lsr_info(info, (unsigned int *) arg);
 
@@ -2226,7 +2264,7 @@ done:
  */
 __initfunc(static __inline__ void show_su_version(void))
 {
-       char *revision = "$Revision: 1.18.2.7 $";
+       char *revision = "$Revision: 1.18.2.8 $";
        char *version, *p;
 
        version = strchr(revision, ' ');
index ed69458afcbfc775407fdf5df317371e5fbd997c..d0169529a9dad2f96a83d3f3138b98110dd9665f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.41.2.8 2001/04/17 07:14:47 davem Exp $
+/* $Id: zs.c,v 1.41.2.9 2001/05/09 07:47:10 davem Exp $
  * zs.c: Zilog serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1109,28 +1109,53 @@ static int zs_write(struct tty_struct * tty, int from_user,
                return 0;
 
        save_flags(flags);
-       while (1) {
-               cli();          
-               c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-                                  SERIAL_XMIT_SIZE - info->xmit_head));
-               if (c <= 0)
-                       break;
+       if (from_user) {
+               down(&tmp_buf_sem);
+               while (1) {
+                       c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                                          SERIAL_XMIT_SIZE - info->xmit_head));
+                       if (c <= 0)
+                               break;
+
+                       c -= copy_from_user(tmp_buf, buf, c);
+                       if (!c) {
+                               if (!total)
+                                       total = -EFAULT;
+                               break;
+                       }
 
-               if (from_user) {
-                       down(&tmp_buf_sem);
-                       copy_from_user(tmp_buf, buf, c);
+                       cli();          
                        c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
                                       SERIAL_XMIT_SIZE - info->xmit_head));
                        memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
-                       up(&tmp_buf_sem);
-               } else
+                       info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+                       info->xmit_cnt += c;
+                       restore_flags(flags);
+
+                       buf += c;
+                       count -= c;
+                       total += c;
+               }
+               up(&tmp_buf_sem);
+       } else {
+               while (1) {
+                       cli();
+                       c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                                          SERIAL_XMIT_SIZE - info->xmit_head));
+                       if (c <= 0) {
+                               restore_flags(flags);
+                               break;
+                       }
+
                        memcpy(info->xmit_buf + info->xmit_head, buf, c);
-               info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-               info->xmit_cnt += c;
-               restore_flags(flags);
-               buf += c;
-               count -= c;
-               total += c;
+                       info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+                       info->xmit_cnt += c;
+                       restore_flags(flags);
+
+                       buf += c;
+                       count -= c;
+                       total += c;
+               }
        }
 
        cli();          
@@ -1856,7 +1881,7 @@ int zs_open(struct tty_struct *tty, struct file * filp)
 
 static void show_serial_version(void)
 {
-       char *revision = "$Revision: 1.41.2.8 $";
+       char *revision = "$Revision: 1.41.2.9 $";
        char *version, *p;
 
        version = strchr(revision, ' ');
index 777556537f7a154990052f4e8f33f149e18798f4..395b77aa9b900da3393f7bdd57a8d5726d7fe58f 100644 (file)
@@ -5,7 +5,6 @@
    Modifications By: Joel Jacobson <linux@3ware.com>
                     Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 
-
    Copyright (C) 1999-2001 3ware Inc.
 
    Kernel compatablity By:     Andre Hedrick <andre@suse.com>
                  Make tw_setfeature() call with interrupts disabled.
                  Register interrupt handler before enabling interrupts.
                  Clear attention interrupt before draining aen queue. 
+   1.02.00.005 - Allocate bounce buffers and custom queue depth for raid5 for
+                 6000 and 5000 series controllers.
+                 Reduce polling mdelays causing problems on some systems.
+                 Fix use_sg = 1 calculation bug. 
+                 Check for scsi_register returning NULL.
+                 Add aen count to /proc/scsi/3w-xxxx.
+                 Remove aen code unit masking in tw_aen_complete().
+   1.02.00.006 - Remove unit from printk in tw_scsi_eh_abort(), causing 
+                 possible oops.
+                 Fix possible null pointer dereference in tw_scsi_queue() 
+                 if done function pointer was invalid.
+   1.02.00.007 - Fix possible null pointer dereferences in tw_ioctl().
+                 Remove check for invalid done function pointer from
+                 tw_scsi_queue().
 */
 
 #include <linux/module.h>
@@ -128,7 +141,7 @@ struct proc_dir_entry tw_scsi_proc_entry = {
 };
 
 /* Globals */
-char *tw_driver_version="1.02.00.004";
+char *tw_driver_version="1.02.00.007";
 TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 int tw_device_extension_count = 0;
 
@@ -138,7 +151,7 @@ int tw_device_extension_count = 0;
 int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id) 
 {
        TW_Param *param;
-       unsigned short aen, aen_code;
+       unsigned short aen;
 
        if (tw_dev->alignment_virtual_address[request_id] == NULL) {
                printk(KERN_WARNING "3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n");
@@ -146,10 +159,11 @@ int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id)
        }
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
        aen = *(unsigned short *)(param->data);
-       aen_code = (aen & 0x0ff);
-       dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen_code);
+       dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen);
+       tw_dev->aen_count++;
+
        /* Now queue the code */
-       tw_dev->aen_queue[tw_dev->aen_tail] = aen_code;
+       tw_dev->aen_queue[tw_dev->aen_tail] = aen;
        if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
                tw_dev->aen_tail = TW_Q_START;
        } else {
@@ -248,7 +262,7 @@ int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
     
                /* Now poll for completion */
                for (i=0;i<imax;i++) {
-                       mdelay(10);
+                       mdelay(5);
                        status_reg_value = inl(status_reg_addr);
                        if (tw_check_bits(status_reg_value)) {
                                printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n");
@@ -443,15 +457,23 @@ int tw_allocate_memory(TW_Device_Extension *tw_dev, int request_id, int size, in
                printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): Found unaligned address.\n");
                return 1;
        }
-
-       if (which == 0) {
-               tw_dev->command_packet_virtual_address[request_id] = virt_addr;
-               tw_dev->command_packet_physical_address[request_id] = 
-                       virt_to_bus(virt_addr);
-       } else {
-               tw_dev->alignment_virtual_address[request_id] = virt_addr;
-               tw_dev->alignment_physical_address[request_id] =
-                       virt_to_bus(virt_addr);
+       switch(which) {
+       case 0:
+         tw_dev->command_packet_virtual_address[request_id] = virt_addr;
+         tw_dev->command_packet_physical_address[request_id] = 
+           virt_to_bus(virt_addr);
+         break;
+       case 1:
+         tw_dev->alignment_virtual_address[request_id] = virt_addr;
+         tw_dev->alignment_physical_address[request_id] =
+           virt_to_bus(virt_addr);
+         break;
+       case 2:
+         tw_dev->bounce_buffer[request_id] = virt_addr;
+         break;
+       default:
+         printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): case slip in tw_allocate_memory()\n");
+         return 1;
        }
        return 0;
 } /* End tw_allocate_memory() */
@@ -708,7 +730,7 @@ int tw_findcards(Scsi_Host_Template *tw_host)
                                kfree(tw_dev);
                                continue;
                        }
-                       
+
                        /* Calculate max cmds per lun */
                        if (tw_dev->num_units > 0)
                                tw_host->cmd_per_lun = (TW_Q_LENGTH-2)/tw_dev->num_units;
@@ -716,7 +738,13 @@ int tw_findcards(Scsi_Host_Template *tw_host)
                        /* Register the card with the kernel SCSI layer */
                        host = scsi_register(tw_host, sizeof(TW_Device_Extension));
                        
-                       /* FIXME - check for NULL */
+                       if (host == NULL) {
+                               printk(KERN_WARNING "3w-xxxx: tw_findcards(): scsi_register() failed for card %d.\n", numcards-1);
+                               release_region((tw_dev->tw_pci_dev->base_address[0]), TW_IO_ADDRESS_RANGE);
+                               tw_free_device_extension(tw_dev);
+                               kfree(tw_dev);
+                               continue;
+                       }
                        
                        status_reg_value = inl(tw_dev->registers.status_reg_addr);
                        
@@ -787,6 +815,9 @@ void tw_free_device_extension(TW_Device_Extension *tw_dev)
 
                if (tw_dev->alignment_virtual_address[i])
                        kfree(tw_dev->alignment_virtual_address[i]);
+
+               if (tw_dev->bounce_buffer[i])
+                       kfree(tw_dev->bounce_buffer[i]);
        }
 } /* End tw_free_device_extension() */
 
@@ -852,7 +883,7 @@ int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits)
        /* Poll for completion */
        imax = TW_POLL_MAX_RETRIES;
        for (i=0;i<imax;i++) {
-               mdelay(10);
+               mdelay(5);
                status_reg_value = inl(status_reg_addr);
                if (tw_check_bits(status_reg_value)) {
                        printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n");
@@ -908,8 +939,10 @@ int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
                tw_dev->aen_queue[i] = 0;
        }
 
-       for (i=0;i<TW_MAX_UNITS;i++)
+       for (i=0;i<TW_MAX_UNITS;i++) {
                tw_dev->is_unit_present[i] = 0;
+               tw_dev->is_raid_five[i] = 0;
+       }
 
        tw_dev->num_units = 0;
        tw_dev->num_aborts = 0;
@@ -927,6 +960,8 @@ int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
        tw_dev->aen_tail = 0;
        tw_dev->sector_count = 0;
        tw_dev->max_sector_count = 0;
+       tw_dev->aen_count = 0;
+       tw_dev->num_raid_five = 0;
        spin_lock_init(&tw_dev->tw_lock);
        return 0;
 } /* End tw_initialize_device_extension() */
@@ -938,13 +973,14 @@ int tw_initialize_units(TW_Device_Extension *tw_dev)
        unsigned char request_id = 0;
        TW_Command *command_packet;
        TW_Param *param;
-       int i, imax, num_units = 0;
+       int i, j, imax, num_units = 0, num_raid_five = 0;
        u32 status_reg_addr, status_reg_value;
        u32 command_que_addr, command_que_value;
        u32 response_que_addr;
        TW_Response_Queue response_queue;
        u32 param_value;
        unsigned char *is_unit_present;
+       unsigned char *raid_level;
 
        dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units()\n");
 
@@ -999,7 +1035,7 @@ int tw_initialize_units(TW_Device_Extension *tw_dev)
        /* Poll for completion */
        imax = TW_POLL_MAX_RETRIES;
        for(i=0; i<imax; i++) {
-               mdelay(10);
+               mdelay(5);
                status_reg_value = inl(status_reg_addr);
                if (tw_check_bits(status_reg_value)) {
                        printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
@@ -1050,6 +1086,107 @@ int tw_initialize_units(TW_Device_Extension *tw_dev)
                printk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): No units found.\n");
                return 1;
        }
+
+       /* Find raid 5 arrays */
+       for (j=0;j<TW_MAX_UNITS;j++) {
+               if (tw_dev->is_unit_present[j] == 0) 
+                       continue;
+               command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+               if (command_packet == NULL) {
+                       printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet virtual address.\n");
+                       return 1;
+               }
+               memset(command_packet, 0, sizeof(TW_Sector));
+               command_packet->byte0.opcode      = TW_OP_GET_PARAM;
+               command_packet->byte0.sgl_offset  = 2;
+               command_packet->size              = 4;
+               command_packet->request_id        = request_id;
+               command_packet->byte3.unit        = 0;
+               command_packet->byte3.host_id     = 0;
+               command_packet->status            = 0;
+               command_packet->flags             = 0;
+               command_packet->byte6.block_count = 1;
+
+               /* Now setup the param */
+               if (tw_dev->alignment_virtual_address[request_id] == NULL) {
+                       printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment virtual address.\n");
+                       return 1;
+               }
+               param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+               memset(param, 0, sizeof(TW_Sector));
+               param->table_id = 0x300+j; /* unit summary table */
+               param->parameter_id = 0x6; /* unit descriptor */
+               param->parameter_size_bytes = 0xc;
+               param_value = tw_dev->alignment_physical_address[request_id];
+               if (param_value == 0) {
+                       printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment physical address.\n");
+                       return 1;
+               }
+               
+               command_packet->byte8.param.sgl[0].address = param_value;
+               command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
+
+               /* Post the command packet to the board */
+               command_que_value = tw_dev->command_packet_physical_address[request_id];
+               if (command_que_value == 0) {
+                       printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet physical address.\n");
+                       return 1;
+               }
+               outl(command_que_value, command_que_addr);
+
+               /* Poll for completion */
+               imax = TW_POLL_MAX_RETRIES;
+               for(i=0; i<imax; i++) {
+                       mdelay(5);
+                       status_reg_value = inl(status_reg_addr);
+                       if (tw_check_bits(status_reg_value)) {
+                               printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
+                               return 1;
+                       }
+                       if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+                               response_queue.value = inl(response_que_addr);
+                               request_id = (unsigned char)response_queue.u.response_id;
+                               if (request_id != 0) {
+                               /* unexpected request id */
+                                       printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected request id.\n");
+                                       return 1;
+                               }
+                               if (command_packet->status != 0) {
+                               /* bad response */
+                                       printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+                                       return 1;
+                               }
+                               found = 1;
+                               break;
+                       }
+               }
+               if (found == 0) {
+                       /* response never received */
+                       printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): No response.\n");
+                       return 1;
+               }
+
+               param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+               raid_level = (unsigned char *)&(param->data[1]);
+               if (*raid_level == 5) {
+                       dprintk(KERN_WARNING "3w-xxxx: Found unit %d to be a raid5 unit.\n", j);
+                       tw_dev->is_raid_five[j] = 1;
+                       num_raid_five++;
+               }
+       }
+       tw_dev->num_raid_five = num_raid_five;
+
+       /* Now allocate raid5 bounce buffers */
+       if ((num_raid_five != 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) {
+               for (i=0;i<TW_Q_LENGTH;i++) {
+                       tw_allocate_memory(tw_dev, i, sizeof(TW_Sector)*128, 2);
+                       if (tw_dev->bounce_buffer[i] == NULL) {
+                               printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bounce buffer allocation failed.\n");
+                               return 1;
+                       }
+                       memset(tw_dev->bounce_buffer[i], 0, sizeof(TW_Sector)*128);
+               }
+       }
   
        return 0;
 } /* End tw_initialize_units() */
@@ -1283,12 +1420,17 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
                case TW_OP_SET_PARAM:
                        dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_SET_PARAM: table_id = %d, parameter_id = %d, parameter_size_bytes = %d.\n",
                        ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes);
-                       command_packet->byte0.opcode = TW_OP_SET_PARAM;
-                       param->table_id = ioctl->table_id;
-                       param->parameter_id = ioctl->parameter_id;
-                       param->parameter_size_bytes = ioctl->parameter_size_bytes;
-                       memcpy(param->data, ioctl->data, ioctl->parameter_size_bytes);
-                       break;
+                       if (ioctl->data != NULL) {
+                               command_packet->byte0.opcode = TW_OP_SET_PARAM;
+                               param->table_id = ioctl->table_id;
+                               param->parameter_id = ioctl->parameter_id;
+                               param->parameter_size_bytes = ioctl->parameter_size_bytes;
+                               memcpy(param->data, ioctl->data, ioctl->parameter_size_bytes);
+                               break;
+                       } else {
+                               printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
+                               return 1;
+                               }
                case TW_OP_AEN_LISTEN:
                        dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_AEN_LISTEN.\n");
                        if (tw_dev->aen_head == tw_dev->aen_tail) {
@@ -1313,11 +1455,15 @@ int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
                        tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
                        return 0;
                case TW_CMD_PACKET:
-                 memcpy(command_packet, ioctl->data, sizeof(TW_Command));
-                 command_packet->request_id = request_id;
-                 tw_post_command_packet(tw_dev, request_id);
-               
-                 return 0;
+                       if (ioctl->data != NULL) {
+                               memcpy(command_packet, ioctl->data, sizeof(TW_Command));
+                               command_packet->request_id = request_id;
+                               tw_post_command_packet(tw_dev, request_id);
+                               return 0;
+                       } else {
+                               printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
+                               return 1;
+                       }
                default:
                        printk(KERN_WARNING "3w-xxxx: Unknown ioctl 0x%x.\n", opcode);
                        tw_dev->state[request_id] = TW_S_COMPLETED;
@@ -1752,6 +1898,7 @@ int tw_scsi_proc_info(char *buffer, char **start, off_t offset, int length, int
                tw_copy_info(&info, "Max sector count:              %3d\n", tw_dev->max_sector_count);
                tw_copy_info(&info, "Resets:                        %3d\n", tw_dev->num_resets);
                tw_copy_info(&info, "Aborts:                        %3d\n", tw_dev->num_aborts);
+               tw_copy_info(&info, "AEN's:                         %3d\n", tw_dev->aen_count);   
        }
        if (info.position > info.offset) {
                return (info.position - info.offset);
@@ -1769,6 +1916,13 @@ int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
        int flags = 0;
        TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->host->hostdata;
 
+       if (tw_dev == NULL) {
+               printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid device extension.\n");
+               SCpnt->result = (DID_ERROR << 16);
+               done(SCpnt);
+               return 0;
+       }
+
        spin_lock_irqsave(&tw_dev->tw_lock, flags);
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue()\n");
 
@@ -1779,20 +1933,6 @@ int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
                spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
                return 0;
        }
-       if (done == NULL) {
-               printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid done function.\n");
-               SCpnt->result = (DID_ERROR << 16);
-               done(SCpnt);
-               spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
-               return 0;
-       }
-       if (tw_dev == NULL) {
-               printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid device extension.\n");
-               SCpnt->result = (DID_ERROR << 16);
-               done(SCpnt);
-               spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
-               return 0;
-       }
        
        /* Save done function into Scsi_Cmnd struct */
        SCpnt->scsi_done = done;
@@ -2093,7 +2233,7 @@ int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
        TW_Command *command_packet;
        u32 command_que_addr, command_que_value = 0;
        u32 lba = 0x0, num_sectors = 0x0;
-       int i;
+       int i, count = 0;
        Scsi_Cmnd *srb;
        struct scatterlist *sglist;
 
@@ -2151,29 +2291,52 @@ int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
        command_packet->byte8.io.lba = lba;
        command_packet->byte6.block_count = num_sectors;
 
-       /* Do this if there are no sg list entries */
-       if (tw_dev->srb[request_id]->use_sg == 0) {    
-               dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n");
-               command_packet->byte8.io.sgl[0].address = virt_to_bus(tw_dev->srb[request_id]->request_buffer);
-               command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
-       }
-
-       /* Do this if we have multiple sg list entries */
-       if (tw_dev->srb[request_id]->use_sg > 0) {
-               for (i=0;i<tw_dev->srb[request_id]->use_sg; i++) {
-                       command_packet->byte8.io.sgl[i].address = virt_to_bus(sglist[i].address);
-                       command_packet->byte8.io.sgl[i].length = sglist[i].length;
-                       command_packet->size+=2;
+       if ((tw_dev->is_raid_five[tw_dev->srb[request_id]->target] == 0) || (srb->cmnd[0] == READ_6) || (srb->cmnd[0] == READ_10) || (tw_dev->tw_pci_dev->device == TW_DEVICE_ID2)) {
+               /* Do this if there are no sg list entries */
+               if (tw_dev->srb[request_id]->use_sg == 0) {    
+                       dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n");
+                       command_packet->byte8.io.sgl[0].address = virt_to_bus(tw_dev->srb[request_id]->request_buffer);
+                       command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
+               }
+               
+               /* Do this if we have multiple sg list entries */
+               if (tw_dev->srb[request_id]->use_sg > 0) {
+                       for (i=0;i<tw_dev->srb[request_id]->use_sg; i++) {
+                               command_packet->byte8.io.sgl[i].address = virt_to_bus(sglist[i].address);
+                               command_packet->byte8.io.sgl[i].length = sglist[i].length;
+                               command_packet->size+=2;
+                       }
+                       if (tw_dev->srb[request_id]->use_sg >= 1)
+                               command_packet->size-=2;
+               }
+       } else {
+               /* Do this if there are no sg list entries for raid 5 */
+               if (tw_dev->srb[request_id]->use_sg == 0) {    
+                       dprintk(KERN_WARNING "doing raid 5 write use_sg = 0, bounce_buffer[%d] = 0x%p\n", request_id, tw_dev->bounce_buffer[request_id]);
+                       memcpy(tw_dev->bounce_buffer[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
+                       command_packet->byte8.io.sgl[0].address = virt_to_bus(tw_dev->bounce_buffer[request_id]);
+                       command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
+               }
+               
+               /* Do this if we have multiple sg list entries for raid 5 */
+               if (tw_dev->srb[request_id]->use_sg > 0) {
+                       dprintk(KERN_WARNING "doing raid 5 write use_sg = %d, sglist[0].length = %d\n",
+                              tw_dev->srb[request_id]->use_sg, sglist[0].length);
+                       for (i=0;i<tw_dev->srb[request_id]->use_sg; i++) {
+                               memcpy((char *)(tw_dev->bounce_buffer[request_id])+count, sglist[i].address, sglist[i].length);
+                               count+=sglist[i].length;
+                       }
+                       command_packet->byte8.io.sgl[0].address = virt_to_bus(tw_dev->bounce_buffer[request_id]);
+                       command_packet->byte8.io.sgl[0].length = count;
+                       command_packet->size = 5; /* single sgl */
                }
-               if (tw_dev->srb[request_id]->use_sg > 1)
-                       command_packet->size-=2;
        }
-
+               
        /* Update SG statistics */
        tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
        if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
                tw_dev->max_sgl_entries = tw_dev->sgl_entries;
-
+       
        command_que_value = tw_dev->command_packet_physical_address[request_id];
        if (command_que_value == 0) {
                dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Bad command packet physical address.\n");
@@ -2277,7 +2440,7 @@ int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size,
        /* Poll for completion */
        imax = TW_POLL_MAX_RETRIES;
        for (i=0;i<imax;i++) {
-               mdelay(10);
+               mdelay(5);
                status_reg_value = inl(status_reg_addr);
                if (tw_check_bits(status_reg_value)) {
                        printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n");
index 2fc41906fdffc8d37c45cd17bb93045b649e25c2..676e0e89a9a99620d5a18ee6d6d1ecded28c690e 100644 (file)
 #define TW_COMMAND_ALIGNMENT_MASK            0x1ff
 #define TW_INIT_MESSAGE_CREDITS                      0x100
 #define TW_INIT_COMMAND_PACKET_SIZE          0x3
-#define TW_POLL_MAX_RETRIES                  10000
+#define TW_POLL_MAX_RETRIES                  20000
 #define TW_MAX_SGL_LENGTH                    62
-#define TW_Q_LENGTH                          256
+#define TW_Q_LENGTH                          16
 #define TW_Q_START                           0
 #define TW_MAX_SLOT                          32
 #define TW_MAX_PCI_BUSES                     255
@@ -264,8 +264,11 @@ typedef struct TAG_TW_Device_Extension {
        TW_Registers            registers;
        u32                     *alignment_virtual_address[TW_Q_LENGTH];
        u32                     alignment_physical_address[TW_Q_LENGTH];
+       u32                     *bounce_buffer[TW_Q_LENGTH];
        int                     is_unit_present[TW_MAX_UNITS];
+       int                     is_raid_five[TW_MAX_UNITS];
        int                     num_units;
+       int                     num_raid_five;
        u32                     *command_packet_virtual_address[TW_Q_LENGTH];
        u32                     command_packet_physical_address[TW_Q_LENGTH];
        struct pci_dev          *tw_pci_dev;
@@ -288,6 +291,7 @@ typedef struct TAG_TW_Device_Extension {
        u32                     num_resets;
        u32                     sector_count;
        u32                     max_sector_count;
+       u32                     aen_count;
        struct Scsi_Host        *host;
        spinlock_t              tw_lock;
        unsigned char           ioctl_size[TW_Q_LENGTH];
index 3182bfaaedf66df08eecf3c3ac89c5d7c610c34f..ce7d4ee23d43cb26c74693b5e0071cbb91346c90 100644 (file)
@@ -1,6 +1,6 @@
 README file for the osst driver
 ===============================
-(w) Kurt Garloff <garloff@suse.de> 11/2000
+(w) Kurt Garloff <garloff@suse.de> 04/2001
 
 This file describes the osst driver as of version 0.8.x/0.9.x, the released
 version of the osst driver.
@@ -45,7 +45,7 @@ that it used the same kernel structures and the same device node as st.
 So you could only have either of them being present in the kernel. This has
 been fixed by registering an own device, now.
 st and osst can coexist, each only accessing the devices it can support by
-their own device.
+themselves.
 
 
 Installation
@@ -87,10 +87,11 @@ symlink trick. The IOCTLs to control tape operation are also mostly
 supported and you may try the mt (or mt_st) program to jump between
 filemarks, eject the tape, ...
 
-There's one limitation: You need to use a block size of 32kB.
-
-(This limitation is worked on and will be fixed in version 0.8.7 of
- this driver.)
+There's one limitation: You need to use a block size of 512 bytes, 1kB, 2kB,
+4kB, 8kB, 16kB or 32kB. The default block size is 512 bytes. However, your 
+backup software can transfer any multiple of the current block size. The
+blocksize can be changed with:
+mt -f /dev/nosst0 defblksize 1024
 
 If you just want to get started with standard software, here is an example
 for creating and restoring a full backup:
@@ -112,13 +113,42 @@ On a fast machine, you may profit from software data compression (z flag for
 tar).
 
 
+Interpreting log output
+-----------------------
+Log output of different severity is created by osst. Every message starts
+with "osstX:S:" where X is the tape device (minor number modulo 32), or a
+blank if not applicable, and S is the severity:
+
+:A: Assert, an error that "should not happen". If you get one of these and
+    have not changed anything in osst_options.h, report it to the mail list.
+
+:E: Error, your backup is toast (sorry).
+
+:W: Warning, something happened that endangers your data. Look for other
+    information to see if osst was able to recover.
+
+:I: Information which osst wants you to know. This could be follow-on info
+    on a previously issued warning or error.
+
+:D: Debug output, created when you compile with "#define DEBUG 1".
+
+This output is sent to klogd with corresponding priority. If you don't see
+it in your system log (typically /var/log/messages), check your syslog.conf.
+
+
 USB and IDE
 -----------
 Via the SCSI emulation layers usb-storage and ide-scsi, you can also use the
 osst driver to drive the USB-30 and the DI-30 drives. (Unfortunately, there
 is no such layer for the parallel port, otherwise the DP-30 would work as
-well.) For the USB support, you need the latest 2.4.0-test kernels and the 
-latest usb-storage driver from 
+well.) 
+
+For the DI-30, compile the SCSI layer and ide-scsi into the kernel and pass
+hdX=scsi as boot parameter to your kernel, with hdX corresponding to your
+OnStream device.
+
+For the USB support, you need the usb-sotrage driver of 2.4.0 kernel or
+newer and you have to enable the Freecom support. For news, check
 http://www.linux-usb.org/
 http://sourceforge.net/cvs/?group_id=3581
 
@@ -158,6 +188,11 @@ Status
 have been sent, but mostly reported success or only minor trouble.
 All the issues have been addressed.
 Check the web pages for more info about the current developments.
+0.9.x is the tree for the 2.3/2.4 kernel.
+
+0.8.6.x and 0.9.4.x have been integrated into the mainstream kernels 2.2.19
+and 2.4.0 repsectively. Newer versions with variable block size support will
+be submitted soon.
 
 
 Acknowledgments
@@ -188,7 +223,7 @@ Makedevs.sh
 #!/bin/sh
 # Script to create OnStream SC-x0 device nodes (major 206)
 # Usage: Makedevs.sh [nos [path to dev]]
-# $Id: README.osst.kernel,v 1.1.2.2 2000/12/20 14:08:38 garloff Exp $
+# $Id: README.osst.kernel,v 1.3.2.3 2001/06/02 23:49:03 riede Exp $
 major=206
 nrs=4
 dir=/dev
index 3c4ace5b092d31bfb19f073a78f9113dae9c52fb..07495e268291d0238caca17c042c4071af15c81f 100644 (file)
   Copyright 1992 - 2000 Kai Makisara
                 email Kai.Makisara@metla.fi
 
-  $Header: /home/cvsroot/Driver/osst.c,v 1.28.2.12.2.1 2000/12/15 20:36:12 garloff Exp $
+  $Header: /home/cvsroot/Driver/osst.c,v 1.28.2.25 2001/06/03 21:56:26 riede Exp $
 
   Last modified: Wed Feb  2 22:04:05 2000 by makisara@kai.makisara.local
   Some small formal changes - aeb, 950809
 */
 
-static const char * cvsid = "$Id: osst.c,v 1.28.2.12.2.1 2000/12/15 20:36:12 garloff Exp $";
-const char * osst_version = "0.8.6.1";
+static const char * cvsid = "$Id: osst.c,v 1.28.2.25 2001/06/03 21:56:26 riede Exp $";
+const char * osst_version = "0.8.13";
 
 /* The "failure to reconnect" firmware bug */
-#define OSST_FW_NEED_POLL_MIN 10602 /*(107A)*/
-#define OSST_FW_NEED_POLL_MAX 10708 /*(108D)*/
+#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
+#define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
 #define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
 
 #include <linux/module.h>
@@ -95,6 +95,8 @@ static int max_sg_segs = 0;
 
 #if DEBUG
 static int debugging = 1;
+/* uncomment define below to test error recovery */
+// #define OSST_INJECT_ERRORS 1 
 #endif
 
 #define MAX_RETRIES 0
@@ -148,7 +150,7 @@ static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int f
 
 static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt);
 
-static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int file_blk);
+static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt);
 
 static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int pending);
 
@@ -179,7 +181,7 @@ static int osst_chk_result(Scsi_Cmnd * SCpnt)
 
 #if DEBUG
   if (debugging) {
-    printk(OSST_DEB_MSG "osst%d: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
+    printk(OSST_DEB_MSG "osst%d:D: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
           dev, result,
           SCpnt->data_cmnd[0], SCpnt->data_cmnd[1], SCpnt->data_cmnd[2],
           SCpnt->data_cmnd[3], SCpnt->data_cmnd[4], SCpnt->data_cmnd[5],
@@ -199,14 +201,21 @@ static int osst_chk_result(Scsi_Cmnd * SCpnt)
        SCpnt->data_cmnd[0] != MODE_SENSE &&
        SCpnt->data_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
     if (driver_byte(result) & DRIVER_SENSE) {
-      printk(KERN_WARNING "osst%d: Error with sense data: ", dev);
+      printk(KERN_WARNING "osst%d:W: Error with sense data: ", dev);
       print_sense("osst", SCpnt);
     }
-    else
+    else {
+static int     notyetprinted = 1;
       printk(KERN_WARNING
-            "osst%d: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
-            dev, result, suggestion(result), driver_byte(result),
+            "osst%d:W: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
+            dev, result, suggestion(result), driver_byte(result) & DRIVER_MASK,
             host_byte(result));
+      if (notyetprinted) {
+       notyetprinted = 0;
+       printk(KERN_INFO "osst%d:I: This error may be caused by your scsi controller,\n", dev);
+       printk(KERN_INFO "osst%d:I: it has been reported with some Buslogic cards.\n", dev);
+      }
+    }
   }
 
   if ((sense[0] & 0x70) == 0x70 &&
@@ -222,7 +231,7 @@ static int osst_chk_result(Scsi_Cmnd * SCpnt)
        stp = "write";
       else
        stp = "ioctl";
-      printk(OSST_DEB_MSG "osst%d: Recovered %s error (%d).\n", dev, stp,
+      printk(OSST_DEB_MSG "osst%d:D: Recovered %s error (%d).\n", dev, stp,
             os_scsi_tapes[dev]->recover_count);
     }
 #endif
@@ -237,7 +246,6 @@ static int osst_chk_result(Scsi_Cmnd * SCpnt)
 static void osst_sleep_done (Scsi_Cmnd * SCpnt)
 {
   unsigned int st_nbr;
-  int remainder;
   OS_Scsi_Tape * STp;
 
   if ((st_nbr = TAPE_NR(SCpnt->request.rq_dev)) < osst_template.nr_dev) {
@@ -246,14 +254,7 @@ static void osst_sleep_done (Scsi_Cmnd * SCpnt)
        (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
        (SCpnt->sense_buffer[2] & 0x40)) {
       /* EOM at write-behind, has all been written? */
-      if ((SCpnt->sense_buffer[0] & 0x80) != 0)
-       remainder = (SCpnt->sense_buffer[3] << 24) |
-             (SCpnt->sense_buffer[4] << 16) |
-               (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6];
-      else
-       remainder = 0;
-      if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW ||
-         remainder > 0)
+      if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW)
        (STp->buffer)->last_result = SCpnt->result; /* Error */
       else
        (STp->buffer)->last_result = INT_MAX; /* OK */
@@ -270,7 +271,7 @@ static void osst_sleep_done (Scsi_Cmnd * SCpnt)
   }
 #if DEBUG
   else if (debugging)
-    printk(KERN_ERR "osst?: Illegal interrupt device %x\n", st_nbr);
+    printk(KERN_ERR "osst?:D: Illegal interrupt device %x\n", st_nbr);
 #endif
 }
 
@@ -283,12 +284,14 @@ static Scsi_Cmnd * osst_do_scsi(Scsi_Cmnd *SCpnt, OS_Scsi_Tape *STp,
 {
   unsigned long flags;
   unsigned char *bp;
-//static int inject = 0; /* FIXME - take out inject occasional read errors */
-//static int repeat = 0;
+#ifdef OSST_INJECT_ERRORS
+  static int inject = 0;
+  static int repeat = 0;
+#endif
   spin_lock_irqsave(&io_request_lock, flags);
   if (SCpnt == NULL)
     if ((SCpnt = scsi_allocate_device(NULL, STp->device, 1)) == NULL) {
-      printk(KERN_ERR "osst%d: Can't get SCSI request.\n", TAPE_NR(STp->devt));
+      printk(KERN_ERR "osst%d:E: Can't get SCSI request.\n", TAPE_NR(STp->devt));
       spin_unlock_irqrestore(&io_request_lock, flags);
       return NULL;
     }
@@ -317,12 +320,14 @@ static Scsi_Cmnd * osst_do_scsi(Scsi_Cmnd *SCpnt, OS_Scsi_Tape *STp,
       down(SCpnt->request.sem);
 
       (STp->buffer)->last_result_fatal = osst_chk_result(SCpnt);
-//if ((STp->buffer)->last_result_fatal == 0 &&
-//    cmd[0] == READ_6 && cmd[4] && ( /* (++ inject % 83) == 29  || */
-//     (STp->first_frame_position == 240 /* or STp->read_error_frame to fail again on the block calculated above */ && ++repeat < 3))) {
-//     printk(OSST_DEB_MSG "osst%d: injecting read error\n", TAPE_NR(STp->devt));
-//     STp->buffer->last_result_fatal = 1; /* FIXME - take out inject occasional read errors */
-//}
+#ifdef OSST_INJECT_ERRORS
+      if (STp->buffer->last_result_fatal == 0 &&
+         cmd[0] == READ_6 && cmd[4] && ( /* (++ inject % 83) == 29  || */
+             (STp->first_frame_position == 240 /* or STp->read_error_frame to fail again on the block calculated above */ && ++repeat < 3))) {
+       printk(OSST_DEB_MSG "osst%d:D: Injecting read error\n", TAPE_NR(STp->devt));
+       STp->buffer->last_result_fatal = 1;
+      }
+#endif
   }
 
   return SCpnt;
@@ -333,7 +338,6 @@ static Scsi_Cmnd * osst_do_scsi(Scsi_Cmnd *SCpnt, OS_Scsi_Tape *STp,
 static void osst_write_behind_check(OS_Scsi_Tape *STp)
 {
   OSST_buffer * STbuffer;
-  ST_partstat * STps;
 
   STbuffer = STp->buffer;
 
@@ -357,21 +361,9 @@ static void osst_write_behind_check(OS_Scsi_Tape *STp)
   scsi_release_command((STp->buffer)->last_SCpnt);
 
   if (STbuffer->writing < STbuffer->buffer_bytes)
-#if 0
-    memcpy(STbuffer->b_data,
-          STbuffer->b_data + STbuffer->writing,
-          STbuffer->buffer_bytes - STbuffer->writing);
-#else
-  printk(KERN_WARNING "osst: write_behind_check: something left in buffer!\n");
-#endif
+    printk(KERN_WARNING "osst:A: write_behind_check: something left in buffer!\n");
+
   STbuffer->buffer_bytes -= STbuffer->writing;
-  STps = &(STp->ps[STp->partition]);
-  if (STps->drv_block >= 0) {
-    if (STp->block_size == 0)
-      STps->drv_block++;
-    else
-      STps->drv_block += STbuffer->writing / STp->block_size;
-  }
   STbuffer->writing = 0;
 
   return;
@@ -383,7 +375,8 @@ static void osst_write_behind_check(OS_Scsi_Tape *STp)
 /*
  * Initialize the OnStream AUX
  */
-static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int logical_blk_num)
+static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int frame_seq_number,
+                                        int logical_blk_num, int blk_sz, int blk_cnt)
 {
        os_aux_t       *aux = STp->buffer->aux;
        os_partition_t *par = &aux->partition;
@@ -417,9 +410,10 @@ static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int logical_blk_nu
                dat->reserved1 = 0;
                dat->entry_cnt = 1;
                dat->reserved3 = 0;
-               dat->dat_list[0].blk_sz   = htonl(frame_type==OS_FRAME_TYPE_DATA?STp->block_size:0);
-               dat->dat_list[0].blk_cnt  = htons(1);
-               dat->dat_list[0].flags    = frame_type==OS_FRAME_TYPE_MARKER?OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
+               dat->dat_list[0].blk_sz   = htonl(blk_sz);
+               dat->dat_list[0].blk_cnt  = htons(blk_cnt);
+               dat->dat_list[0].flags    = frame_type==OS_FRAME_TYPE_MARKER?
+                                                       OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
                dat->dat_list[0].reserved = 0;
          case  OS_FRAME_TYPE_EOD:
                aux->update_frame_cntr    = htonl(0);
@@ -428,27 +422,28 @@ static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int logical_blk_nu
                par->wrt_pass_cntr        = htons(STp->wrt_pass_cntr);
                par->first_frame_ppos     = htonl(STp->first_data_ppos);
                par->last_frame_ppos      = htonl(STp->capacity);
-               aux->frame_seq_num        = htonl(logical_blk_num);
+               aux->frame_seq_num        = htonl(frame_seq_number);
                aux->logical_blk_num_high = htonl(0);
                aux->logical_blk_num      = htonl(logical_blk_num);
                break;
          default: ; /* probably FILL */
        }
-       aux->filemark_cnt = ntohl(STp->filemark_cnt);        /* FIXME -- violates ADR spec */
+       aux->filemark_cnt = ntohl(STp->filemark_cnt);
        aux->phys_fm = ntohl(0xffffffff);
        aux->last_mark_ppos = ntohl(STp->last_mark_ppos);
+       aux->last_mark_lbn  = ntohl(STp->last_mark_lbn);
 }
 
 /*
  * Verify that we have the correct tape frame
  */
-static int osst_verify_frame(OS_Scsi_Tape * STp, int logical_blk_num, int quiet)
+static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet)
 {
        os_aux_t       * aux  = STp->buffer->aux;
         os_partition_t * par  = &(aux->partition);
        ST_partstat    * STps = &(STp->ps[STp->partition]);
-        int              i;
        int              dev  = TAPE_NR(STp->devt);
+       int              blk_cnt, blk_sz, i;
 
         if (STp->raw) {
                 if (STp->buffer->last_result_fatal) {
@@ -459,55 +454,70 @@ static int osst_verify_frame(OS_Scsi_Tape * STp, int logical_blk_num, int quiet)
                 return 1;
         }
         if (STp->buffer->last_result_fatal) {
-                printk(KERN_INFO "osst%d: Skipping frame, read error\n", dev);
-                return 0;
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Skipping frame, read error\n", dev);
+#endif
+               return 0;
         }
         if (ntohl(aux->format_id) != 0) {
-                printk(KERN_INFO "osst%d: Skipping frame, format_id %u\n", dev, ntohl(aux->format_id));
-                return 0;
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Skipping frame, format_id %u\n", dev, ntohl(aux->format_id));
+#endif
+               goto err_out;
         }
         if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
            (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
-                printk(KERN_INFO "osst%d: Skipping frame, incorrect application signature\n", dev);
-                return 0;
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Skipping frame, incorrect application signature\n", dev);
+#endif
+               goto err_out;
         }
         if (par->partition_num != OS_DATA_PARTITION) {
                 if (!STp->linux_media || STp->linux_media_version != 2) {
-                        printk(KERN_INFO "osst%d: Skipping frame, partition num %d\n", dev, par->partition_num);                           return 0;
+#if DEBUG
+                       printk(OSST_DEB_MSG "osst%d:D: Skipping frame, partition num %d\n",
+                                       dev, par->partition_num);
+#endif
+                       goto err_out;
                 }
         }
         if (par->par_desc_ver != OS_PARTITION_VERSION) {
-                printk(KERN_INFO "osst%d: Skipping frame, partition version %d\n", dev, par->par_desc_ver);
-                return 0;
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Skipping frame, partition version %d\n", dev, par->par_desc_ver);
+#endif
+               goto err_out;
         }
         if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
-                printk(KERN_INFO "osst%d: Skipping frame, wrt_pass_cntr %d (expected %d)\n", 
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n", 
                                 dev, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
-                return 0;
-        }
-        if (aux->frame_seq_num != aux->logical_blk_num) {
-                printk(KERN_INFO "osst%d: Skipping frame, seq != logical\n", dev);
-                return 0;
+#endif
+               goto err_out;
         }
         if (aux->frame_type != OS_FRAME_TYPE_DATA &&
             aux->frame_type != OS_FRAME_TYPE_EOD &&
             aux->frame_type != OS_FRAME_TYPE_MARKER) {
-                if (!quiet)
-                       printk(KERN_INFO "osst%d: Skipping frame, frame type %x\n", dev, aux->frame_type);
-                return 0;
+#if DEBUG
+               if (!quiet)
+                       printk(OSST_DEB_MSG "osst%d:D: Skipping frame, frame type %x\n", dev, aux->frame_type);
+#endif
+               goto err_out;
         }
         if (aux->frame_type == OS_FRAME_TYPE_EOD &&
            STp->first_frame_position < STp->eod_frame_ppos) {
-                printk(KERN_INFO "osst%d: skipping premature EOD frame %d\n", dev, STp->first_frame_position);
-                return 0;
+                printk(KERN_INFO "osst%d:I: skipping premature EOD frame %d\n", 
+                               dev, STp->first_frame_position);
+                goto err_out;
        }
-       STp->logical_blk_in_buffer = 1;
+       STp->frame_in_buffer = 1;
 
-        if (logical_blk_num != -1 && ntohl(aux->logical_blk_num) != logical_blk_num) {
-                if (!quiet)
-                        printk(KERN_INFO "osst%d: Skipping frame, logical_blk_num %u (expected %d)\n", 
-                                        dev, ntohl(aux->logical_blk_num), logical_blk_num);
-                return 0;
+        if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
+#if DEBUG
+               if (!quiet)
+                        printk(OSST_DEB_MSG "osst%d:D: Skipping frame, sequence number %u (expected %d)\n", 
+                                        dev, ntohl(aux->frame_seq_num), frame_seq_number);
+#endif
+               goto err_out;
         }
         if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
                 STps->eof = ST_FM_HIT;
@@ -515,8 +525,8 @@ static int osst_verify_frame(OS_Scsi_Tape * STp, int logical_blk_num, int quiet)
                i = ntohl(aux->filemark_cnt);
                if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
                    STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
-#if 1 //DEBUG
-                       printk(OSST_DEB_MSG "osst%i: %s filemark %d at frame %d\n", dev,
+#if DEBUG
+                       printk(OSST_DEB_MSG "osst%d:D: %s filemark %d at frame pos %d\n", dev,
                                  STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
                                  i, STp->first_frame_position - 1);
 #endif
@@ -529,9 +539,31 @@ static int osst_verify_frame(OS_Scsi_Tape * STp, int logical_blk_num, int quiet)
                 STps->eof = ST_EOD_1;
         }
         if (aux->frame_type == OS_FRAME_TYPE_DATA) {
-                STps->eof = ST_NOEOF;
+                blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
+               blk_sz  = ntohl(aux->dat.dat_list[0].blk_sz);
+               STp->buffer->buffer_bytes = blk_cnt * blk_sz;
+               STp->buffer->read_pointer = 0;
+
+               /* See what block size was used to write file */
+               if (STp->block_size != blk_sz && blk_sz > 0) {
+                       printk(KERN_INFO
+               "osst%d:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
+                                       dev, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
+                               STp->block_size<1024?STp->block_size:STp->block_size/1024,
+                               STp->block_size<1024?'b':'k');
+                       STp->block_size            = blk_sz;
+                       STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
+               }
+               STps->eof = ST_NOEOF;
         }
-        return 1;
+        STp->frame_seq_number = ntohl(aux->frame_seq_num);
+       STp->logical_blk_num  = ntohl(aux->logical_blk_num);
+       return 1;
+
+err_out:
+       if (STp->read_error_frame == 0)
+               STp->read_error_frame = STp->first_frame_position - 1;
+       return 0;
 }
 
 /*
@@ -546,7 +578,7 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned tim
        int             dbg = debugging;
        int             dev  = TAPE_NR(STp->devt);
 
-       printk(OSST_DEB_MSG "osst%d: reached onstream wait ready\n", dev);
+       printk(OSST_DEB_MSG "osst%d:D: Reached onstream wait ready\n", dev);
 #endif
 
        memset(cmd, 0, MAX_COMMAND_SIZE);
@@ -561,8 +593,8 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned tim
                time_before(jiffies, startwait + timeout*HZ) ) {
 #if DEBUG
            if (debugging) {
-               printk(OSST_DEB_MSG "osst%d: Sleeping in onstream wait ready\n", dev);
-               printk(OSST_DEB_MSG "osst%d: Turning off debugging for a while\n", dev);
+               printk(OSST_DEB_MSG "osst%d:D: Sleeping in onstream wait ready\n", dev);
+               printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);
                debugging = 0;
            }
 #endif
@@ -581,12 +613,12 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned tim
        if ( SCpnt->sense_buffer[2] &&
             osst_write_error_recovery(STp, aSCpnt, 0) ) {
 #if DEBUG
-           printk(OSST_DEB_MSG "osst%d: Abnormal exit from onstream wait ready\n", dev);
+           printk(OSST_DEB_MSG "osst%d:D: Abnormal exit from onstream wait ready\n", dev);
 #endif
            return (-EIO);
        }
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%d: Normal exit from onstream wait ready\n", dev);
+       printk(OSST_DEB_MSG "osst%d:D: Normal exit from onstream wait ready\n", dev);
 #endif
        return 0;
 }
@@ -614,7 +646,7 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
 #if DEBUG
        int             dev  = TAPE_NR(STp->devt);
 
-       printk(OSST_DEB_MSG "osst%d: Reached onstream flush drive buffer (write filemark)\n", dev);
+       printk(OSST_DEB_MSG "osst%d:D: Reached onstream flush drive buffer (write filemark)\n", dev);
 #endif
 
        memset(cmd, 0, MAX_COMMAND_SIZE);
@@ -667,7 +699,7 @@ static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int curr, in
        char    notyetprinted = 1;
 #endif
        if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
-               printk(KERN_ERR "osst%i: waiting for frame without having initialized read!\n", dev);
+               printk(KERN_ERR "osst%i:A: waiting for frame without having initialized read!\n", dev);
 
        while (time_before (jiffies, startwait + to*HZ))
        { 
@@ -685,7 +717,8 @@ static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int curr, in
                {
 #if DEBUG                      
                        if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC)
-                               printk ("osst%i: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
+                               printk (OSST_DEB_MSG 
+                                       "osst%i:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
                                        dev, curr, curr+minlast, STp->first_frame_position,
                                        STp->last_frame_position, STp->cur_frames,
                                        result, (jiffies-startwait)/HZ, 
@@ -696,7 +729,7 @@ static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int curr, in
 #if DEBUG
                if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC && notyetprinted)
                {
-                       printk ("osst%i: Wait for frame %i (>%i): %i-%i %i (%i)\n",
+                       printk (KERN_INFO "osst%i:I: Wait for frame %i (>%i): %i-%i %i (%i)\n",
                                dev, curr, curr+minlast, STp->first_frame_position,
                                STp->last_frame_position, STp->cur_frames, result);
                        notyetprinted--;
@@ -706,7 +739,7 @@ static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int curr, in
                schedule_timeout (HZ / OSST_POLL_PER_SEC);
        }
 #if DEBUG
-       printk ("osst%i: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
+       printk (OSST_DEB_MSG "osst%i:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
                dev, curr, curr+minlast, STp->first_frame_position,
                STp->last_frame_position, STp->cur_frames,
                (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
@@ -715,9 +748,9 @@ static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int curr, in
 }
 
 /*
- * Read the next OnStream tape block at the current location
+ * Read the next OnStream tape frame at the current location
  */
-static int osst_read_block(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int timeout)
+static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int timeout)
 {
        unsigned char   cmd[MAX_COMMAND_SIZE];
        Scsi_Cmnd     * SCpnt;
@@ -741,7 +774,7 @@ static int osst_read_block(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int timeout)
 
 #if DEBUG
        if (debugging)
-           printk(OSST_DEB_MSG "osst%i: Reading block from OnStream tape\n", dev);
+           printk(OSST_DEB_MSG "osst%d:D: Reading frame from OnStream tape\n", dev);
 #endif
        SCpnt = osst_do_scsi(*aSCpnt, STp, cmd, OS_FRAME_SIZE, STp->timeout, MAX_RETRIES, TRUE);
        *aSCpnt = SCpnt;
@@ -752,11 +785,13 @@ static int osst_read_block(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int timeout)
            retval = 1;
            if (STp->read_error_frame == 0) {
                STp->read_error_frame = STp->first_frame_position;
-               printk(OSST_DEB_MSG "osst: recording read error at %d\n", STp->read_error_frame);/*FIXME*/
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Recording read error at %d\n", dev, STp->read_error_frame);
+#endif
            }
 #if DEBUG
            if (debugging)
-               printk(OSST_DEB_MSG "osst%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
+               printk(OSST_DEB_MSG "osst%d:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
                   dev,
                   SCpnt->sense_buffer[0], SCpnt->sense_buffer[1],
                   SCpnt->sense_buffer[2], SCpnt->sense_buffer[3],
@@ -768,16 +803,19 @@ static int osst_read_block(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int timeout)
            STp->first_frame_position++;
 #if DEBUG
        if (debugging) {
-          printk(OSST_DEB_MSG "osst%i: AUX: %c%c%c%c UpdFrCt#%d %s FrSeq#%d LogBlk#%d\n", dev,
+          printk(OSST_DEB_MSG 
+               "osst%d:D: AUX: %c%c%c%c UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", dev,
                        aux->application_sig[0], aux->application_sig[1],
-                       aux->application_sig[2], aux->application_sig[3], ntohl(aux->update_frame_cntr),
+                       aux->application_sig[2], aux->application_sig[3], 
+                       ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
                        aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
                        aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL", 
-                       ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num) );
+                       ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
+                       ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
           if (aux->frame_type==2)
-               printk(OSST_DEB_MSG "osst%i: mark_cnt=%d, last_mark=%d, next_mark=%d\n", dev,
-                       ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->next_mark_ppos));
-          printk(OSST_DEB_MSG "osst%i: Exit read block from OnStream tape with code %d\n", dev, retval);
+               printk(OSST_DEB_MSG "osst%d:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", dev,
+                       ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
+          printk(OSST_DEB_MSG "osst%d:D: Exit read frame from OnStream tape with code %d\n", dev, retval);
        }
 #endif
        return (retval);
@@ -795,22 +833,22 @@ static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
 
         if (STps->rw != ST_READING) {         /* Initialize read operation */
                 if (STps->rw == ST_WRITING) {
-                        osst_flush_write_buffer(STp, aSCpnt, 1);
+                        osst_flush_write_buffer(STp, aSCpnt);
                        osst_flush_drive_buffer(STp, aSCpnt);
                 }
                 STps->rw = ST_READING;
-               STp->logical_blk_in_buffer = 0;
+               STp->frame_in_buffer = 0;
 
                 /*
                  *      Issue a read 0 command to get the OnStream drive
-                 *      read blocks into its buffer.
+                 *      read frames into its buffer.
                  */
                memset(cmd, 0, MAX_COMMAND_SIZE);
                cmd[0] = READ_6;
                cmd[1] = 1;
 
 #if DEBUG
-               printk(OSST_DEB_MSG "osst%i: Start Read Ahead on OnStream tape\n", dev);
+               printk(OSST_DEB_MSG "osst%d:D: Start Read Ahead on OnStream tape\n", dev);
 #endif
                SCpnt   = osst_do_scsi(*aSCpnt, STp, cmd, 0, STp->timeout, MAX_RETRIES, TRUE);
                *aSCpnt = SCpnt;
@@ -820,7 +858,7 @@ static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
         return retval;
 }
 
-static int osst_get_logical_blk(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int logical_blk_num, int quiet)
+static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int frame_seq_number, int quiet)
 {
        ST_partstat * STps  = &(STp->ps[STp->partition]);
        int           dev   = TAPE_NR(STp->devt);
@@ -831,16 +869,16 @@ static int osst_get_logical_blk(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int log
                      position;
 
         /*
-         * Search and wait for the next logical tape block
+         * Search and wait for the next logical tape frame
          */
         while (1) {
                 if (cnt++ > 400) {
-                        printk(KERN_WARNING "osst%d: Couldn't find logical block %d, aborting\n",
-                                           dev, logical_blk_num);
+                        printk(KERN_ERR "osst%d:E: Couldn't find logical frame %d, aborting\n",
+                                           dev, frame_seq_number);
                        if (STp->read_error_frame) {
                                osst_set_frame_position(STp, aSCpnt, STp->read_error_frame, 0);
-#if 1 //DEBUG
-                               printk(OSST_DEB_MSG "osst%d: Repositioning tape to bad block %d\n",
+#if DEBUG
+                               printk(OSST_DEB_MSG "osst%d:D: Repositioning tape to bad frame %d\n",
                                                 dev, STp->read_error_frame);
 #endif
                                STp->read_error_frame = 0;
@@ -849,54 +887,55 @@ static int osst_get_logical_blk(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int log
                 }
 #if DEBUG
                if (debugging)
-                       printk(OSST_DEB_MSG "osst%d: Looking for block %d, attempt %d\n",
-                                         dev, logical_blk_num, cnt);
+                       printk(OSST_DEB_MSG "osst%d:D: Looking for frame %d, attempt %d\n",
+                                         dev, frame_seq_number, cnt);
 #endif
                 if ( osst_initiate_read(STp, aSCpnt)
-                || ( (!STp->logical_blk_in_buffer) && osst_read_block(STp, aSCpnt, 30) ) ) {
+                || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSCpnt, 30) ) ) {
                         position = osst_get_frame_position(STp, aSCpnt);
                        if (position >= 0xbae && position < 0xbb8)
                                position = 0xbb8;
                        else if (position > STp->eod_frame_ppos || ++bad == 10) {
-printk(OSST_DEB_MSG "osst%d: start again from pos %d, eod %d, bad %d\n", dev, position, STp->eod_frame_ppos, bad); /*FIXME*/
                                position = STp->read_error_frame - 1;
                        }
                        else {
                                position += 39;
                                cnt += 20;
                        }
-#if 1 //DEBUG
-                        printk(OSST_DEB_MSG "osst%d: Bad block detected, positioning tape to block %d\n",
+#if DEBUG
+                        printk(OSST_DEB_MSG "osst%d:D: Bad frame detected, positioning tape to frame %d\n",
                                         dev, position);
 #endif
                         osst_set_frame_position(STp, aSCpnt, position, 0);
                         continue;
                 }
-                if (osst_verify_frame(STp, logical_blk_num, quiet))
+                if (osst_verify_frame(STp, frame_seq_number, quiet))
                         break;
                 if (osst_verify_frame(STp, -1, quiet)) {
-                        x = ntohl(STp->buffer->aux->logical_blk_num);
+                        x = ntohl(STp->buffer->aux->frame_seq_num);
                        if (STp->fast_open) {
-#if 1 //DEBUG
-                               printk(OSST_DEB_MSG "osst%d: Found logical block %d instead of %d after fast open\n",
-                                         dev, x, logical_blk_num);
-#endif
+                               printk(KERN_WARNING 
+                                      "osst%d:W: Found logical frame %d instead of %d after fast open\n",
+                                         dev, x, frame_seq_number);
                                STp->header_ok = 0;
                                STp->read_error_frame = 0;
                                return (-EIO);
                        }
-                        if (x > logical_blk_num) {
+                        if (x > frame_seq_number) {
                                if (++past > 3) {
-                                       /* positioning backwards did not bring us to the desired block */
+                                       /* positioning backwards did not bring us to the desired frame */
                                        position = STp->read_error_frame - 1;
                                }
-                               else
+                               else {
                                        position = osst_get_frame_position(STp, aSCpnt)
-                                                + logical_blk_num - x - 1;
-#if 1 //DEBUG
+                                                + frame_seq_number - x - 1;
+                                       if (STp->first_frame_position >= 3000 && position < 3000)
+                                               position -= 10;
+                               }
+#if DEBUG
                                 printk(OSST_DEB_MSG
-                                      "osst%d: Found logical block %d while looking for %d: back up %d\n",
-                                               dev, x, logical_blk_num,
+                                      "osst%d:D: Found logical frame %d while looking for %d: back up %d\n",
+                                               dev, x, frame_seq_number,
                                                STp->first_frame_position - position);
 #endif
                                osst_set_frame_position(STp, aSCpnt, position, 0);
@@ -907,22 +946,26 @@ printk(OSST_DEB_MSG "osst%d: start again from pos %d, eod %d, bad %d\n", dev, po
                 }
                 if (osst_get_frame_position(STp, aSCpnt) == 0xbaf) {
 #if DEBUG
-                        printk(OSST_DEB_MSG "osst%d: Skipping config partition\n", dev);
+                       printk(OSST_DEB_MSG "osst%d:D: Skipping config partition\n", dev);
 #endif
                        osst_set_frame_position(STp, aSCpnt, 0xbb8, 0);
                        cnt--;
                }
-               STp->logical_blk_in_buffer = 0;
+               STp->frame_in_buffer = 0;
         }
         if (cnt > 1) {
                STp->recover_count++;
                STp->recover_erreg++;
+               printk(KERN_WARNING "osst%d:I: Read error at position %d recovered\n",
+                                       dev, STp->read_error_frame);
        }
-        STp->logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num);
+       STp->read_count++;
 
 #if DEBUG
        if (debugging || STps->eof)
-               printk(OSST_DEB_MSG "osst%i: Exit get logical block (%d=>%d) from OnStream tape with code %d\n",                                                         dev, logical_blk_num, STp->logical_blk_num, STps->eof);
+               printk(OSST_DEB_MSG
+                               "osst%i:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
+                               dev, frame_seq_number, STp->frame_seq_number, STps->eof);
 #endif
        STp->fast_open = FALSE;
        STp->read_error_frame = 0;
@@ -931,60 +974,196 @@ printk(OSST_DEB_MSG "osst%d: start again from pos %d, eod %d, bad %d\n", dev, po
 
 static int osst_seek_logical_blk(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int logical_blk_num)
 {
-       int  estimate;
-       int  retries = 0;
-       int  dev     = TAPE_NR(STp->devt);
-
+        ST_partstat * STps = &(STp->ps[STp->partition]);
+       int     dev        = TAPE_NR(STp->devt);
+       int     retries    = 0;
+       int     frame_seq_estimate, ppos_estimate, move;
+       
        if (logical_blk_num < 0) logical_blk_num = 0;
-       /* FIXME -- this may not be valid for foreign formats */
-       if (logical_blk_num < 2980) estimate  = logical_blk_num + 10;
-       else                        estimate  = logical_blk_num + 20;
-
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%d: Seeking logical block %d (now at %d)\n",
-                         dev, logical_blk_num, STp->logical_blk_num);
-#endif
+       printk(OSST_DEB_MSG "osst%d:D: Seeking logical block %d (now at %d, size %d%c)\n",
+                               dev, logical_blk_num, STp->logical_blk_num, 
+                               STp->block_size<1024?STp->block_size:STp->block_size/1024,
+                               STp->block_size<1024?'b':'k');
+#endif
+       /* Do we know where we are? */
+       if (STps->drv_block >= 0) {
+               move                = logical_blk_num - STp->logical_blk_num;
+               if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
+               move               /= (OS_DATA_SIZE / STp->block_size);
+               frame_seq_estimate  = STp->frame_seq_number + move;
+       } else
+               frame_seq_estimate  = logical_blk_num * STp->block_size / OS_DATA_SIZE;
+
+       if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
+       else                           ppos_estimate = frame_seq_estimate + 20;
+       
        while (++retries < 10) {
-          osst_set_frame_position(STp, aSCpnt, estimate, 0);
-          if (osst_get_logical_blk(STp, aSCpnt, logical_blk_num, 1) >= 0)
-             return 0;
-          if (osst_get_logical_blk(STp, aSCpnt, -1, 1) < 0)
+          if (ppos_estimate > STp->eod_frame_ppos-2) {
+              frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
+              ppos_estimate       = STp->eod_frame_ppos - 2;
+          }
+          if (frame_seq_estimate < 0) {
+              frame_seq_estimate = 0;
+              ppos_estimate      = 10;
+          }
+          osst_set_frame_position(STp, aSCpnt, ppos_estimate, 0);
+          if (osst_get_logical_frame(STp, aSCpnt, frame_seq_estimate, 1) >= 0) {
+             /* we've located the estimated frame, now does it have our block? */
+             if (logical_blk_num <  STp->logical_blk_num ||
+                 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
+                if (STps->eof == ST_FM_HIT)
+                   move = logical_blk_num < STp->logical_blk_num? -2 : 1;
+                else {
+                   move                = logical_blk_num - STp->logical_blk_num;
+                   if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
+                   move               /= (OS_DATA_SIZE / STp->block_size);
+                }
+#if DEBUG
+                printk(OSST_DEB_MSG
+                       "osst%d:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
+                               dev, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
+                               STp->logical_blk_num, logical_blk_num, move);
+#endif
+                frame_seq_estimate += move;
+                ppos_estimate      += move;
+                continue;
+             } else {
+                STp->buffer->read_pointer  = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
+                STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
+                STp->logical_blk_num       =  logical_blk_num;
+#if DEBUG
+                printk(OSST_DEB_MSG 
+                       "osst%d:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
+                               dev, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer, 
+                               STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size, 
+                               STp->block_size);
+#endif
+                STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
+                if (STps->eof == ST_FM_HIT) {
+                    STps->drv_file++;
+                    STps->drv_block = 0;
+                } else {
+                    STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
+                                         STp->logical_blk_num -
+                                            (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
+                                       -1;
+                }
+                STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
+                return 0;
+             }
+          }
+          if (osst_get_logical_frame(STp, aSCpnt, -1, 1) < 0)
              goto error;
-          if (STp->logical_blk_num != logical_blk_num)
-             estimate += logical_blk_num - STp->logical_blk_num;
+          /* we are not yet at the estimated frame, adjust our estimate of its physical position */
+#if DEBUG
+          printk(OSST_DEB_MSG "osst%d:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n", 
+                          dev, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
+                          STp->logical_blk_num, logical_blk_num);
+#endif
+          if (frame_seq_estimate != STp->frame_seq_number)
+             ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
           else
              break;
        }
 error:
-       printk(KERN_WARNING "osst%d: Couldn't seek to logical block %d (at %d), %d retries\n", 
+       printk(KERN_ERR "osst%d:E: Couldn't seek to logical block %d (at %d), %d retries\n", 
                            dev, logical_blk_num, STp->logical_blk_num, retries);
        return (-EIO);
 }
 
-static int osst_seek_frame(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int frame)
+/* The values below are based on the OnStream frame payload size of 32K == 2**15,
+ * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
+ * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
+ * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
+ */
+#define OSST_FRAME_SHIFT  6
+#define OSST_SECTOR_SHIFT 9
+#define OSST_SECTOR_MASK  0x03F
+
+static int osst_get_sector(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
 {
-        ST_partstat   * STps = &(STp->ps[STp->partition]);
-       int             r;
+       int     sector;
+#if DEBUG
+       int     dev = TAPE_NR(STp->devt);
+
+       printk(OSST_DEB_MSG
+               "osst%d:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
+               dev, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
+               STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
+               STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
+               STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
+               STp->buffer->read_pointer, STp->ps[STp->partition].eof);
+#endif
+       /* do we know where we are inside a file? */
+       if (STp->ps[STp->partition].drv_block >= 0) {
+               sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
+                               STp->first_frame_position) << OSST_FRAME_SHIFT;
+               if (STp->ps[STp->partition].rw == ST_WRITING)
+                       sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
+               else
+                       sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
+       } else {
+               sector = osst_get_frame_position(STp, aSCpnt);
+               if (sector > 0)
+                       sector <<= OSST_FRAME_SHIFT;
+       }
+       return sector;
+}
 
+static int osst_seek_sector(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int sector)
+{
+        ST_partstat   * STps   = &(STp->ps[STp->partition]);
+       int             frame  = sector >> OSST_FRAME_SHIFT,
+                       offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT, 
+                       r;
+#if DEBUG
+       int             dev    = TAPE_NR(STp->devt);
+
+       printk(OSST_DEB_MSG "osst%d:D: Seeking sector %d in frame %d at offset %d\n",
+                               dev, sector, frame, offset);
+#endif
        if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
 
        if (frame <= STp->first_data_ppos) {
-               STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
+               STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
                return (osst_set_frame_position(STp, aSCpnt, frame, 0));
        }
-       r = osst_set_frame_position(STp, aSCpnt, frame-1, 0);
+       r = osst_set_frame_position(STp, aSCpnt, offset?frame:frame-1, 0);
        if (r < 0) return r;
 
-       r = osst_get_logical_blk(STp, aSCpnt, -1, 1);
+       r = osst_get_logical_frame(STp, aSCpnt, -1, 1);
        if (r < 0) return r;
 
-       if (osst_get_frame_position(STp, aSCpnt) != frame) return (-EIO);
+       if (osst_get_frame_position(STp, aSCpnt) != (offset?frame+1:frame)) return (-EIO);
 
-       STp->logical_blk_num++;
-       STp->logical_blk_in_buffer = 0;
-       STps->drv_file  = htonl(STp->buffer->aux->filemark_cnt);
-       STps->drv_block = -1;
-       STps->eof       = ST_NOEOF; /* FIXME test for eod */
+       if (offset) {
+               STp->logical_blk_num      += offset / STp->block_size;
+               STp->buffer->read_pointer  = offset;
+               STp->buffer->buffer_bytes -= offset;
+       } else {
+               STp->frame_seq_number++;
+               STp->frame_in_buffer       = 0;
+               STp->logical_blk_num      += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
+               STp->buffer->buffer_bytes  = STp->buffer->read_pointer = 0;
+       }
+       STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
+       if (STps->eof == ST_FM_HIT) {
+               STps->drv_file++;
+               STps->drv_block = 0;
+       } else {
+               STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
+                                   STp->logical_blk_num -
+                                       (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
+                                 -1;
+       }
+       STps->eof       = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
+#if DEBUG
+       printk(OSST_DEB_MSG
+               "osst%d:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
+               dev, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
+               STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
+#endif
        return 0;
 }
 
@@ -992,38 +1171,43 @@ static int osst_seek_frame(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int frame)
  * Read back the drive's internal buffer contents, as a part
  * of the write error recovery mechanism for old OnStream
  * firmware revisions.
+ * Precondition for this function to work: all frames in the
+ * drive's buffer must be of one type (DATA, MARK or EOD)!
  */
 static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt,
-                                       unsigned int block, unsigned int skip, int pending)
+                                       unsigned int frame, unsigned int skip, int pending)
 {
        Scsi_Cmnd     * SCpnt = * aSCpnt;
        unsigned char * buffer, * p;
        unsigned char   cmd[MAX_COMMAND_SIZE];
-       int             frames, flag, new_block, i, logical_blk_num;
-       int             dev  = TAPE_NR(STp->devt);
-       long            startwait = jiffies;
+       int             flag, new_frame, i;
+       int             nframes          = STp->cur_frames;
+       int             blks_per_frame   = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
+       int             frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
+                                               - (nframes + pending - 1);
+       int             logical_blk_num  = ntohl(STp->buffer->aux->logical_blk_num) 
+                                               - (nframes + pending - 1) * blks_per_frame;
+       int             dev              = TAPE_NR(STp->devt);
+       long            startwait        = jiffies;
 #if DEBUG
-       int             dbg = debugging;
+       int             dbg              = debugging;
 #endif
 
-       frames = STp->cur_frames;
-       if ((buffer = (unsigned char *)vmalloc((frames + pending) * OS_DATA_SIZE)) == NULL)
+       if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
                return (-EIO);
 
-       logical_blk_num = STp->logical_blk_num - frames - pending;
-       printk(KERN_INFO "osst%d: Reading back %d frames from drive buffer%s\n",
-                        dev, frames, pending?" and one that was pending":"");
+       printk(KERN_INFO "osst%d:I: Reading back %d frames from drive buffer%s\n",
+                        dev, nframes, pending?" and one that was pending":"");
 
-       if (pending) {
-               osst_copy_from_buffer(STp->buffer, (p = &buffer[frames * OS_DATA_SIZE]));
-//             memcpy((p = &buffer[frames * OS_DATA_SIZE]), STp->buffer->b_data, OS_DATA_SIZE);
+       osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
 #if DEBUG
-               if (debugging)
-                       printk(OSST_DEB_MSG "osst%d: Pending logical block %d, data %x %x %x %x\n",
-                                         dev, logical_blk_num + frames, p[0], p[1], p[2], p[3]);
+       if (pending && debugging)
+               printk(OSST_DEB_MSG "osst%d:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
+                               dev, frame_seq_number + nframes,
+                               logical_blk_num + nframes * blks_per_frame,
+                               p[0], p[1], p[2], p[3]);
 #endif
-       }
-       for (i = 0, p = buffer; i < frames; i++, p += OS_DATA_SIZE) {
+       for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
 
                memset(cmd, 0, MAX_COMMAND_SIZE);
                cmd[0] = 0x3C;          /* Buffer Read           */
@@ -1034,62 +1218,62 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Cmnd ** aS
                SCpnt = osst_do_scsi(SCpnt, STp, cmd, OS_FRAME_SIZE, STp->timeout, MAX_RETRIES, TRUE);
        
                if ((STp->buffer)->last_result_fatal) {
-                       printk(KERN_ERR "osst%d: Failed to read block back from OnStream buffer\n", dev);
+                       printk(KERN_ERR "osst%d:E: Failed to read frame back from OnStream buffer\n", dev);
                        vfree((void *)buffer);
                        *aSCpnt = SCpnt;
                        return (-EIO);
                }
                osst_copy_from_buffer(STp->buffer, p);
-//             memcpy(p, STp->buffer->b_data, OS_DATA_SIZE);
 #if DEBUG
                if (debugging)
-                       printk(OSST_DEB_MSG "osst%d: Read back logical block %d, data %x %x %x %x\n",
-                                         dev, logical_blk_num + i, p[0], p[1], p[2], p[3]);
+                       printk(OSST_DEB_MSG "osst%d:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
+                                         dev, frame_seq_number + i, p[0], p[1], p[2], p[3]);
 #endif
        }
         *aSCpnt = SCpnt;
        osst_get_frame_position(STp, aSCpnt);
 
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%d: Frames left in buffer: %d\n", dev, STp->cur_frames);
+       printk(OSST_DEB_MSG "osst%d:D: Frames left in buffer: %d\n", dev, STp->cur_frames);
 #endif
        /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
-       /* In the header we don't actually re-write the blocks that fail, just the ones after them */
+       /* In the header we don't actually re-write the frames that fail, just the ones after them */
 
-       for (flag=1, new_block=block, p=buffer, i=0; i < frames + pending; ) {
+       for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
 
                if (flag) {
                        if (STp->write_type == OS_WRITE_HEADER) {
                                i += skip;
                                p += skip * OS_DATA_SIZE;
                        }
-                       else if (new_block < 2990 && new_block+skip+frames+pending >= 2990)
-                               new_block = 3000-i;
+                       else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
+                               new_frame = 3000-i;
                        else
-                               new_block += skip;
+                               new_frame += skip;
 #if DEBUG
-                       printk(OSST_DEB_MSG "osst%d: Position to frame %d, write lblk %d\n",
-                                               dev, new_block+i, logical_blk_num+i); /* FIXME var blk sz */
+                       printk(OSST_DEB_MSG "osst%d:D: Position to frame %d, write fseq %d\n",
+                                               dev, new_frame+i, frame_seq_number+i);
 #endif
-                       osst_set_frame_position(STp, aSCpnt, new_block + i, 0);
+                       osst_set_frame_position(STp, aSCpnt, new_frame + i, 0);
                        osst_wait_ready(STp, aSCpnt, 60);
                        osst_get_frame_position(STp, aSCpnt);
                        SCpnt = * aSCpnt;
 
-                       if (new_block > block + 1000) {
-                               printk(KERN_ERR "osst%d: Failed to find valid tape media\n", dev);
+                       if (new_frame > frame + 1000) {
+                               printk(KERN_ERR "osst%d:E: Failed to find writable tape media\n", dev);
                                vfree((void *)buffer);
                                return (-EIO);
                        }
                        flag = 0;
-                       if ( i >= frames + pending ) break;
+                       if ( i >= nframes + pending ) break;
                }
                osst_copy_to_buffer(STp->buffer, p);
-//             memcpy(STp->buffer->b_data, p, OS_DATA_SIZE);
                /*
                 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
                 */
-               osst_init_aux(STp, STp->buffer->aux->frame_type, logical_blk_num+i );
+               osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
+                               logical_blk_num + i*blks_per_frame,
+                               ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
                memset(cmd, 0, MAX_COMMAND_SIZE);
                cmd[0] = WRITE_6;
                cmd[1] = 1;
@@ -1097,7 +1281,10 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Cmnd ** aS
 
 #if DEBUG
                if (debugging)
-                       printk(OSST_DEB_MSG "osst%d: About to attempt to write to frame %d\n", dev, new_block+i);
+                       printk(OSST_DEB_MSG
+                               "osst%d:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
+                               dev, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
+                               p[0], p[1], p[2], p[3]);
 #endif
                SCpnt = osst_do_scsi(SCpnt, STp, cmd, OS_FRAME_SIZE, STp->timeout, MAX_WRITE_RETRIES, TRUE);
 
@@ -1107,9 +1294,9 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Cmnd ** aS
                        p += OS_DATA_SIZE; i++;
 
                        /* if we just sent the last frame, wait till all successfully written */
-                       if ( i == frames + pending ) {
+                       if ( i == nframes + pending ) {
 #if DEBUG
-                               printk(OSST_DEB_MSG "osst%d: Check re-write successful\n", dev);
+                               printk(OSST_DEB_MSG "osst%d:D: Check re-write successful\n", dev);
 #endif
                                memset(cmd, 0, MAX_COMMAND_SIZE);
                                cmd[0] = WRITE_FILEMARKS;
@@ -1118,8 +1305,8 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Cmnd ** aS
 
 #if DEBUG
                                if (debugging) {
-                                       printk(OSST_DEB_MSG "osst%d: Sleeping in re-write wait ready\n", dev);
-                                       printk(OSST_DEB_MSG "osst%d: Turning off debugging for a while\n", dev);
+                                       printk(OSST_DEB_MSG "osst%d:D: Sleeping in re-write wait ready\n", dev);
+                                       printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);
                                        debugging = 0;
                                }
 #endif
@@ -1144,44 +1331,47 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Cmnd ** aS
                                }
 #if DEBUG
                                debugging = dbg;
-                               printk(OSST_DEB_MSG "osst%d: Wait re-write finished\n", dev);
+                               printk(OSST_DEB_MSG "osst%d:D: Wait re-write finished\n", dev);
 #endif
                        }
                }
+               *aSCpnt = SCpnt;
                if (flag) {
                        if ((SCpnt->sense_buffer[ 2] & 0x0f) == 13 &&
                             SCpnt->sense_buffer[12]         ==  0 &&
                             SCpnt->sense_buffer[13]         ==  2) {
-                               printk(KERN_ERR "osst%d: Volume overflow in write error recovery\n", dev);
+                               printk(KERN_ERR "osst%d:E: Volume overflow in write error recovery\n", dev);
                                vfree((void *)buffer);
                                return (-EIO);                  /* hit end of tape = fail */
                        }
                        i = ((SCpnt->sense_buffer[3] << 24) |
                             (SCpnt->sense_buffer[4] << 16) |
                             (SCpnt->sense_buffer[5] <<  8) |
-                             SCpnt->sense_buffer[6]        ) - new_block;
+                             SCpnt->sense_buffer[6]        ) - new_frame;
                        p = &buffer[i * OS_DATA_SIZE];
 #if DEBUG
-                       printk(OSST_DEB_MSG "osst%d: Additional write error at %d\n", dev, new_block+i);
+                       printk(OSST_DEB_MSG "osst%d:D: Additional write error at %d\n", dev, new_frame+i);
 #endif
                        osst_get_frame_position(STp, aSCpnt);
 #if DEBUG
-                       printk(OSST_DEB_MSG "osst%d: reported frame positions: host = %d, tape = %d\n",
+                       printk(OSST_DEB_MSG "osst%d:D: reported frame positions: host = %d, tape = %d\n",
                                          dev, STp->first_frame_position, STp->last_frame_position);
 #endif
                }
-               *aSCpnt = SCpnt;
        }    
+       if (!pending)
+               osst_copy_to_buffer(STp->buffer, p);    /* so buffer content == at entry in all cases */
        vfree((void *)buffer);
        return 0;
 }
 
 static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt,
-                                       unsigned int block, unsigned int skip, int pending)
+                                       unsigned int frame, unsigned int skip, int pending)
 {
        unsigned char   cmd[MAX_COMMAND_SIZE];
-       Scsi_Cmnd     * SCpnt     = * aSCpnt;
+       Scsi_Cmnd     * SCpnt;
        int             dev       = TAPE_NR(STp->devt);
+       int             expected  __attribute__ ((__unused__));
        int             attempts  = 1000 / skip;
        int             flag      = 1;
        long            startwait = jiffies;
@@ -1194,23 +1384,24 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt,
 #if DEBUG
                        debugging = dbg;
 #endif
-                       if (block < 2990 && block+skip+STp->cur_frames+pending >= 2990)
-                               block = 3000-skip;
+                       if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
+                               frame = 3000-skip;
+                       expected = frame+skip+STp->cur_frames+pending;
 #if DEBUG
-                       printk(OSST_DEB_MSG "osst%d: Position to frame %d, re-write from lblk %d\n",
-                                         dev, block+skip, STp->logical_blk_num-STp->cur_frames-pending);
+                       printk(OSST_DEB_MSG "osst%d:D: Position to fppos %d, re-write from fseq %d\n",
+                                         dev, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
 #endif
-                       osst_set_frame_position(STp, aSCpnt, block + skip, 1);
+                       osst_set_frame_position(STp, aSCpnt, frame + skip, 1);
                        flag = 0;
                        attempts--;
                }
                if (osst_get_frame_position(STp, aSCpnt) < 0) {         /* additional write error */
 #if DEBUG
-                       printk(OSST_DEB_MSG "osst%d: Addl error, host %d, tape %d, buffer %d\n",
+                       printk(OSST_DEB_MSG "osst%d:D: Addl error, host %d, tape %d, buffer %d\n",
                                          dev, STp->first_frame_position,
                                          STp->last_frame_position, STp->cur_frames);
 #endif
-                       block = STp->last_frame_position;
+                       frame = STp->last_frame_position;
                        flag = 1;
                        continue;
                }
@@ -1221,10 +1412,10 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt,
                        cmd[1] = 1;
                        cmd[4] = 1;
 #if DEBUG
-                       printk(OSST_DEB_MSG "osst%d: About to write pending lblk %d at frame %d\n",
-                                         dev, STp->logical_blk_num-1, STp->first_frame_position);
+                       printk(OSST_DEB_MSG "osst%d:D: About to write pending fseq %d at fppos %d\n",
+                                         dev, STp->frame_seq_number-1, STp->first_frame_position);
 #endif
-                       SCpnt = osst_do_scsi(SCpnt, STp, cmd, OS_FRAME_SIZE, STp->timeout,
+                       SCpnt = osst_do_scsi(*aSCpnt, STp, cmd, OS_FRAME_SIZE, STp->timeout,
                                                                        MAX_WRITE_RETRIES, TRUE);
                        *aSCpnt = SCpnt;
 
@@ -1232,8 +1423,8 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt,
                                if ((SCpnt->sense_buffer[ 2] & 0x0f) == 13 &&
                                     SCpnt->sense_buffer[12]         ==  0 &&
                                     SCpnt->sense_buffer[13]         ==  2) {
-                                       printk(OSST_DEB_MSG
-                                              "osst%d: Volume overflow in write error recovery\n",
+                                       printk(KERN_ERR
+                                              "osst%d:E: Volume overflow in write error recovery\n",
                                               dev);
                                        break;                          /* hit end of tape = fail */
                                }
@@ -1247,20 +1438,25 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt,
                if (STp->cur_frames == 0) {
 #if DEBUG
                        debugging = dbg;
-                       printk(OSST_DEB_MSG "osst%d: Wait re-write finished\n", dev);
+                       printk(OSST_DEB_MSG "osst%d:D: Wait re-write finished\n", dev);
 #endif
+                       if (STp->first_frame_position != expected) {
+                               printk(KERN_ERR "osst%d:A: Actual position %d - expected %d\n", 
+                                               dev, STp->first_frame_position, expected);
+                               return (-EIO);
+                       }
                        return 0;
                }
 #if DEBUG
                if (debugging) {
-                       printk(OSST_DEB_MSG "osst%d: Sleeping in re-write wait ready\n", dev);
-                       printk(OSST_DEB_MSG "osst%d: Turning off debugging for a while\n", dev);
+                       printk(OSST_DEB_MSG "osst%d:D: Sleeping in re-write wait ready\n", dev);
+                       printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);
                        debugging = 0;
                }
 #endif
                schedule_timeout(HZ / 10);
        }
-       printk(KERN_ERR "osst%d: Failed to find valid tape media\n", dev);
+       printk(KERN_ERR "osst%d:E: Failed to find valid tape media\n", dev);
 #if DEBUG
        debugging = dbg;
 #endif
@@ -1278,7 +1474,7 @@ static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, in
        int           dev    = TAPE_NR(STp->devt);
        int           retval = 0;
        int           rw_state;
-       unsigned int  block, skip;
+       unsigned int  frame, skip;
 
        rw_state = STps->rw;
 
@@ -1286,54 +1482,57 @@ static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, in
          || SCpnt->sense_buffer[12]         != 12
          || SCpnt->sense_buffer[13]         != 0) {
 #if DEBUG
-               printk(OSST_DEB_MSG "osst%d: Write error recovery cannot handle %02x:%02x:%02x\n",
+               printk(OSST_DEB_MSG "osst%d:D: Write error recovery cannot handle %02x:%02x:%02x\n",
                        dev, SCpnt->sense_buffer[ 2], SCpnt->sense_buffer[12], SCpnt->sense_buffer[13]);
 #endif
                return (-EIO);
        }
-       block = (SCpnt->sense_buffer[3] << 24) |
+       frame = (SCpnt->sense_buffer[3] << 24) |
                (SCpnt->sense_buffer[4] << 16) |
                (SCpnt->sense_buffer[5] <<  8) |
                 SCpnt->sense_buffer[6];
        skip  =  SCpnt->sense_buffer[9];
  
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%d: Detected physical bad block at %u, advised to skip %d\n", dev, block, skip);
+       printk(OSST_DEB_MSG "osst%d:D: Detected physical bad frame at %u, advised to skip %d\n", 
+                       dev, frame, skip);
 #endif
        osst_get_frame_position(STp, aSCpnt);
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%d: reported frame positions: host = %d, tape = %d\n",
+       printk(OSST_DEB_MSG "osst%d:D: reported frame positions: host = %d, tape = %d\n",
                        dev, STp->first_frame_position, STp->last_frame_position);
 #endif
        switch (STp->write_type) {
           case OS_WRITE_DATA:
           case OS_WRITE_EOD:
           case OS_WRITE_NEW_MARK:
-               printk(KERN_WARNING "osst%d: Relocating %d buffered logical blocks to physical block %u\n",
-                       dev, STp->cur_frames, block + skip);
+               printk(KERN_WARNING
+                       "osst%d:I: Relocating %d buffered logical frames from position %u to %u\n",
+                       dev, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
                if (STp->os_fw_rev >= 10600)
-                       retval = osst_reposition_and_retry(STp, aSCpnt, block, skip, pending);
+                       retval = osst_reposition_and_retry(STp, aSCpnt, frame, skip, pending);
                else
-                       retval = osst_read_back_buffer_and_rewrite(STp, aSCpnt, block, skip, pending);
+                       retval = osst_read_back_buffer_and_rewrite(STp, aSCpnt, frame, skip, pending);
+               printk(KERN_WARNING "osst%d:I: Write error%srecovered\n", dev, retval?" not ":" ");
                break;
           case OS_WRITE_LAST_MARK:
-               printk(KERN_ERR "osst%d: Bad block in update last marker, fatal\n", dev);
-               osst_set_frame_position(STp, aSCpnt, block + STp->cur_frames + pending, 0);
+               printk(KERN_ERR "osst%d:E: Bad frame in update last marker, fatal\n", dev);
+               osst_set_frame_position(STp, aSCpnt, frame + STp->cur_frames + pending, 0);
                retval = -EIO;
                break;
           case OS_WRITE_HEADER:
-               printk(KERN_WARNING "osst%d: Bad block in header partition, skipped\n", dev);
-               retval = osst_read_back_buffer_and_rewrite(STp, aSCpnt, block, 1, pending);
+               printk(KERN_WARNING "osst%d:I: Bad frame in header partition, skipped\n", dev);
+               retval = osst_read_back_buffer_and_rewrite(STp, aSCpnt, frame, 1, pending);
                break;
           default:
-               printk(KERN_WARNING "osst%d: Bad block in filler, ignored\n", dev);
-               osst_set_frame_position(STp, aSCpnt, block + STp->cur_frames + pending, 0);
+               printk(KERN_INFO "osst%d:I: Bad frame in filler, ignored\n", dev);
+               osst_set_frame_position(STp, aSCpnt, frame + STp->cur_frames + pending, 0);
        }
        osst_get_frame_position(STp, aSCpnt);
 #if DEBUG
-       printk(KERN_ERR "osst%d: Positioning complete, cur_frames %d, pos %d, tape pos %d\n", 
+       printk(OSST_DEB_MSG "osst%d:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n", 
                        dev, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
-       printk(OSST_DEB_MSG "osst%d: next logical block to write: %d\n", dev, STp->logical_blk_num);
+       printk(OSST_DEB_MSG "osst%d:D: next logical frame to write: %d\n", dev, STp->logical_blk_num);
 #endif
        if (retval == 0) {
                STp->recover_count++;
@@ -1350,10 +1549,12 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Cmnd ** a
        int     last_mark_ppos = -1;
 
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%d: Reached space_over_filemarks_backwards %d %d\n", dev, mt_op, mt_count);
+       printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_backwards %d %d\n", dev, mt_op, mt_count);
+#endif
+       if (osst_get_logical_frame(STp, aSCpnt, -1, 0) < 0) {
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_bwd\n", dev);
 #endif
-       if (osst_get_logical_blk(STp, aSCpnt, -1, 0) < 0) {
-               printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks_bwd\n", dev);
                return -EIO;
        }
        if (STp->linux_media_version >= 4) {
@@ -1369,12 +1570,13 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Cmnd ** a
                    STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
 
                        last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
-#if 1 //DEBUG
+#if DEBUG
                if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
-                       printk(OSST_DEB_MSG "osst%i: Filemark lookup fail due to %s\n", dev,
+                       printk(OSST_DEB_MSG "osst%i:D: Filemark lookup fail due to %s\n", dev,
                               STp->header_cache == NULL?"lack of header cache":"count out of range");
                else
-                       printk(OSST_DEB_MSG "osst%i: Filemark lookup: prev mark %d (%s), skip %d to %d\n", dev, cnt,
+                       printk(OSST_DEB_MSG "osst%i:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
+                              dev, cnt,
                               ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
                                (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
                                         STp->buffer->aux->last_mark_ppos))?"match":"error",
@@ -1382,22 +1584,28 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Cmnd ** a
 #endif
                if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
                        osst_set_frame_position(STp, aSCpnt, last_mark_ppos, 0);
-                       if (osst_get_logical_blk(STp, aSCpnt, -1, 0) < 0) {
-                               printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev);
+                       if (osst_get_logical_frame(STp, aSCpnt, -1, 0) < 0) {
+#if DEBUG
+                               printk(OSST_DEB_MSG
+                                       "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);
+#endif
                                return (-EIO);
                        }
                        if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
-                               printk(KERN_INFO "osst%i: Expected to find marker at block %d, not found\n",
+                               printk(KERN_WARNING "osst%i:W: Expected to find marker at ppos %d, not found\n",
                                                 dev, last_mark_ppos);
                                return (-EIO);
                        }
                        if (mt_op == MTBSFM) {
-                               STp->logical_blk_num++;
-                               STp->logical_blk_in_buffer = 0;
+                               STp->frame_seq_number++;
+                               STp->frame_in_buffer  = 0;
+                               STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
                        }
                        return 0;
                }
-               printk(KERN_INFO "osst%i: Reverting to scan filemark backwards\n", dev);
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Reverting to scan filemark backwards\n", dev);
+#endif
        }
        cnt = 0;
        while (cnt != mt_count) {
@@ -1405,22 +1613,26 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Cmnd ** a
                if (last_mark_ppos == -1)
                        return (-EIO);
 #if DEBUG
-               printk(OSST_DEB_MSG "osst%i: Positioning to last mark at %d\n", dev, last_mark_ppos);
+               printk(OSST_DEB_MSG "osst%d:D: Positioning to last mark at %d\n", dev, last_mark_ppos);
 #endif
                osst_set_frame_position(STp, aSCpnt, last_mark_ppos, 0);
                cnt++;
-               if (osst_get_logical_blk(STp, aSCpnt, -1, 0) < 0) {
-                       printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev);
+               if (osst_get_logical_frame(STp, aSCpnt, -1, 0) < 0) {
+#if DEBUG
+                       printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);
+#endif
                        return (-EIO);
                }
                if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
-                       printk(KERN_INFO "osst%i: expected to find marker at block %d, not found\n", dev, last_mark_ppos);
+                       printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n",
+                                       dev, last_mark_ppos);
                        return (-EIO);
                }
        }
        if (mt_op == MTBSFM) {
-               STp->logical_blk_num++;
-               STp->logical_blk_in_buffer = 0;
+               STp->frame_seq_number++;
+               STp->frame_in_buffer  = 0;
+               STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
        }
        return 0;
 }
@@ -1432,30 +1644,34 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Cmnd ** a
  */
 static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int mt_op, int mt_count)
 {
-       int           dev = TAPE_NR(STp->devt);
        int           cnt = 0;
+#if DEBUG
+       int     dev = TAPE_NR(STp->devt);
 
+       printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_forward_slow %d %d\n", dev, mt_op, mt_count);
+#endif
+       if (osst_get_logical_frame(STp, aSCpnt, -1, 0) < 0) {
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%d: Reached space_over_filemarks_forward_slow %d %d\n", dev, mt_op, mt_count);
+               printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd\n", dev);
 #endif
-       if (osst_get_logical_blk(STp, aSCpnt, -1, 0) < 0) {
-               printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks_fwd\n", dev);
                return (-EIO);
        }
        while (1) {
-               if (osst_get_logical_blk(STp, aSCpnt, -1, 0) < 0) {
-                       printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev);
+               if (osst_get_logical_frame(STp, aSCpnt, -1, 0) < 0) {
+#if DEBUG
+                       printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);
+#endif
                        return (-EIO);
                }
                if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
                        cnt++;
                if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
 #if DEBUG
-                       printk(OSST_DEB_MSG "osst%i: space_fwd: EOD reached\n", dev);
+                       printk(OSST_DEB_MSG "osst%d:D: space_fwd: EOD reached\n", dev);
 #endif
                        if (STp->first_frame_position > STp->eod_frame_ppos+1) {
 #if DEBUG
-                               printk(OSST_DEB_MSG "osst%i: EOD position corrected (%d=>%d)\n",
+                               printk(OSST_DEB_MSG "osst%d:D: EOD position corrected (%d=>%d)\n",
                                                dev, STp->eod_frame_ppos, STp->first_frame_position-1);
 #endif
                                STp->eod_frame_ppos = STp->first_frame_position-1;
@@ -1464,11 +1680,12 @@ static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Cmnd
                }
                if (cnt == mt_count)
                        break;
-               STp->logical_blk_in_buffer = 0;
+               STp->frame_in_buffer = 0;
        }
        if (mt_op == MTFSF) {
-               STp->logical_blk_num++;
-               STp->logical_blk_in_buffer = 0;
+               STp->frame_seq_number++;
+               STp->frame_in_buffer  = 0;
+               STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
        }
        return 0;
 }
@@ -1483,10 +1700,12 @@ static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Cmnd
                      next_mark_ppos = -1;
 
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%d: Reached space_over_filemarks_forward_fast %d %d\n", dev, mt_op, mt_count);
+       printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_forward_fast %d %d\n", dev, mt_op, mt_count);
+#endif
+       if (osst_get_logical_frame(STp, aSCpnt, -1, 0) < 0) {
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd\n", dev);
 #endif
-       if (osst_get_logical_blk(STp, aSCpnt, -1, 0) < 0) {
-               printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks_fwd\n", dev);
                return (-EIO);
        }
 
@@ -1503,33 +1722,39 @@ static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Cmnd
                     (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
 
                        next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
-#if 1 //DEBUG
+#if DEBUG
                if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
-                       printk(OSST_DEB_MSG "osst%i: Filemark lookup fail due to %s\n", dev,
+                       printk(OSST_DEB_MSG "osst%d:D: Filemark lookup fail due to %s\n", dev,
                               STp->header_cache == NULL?"lack of header cache":"count out of range");
                else
-                       printk(OSST_DEB_MSG "osst%i: Filemark lookup: prev mark %d (%s), skip %d to %d\n", dev, cnt,
+                       printk(OSST_DEB_MSG "osst%d:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
+                              dev, cnt,
                               ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
                                (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
                                         STp->buffer->aux->last_mark_ppos))?"match":"error",
                               mt_count, next_mark_ppos);
 #endif
                if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
-                       printk(KERN_INFO "osst%i: Reverting to slow filemark space\n", dev);
+#if DEBUG
+                       printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev);
+#endif
                        return osst_space_over_filemarks_forward_slow(STp, aSCpnt, mt_op, mt_count);
                } else {
                        osst_set_frame_position(STp, aSCpnt, next_mark_ppos, 0);
-                       if (osst_get_logical_blk(STp, aSCpnt, -1, 0) < 0) {
-                               printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev);
+                       if (osst_get_logical_frame(STp, aSCpnt, -1, 0) < 0) {
+#if DEBUG
+                               printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n",
+                                                dev);
+#endif
                                return (-EIO);
                        }
                        if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
-                               printk(KERN_INFO "osst%i: Expected to find marker at block %d, not found\n",
+                               printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n",
                                                 dev, next_mark_ppos);
                                return (-EIO);
                        }
                        if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
-                               printk(KERN_INFO "osst%i: Expected to find marker %d at block %d, not %d\n",
+                               printk(KERN_WARNING "osst%d:W: Expected to find marker %d at ppos %d, not %d\n",
                                                 dev, cnt+mt_count, next_mark_ppos,
                                                 ntohl(STp->buffer->aux->filemark_cnt));
                                return (-EIO);
@@ -1544,24 +1769,28 @@ static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Cmnd
                                break;
                        if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
 #if DEBUG
-                               printk(OSST_DEB_MSG "osst%i: space_fwd: EOD reached\n", dev);
+                               printk(OSST_DEB_MSG "osst%d:D: space_fwd: EOD reached\n", dev);
 #endif
                                return (-EIO);
                        }
                        if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
                                if (STp->first_mark_ppos == -1) {
-                                       printk(KERN_INFO "osst%i: Reverting to slow filemark space\n", dev);
+#if DEBUG
+                                       printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev);
+#endif
                                        return osst_space_over_filemarks_forward_slow(STp, aSCpnt, mt_op, mt_count);
                                }
                                osst_set_frame_position(STp, aSCpnt, STp->first_mark_ppos, 0);
-                               if (osst_get_logical_blk(STp, aSCpnt, -1, 0) < 0) {
-                                       printk(KERN_INFO
-                                              "osst%i: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
+                               if (osst_get_logical_frame(STp, aSCpnt, -1, 0) < 0) {
+#if DEBUG
+                                       printk(OSST_DEB_MSG
+                                              "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
                                               dev);
+#endif
                                        return (-EIO);
                                }
                                if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
-                                       printk(KERN_INFO "osst%i: Expected to find filemark at %d\n",
+                                       printk(KERN_WARNING "osst%d:W: Expected to find filemark at %d\n",
                                                         dev, STp->first_mark_ppos);
                                        return (-EIO);
                                }
@@ -1575,28 +1804,35 @@ static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Cmnd
                while (cnt != mt_count) {
                        next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
                        if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
-                               printk(KERN_INFO "osst%i: Reverting to slow filemark space\n", dev);
+#if DEBUG
+                               printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev);
+#endif
                                return osst_space_over_filemarks_forward_slow(STp, aSCpnt, mt_op, mt_count - cnt);
                        }
 #if DEBUG
-                       else printk(OSST_DEB_MSG "osst%i: Positioning to next mark at %d\n", dev, next_mark_ppos);
+                       else printk(OSST_DEB_MSG "osst%d:D: Positioning to next mark at %d\n", dev, next_mark_ppos);
 #endif
                        osst_set_frame_position(STp, aSCpnt, next_mark_ppos, 0);
                        cnt++;
-                       if (osst_get_logical_blk(STp, aSCpnt, -1, 0) < 0) {
-                               printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev);
+                       if (osst_get_logical_frame(STp, aSCpnt, -1, 0) < 0) {
+#if DEBUG
+                               printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n",
+                                                dev);
+#endif
                                return (-EIO);
                        }
                        if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
-                               printk(KERN_INFO "osst%i: Expected to find marker at block %d, not found\n",
+                               printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n",
                                                 dev, next_mark_ppos);
                                return (-EIO);
                        }
                }
        }
-       if (mt_op == MTFSF) 
-               STp->logical_blk_num++;
-               STp->logical_blk_in_buffer = 0;
+       if (mt_op == MTFSF) {
+               STp->frame_seq_number++;
+               STp->frame_in_buffer  = 0;
+               STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
+       }
        return 0;
 }
 
@@ -1626,75 +1862,22 @@ static void osst_set_retries(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int retrie
        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
 
        if (debugging)
-           printk(OSST_DEB_MSG "osst%i: Setting number of retries on OnStream tape to %d\n", dev, retries);
+           printk(OSST_DEB_MSG "osst%d:D: Setting number of retries on OnStream tape to %d\n", dev, retries);
 
        SCpnt = osst_do_scsi(SCpnt, STp, cmd, cmd[4], STp->timeout, 0, TRUE);
        *aSCpnt = SCpnt;
 
        if ((STp->buffer)->last_result_fatal)
-           printk (KERN_ERR "osst%d: Couldn't set retries to %d\n", dev, retries);
+           printk (KERN_ERR "osst%d:D: Couldn't set retries to %d\n", dev, retries);
 }
 #endif
 
-#if 0
-static void osst_update_markers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int last_mark_ppos, int this_mark_ppos)
-{
-       int           dev = TAPE_NR(STp->devt);
-       int           frame,
-                     reslt;
-
-       if (STp->raw) return;
-
-       STp->last_mark_ppos = this_mark_ppos;
-       if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX) 
-               STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
-       if (STp->filemark_cnt++ == 0)
-               STp->first_mark_ppos = this_mark_ppos;
-
-       if (STp->linux_media_version >= 4) return;
-       if (last_mark_ppos == -1)          return;
-
-       STp->write_type = OS_WRITE_LAST_MARK;
-       frame = osst_get_frame_position(STp, aSCpnt);
-#if DEBUG
-       printk(OSST_DEB_MSG "osst%i: Update last_marker at frame %d\n", dev, last_mark_ppos);
-       printk(OSST_DEB_MSG "osst%i: current position %d, lblk %d, tape blk %d\n",
-                         dev, frame, STp->logical_blk_num, STp->last_frame_position);
-#endif
-       osst_set_frame_position(STp, aSCpnt, last_mark_ppos, 0);
-       osst_initiate_read (STp, aSCpnt);
-       reslt = osst_read_block(STp, aSCpnt, 180);
-
-       if (reslt) {
-               printk(KERN_WARNING "osst%i: couldn't read last marker\n", dev);
-               osst_set_frame_position(STp, aSCpnt, frame, 0);
-               return;
-       }
-       if (STp->buffer->aux->frame_type  != OS_FRAME_TYPE_MARKER) {
-               printk(KERN_WARNING "osst%i: expected marker at addr %d\n", dev, last_mark_ppos);
-               osst_set_frame_position(STp, aSCpnt, frame, 0);
-               return;
-       }
-#if DEBUG
-       printk(OSST_DEB_MSG "osst%i: writing back marker\n", dev);
-#endif
-       STp->buffer->aux->next_mark_ppos = htonl(this_mark_ppos);
-       osst_set_frame_position(STp, aSCpnt, last_mark_ppos, 0);
-       STp->dirty = 1;
-       if (osst_flush_write_buffer(STp, aSCpnt, 0) ||
-           osst_flush_drive_buffer(STp, aSCpnt)     ) {
-               printk(KERN_WARNING "osst%i: couldn't write marker back at addr %d\n", dev, last_mark_ppos);
-       }
-       osst_set_frame_position(STp, aSCpnt, frame, 0); 
-
-       return; /* FIXME -- errors should go back to user space */
-}
-#endif
 
 static int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
 {
        int     result;
-       int     this_mark_ppos;
+       int     this_mark_ppos = STp->first_frame_position;
+       int     this_mark_lbn  = STp->logical_blk_num;
 #if DEBUG
        int     dev = TAPE_NR(STp->devt);
 #endif
@@ -1702,22 +1885,20 @@ static int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
        if (STp->raw) return 0;
 
        STp->write_type = OS_WRITE_NEW_MARK;
-       this_mark_ppos = osst_get_frame_position(STp, aSCpnt);
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%i: Writing Filemark %i at frame %d (lblk %d)\n", 
-              dev, STp->filemark_cnt, this_mark_ppos, STp->logical_blk_num);
+       printk(OSST_DEB_MSG "osst%d:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n", 
+              dev, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
 #endif
-       osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->logical_blk_num++);
        STp->dirty = 1;
-       result  = osst_flush_write_buffer(STp, aSCpnt, 0);
+       result  = osst_flush_write_buffer(STp, aSCpnt);
        result |= osst_flush_drive_buffer(STp, aSCpnt);
-//printk(OSST_DEB_MSG "osst%d: Finished writing file\n",TAPE_NR(STp->devt));
+
        STp->last_mark_ppos = this_mark_ppos;
+       STp->last_mark_lbn  = this_mark_lbn;
        if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX) 
                STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
        if (STp->filemark_cnt++ == 0)
                STp->first_mark_ppos = this_mark_ppos;
-//     osst_update_markers(STp, aSCpnt, STp->last_mark_ppos, this_mark_ppos);
        return result;
 }
 
@@ -1731,70 +1912,67 @@ static int osst_write_eod(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
        if (STp->raw) return 0;
 
        STp->write_type = OS_WRITE_EOD;
-       STp->eod_frame_ppos = osst_get_frame_position(STp, aSCpnt);
+       STp->eod_frame_ppos = STp->first_frame_position;
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%i: Writing EOD at %d=>%d\n", dev, STp->logical_blk_num, STp->eod_frame_ppos);
+       printk(OSST_DEB_MSG "osst%d:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", dev,
+                       STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
 #endif
-       osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->logical_blk_num++);
        STp->dirty = 1;
 
-       result  = osst_flush_write_buffer(STp, aSCpnt, 0);      
+       result  = osst_flush_write_buffer(STp, aSCpnt); 
        result |= osst_flush_drive_buffer(STp, aSCpnt);
-       STp->eod_frame_lfa = --(STp->logical_blk_num);
+       STp->eod_frame_lfa = --(STp->frame_seq_number);
        return result;
 }
 
-static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int block, int count)
+static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int where, int count)
 {
        int           dev = TAPE_NR(STp->devt);
 
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%i: Reached onstream write filler group %d\n", dev, block);
+       printk(OSST_DEB_MSG "osst%d:D: Reached onstream write filler group %d\n", dev, where);
 #endif
        osst_wait_ready(STp, aSCpnt, 60 * 5);
-       osst_set_frame_position(STp, aSCpnt, block, 0);
+       osst_set_frame_position(STp, aSCpnt, where, 0);
        STp->write_type = OS_WRITE_FILLER;
-       osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0);
        while (count--) {
            memcpy(STp->buffer->b_data, "Filler", 6);
            STp->buffer->buffer_bytes = 6;
            STp->dirty = 1;
-           if (osst_flush_write_buffer(STp, aSCpnt, 0)) {
-               printk(KERN_INFO "osst%i: Couldn't write filler frame\n", dev);
+           if (osst_flush_write_buffer(STp, aSCpnt)) {
+               printk(KERN_INFO "osst%i:I: Couldn't write filler frame\n", dev);
                return (-EIO);
            }
        }
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%i: Exiting onstream write filler group\n", dev);
+       printk(OSST_DEB_MSG "osst%d:D: Exiting onstream write filler group\n", dev);
 #endif
        return osst_flush_drive_buffer(STp, aSCpnt);
 }
 
-static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int block, int count)
+static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int where, int count)
 {
        int     dev   = TAPE_NR(STp->devt);
        int     result;
 
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%i: Reached onstream write header group %d\n", dev, block);
+       printk(OSST_DEB_MSG "osst%d:D: Reached onstream write header group %d\n", dev, where);
 #endif
        osst_wait_ready(STp, aSCpnt, 60 * 5);
-       osst_set_frame_position(STp, aSCpnt, block, 0);
+       osst_set_frame_position(STp, aSCpnt, where, 0);
        STp->write_type = OS_WRITE_HEADER;
-       osst_init_aux(STp, OS_FRAME_TYPE_HEADER, STp->logical_blk_num);
        while (count--) {
            osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
-//         memcpy(STp->buffer->b_data, STp->header_cache, sizeof(os_header_t));
            STp->buffer->buffer_bytes = sizeof(os_header_t);
            STp->dirty = 1;
-           if (osst_flush_write_buffer(STp, aSCpnt, 0)) {
-               printk(KERN_INFO "osst%i: Couldn't write header frame\n", dev);
+           if (osst_flush_write_buffer(STp, aSCpnt)) {
+               printk(KERN_INFO "osst%i:I: Couldn't write header frame\n", dev);
                return (-EIO);
            }
        }
        result = osst_flush_drive_buffer(STp, aSCpnt);
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%i: Write onstream header group %s\n", dev, result?"failed":"done");
+       printk(OSST_DEB_MSG "osst%d:D: Write onstream header group %s\n", dev, result?"failed":"done");
 #endif
        return result;
 }
@@ -1806,18 +1984,18 @@ static int osst_write_header(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int locate
        int           dev   = TAPE_NR(STp->devt);
 
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%i: Writing tape header\n", dev);
+       printk(OSST_DEB_MSG "osst%d:D: Writing tape header\n", dev);
 #endif
        if (STp->raw) return 0;
 
        if (STp->header_cache == NULL) {
                if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
-                       printk(KERN_ERR "osst%i: Failed to allocate header cache\n", dev);
+                       printk(KERN_ERR "osst%i:E: Failed to allocate header cache\n", dev);
                        return (-ENOMEM);
                }
                memset(STp->header_cache, 0, sizeof(os_header_t));
 #if DEBUG
-               printk(OSST_DEB_MSG "osst%d: Allocated and cleared memory for header cache\n", dev);
+               printk(OSST_DEB_MSG "osst%d:D: Allocated and cleared memory for header cache\n", dev);
 #endif
        }
        if (STp->header_ok) STp->update_frame_cntr++;
@@ -1858,12 +2036,12 @@ static int osst_write_header(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int locate
 
        if (locate_eod) {
 #if DEBUG
-               printk(OSST_DEB_MSG "osst%i: locating back to eod frame addr %d\n", dev, STp->eod_frame_ppos);
+               printk(OSST_DEB_MSG "osst%d:D: Locating back to eod frame addr %d\n", dev, STp->eod_frame_ppos);
 #endif
                osst_set_frame_position(STp, aSCpnt, STp->eod_frame_ppos, 0);
        }
        if (reslt)
-               printk(KERN_WARNING "osst%i: write header failed\n", dev);
+               printk(KERN_ERR "osst%d:E: Write header failed\n", dev);
        else {
                memcpy(STp->application_sig, "LIN4", 4);
                STp->linux_media         = 1;
@@ -1878,15 +2056,15 @@ static int osst_reset_header(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
        if (STp->header_cache != NULL)
                memset(STp->header_cache, 0, sizeof(os_header_t));
 
-       STp->logical_blk_num = 0;
-       STp->logical_blk_in_buffer = 0;
+       STp->logical_blk_num = STp->frame_seq_number = 0;
+       STp->frame_in_buffer = 0;
        STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
        STp->filemark_cnt = 0;
-       STp->first_mark_ppos = STp->last_mark_ppos = -1;
+       STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
        return osst_write_header(STp, aSCpnt, 1);
 }
 
-static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int block)
+static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int ppos)
 {
        int           dev = TAPE_NR(STp->devt);
        os_header_t * header;
@@ -1898,17 +2076,17 @@ static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int b
        if (STp->raw)
                return 1;
 
-       if (block == 5 || block == 0xbae || STp->buffer->last_result_fatal) {
-               if (osst_set_frame_position(STp, aSCpnt, block, 0))
-                       printk(KERN_WARNING "osst%i: Couldn't position tape\n", dev);
+       if (ppos == 5 || ppos == 0xbae || STp->buffer->last_result_fatal) {
+               if (osst_set_frame_position(STp, aSCpnt, ppos, 0))
+                       printk(KERN_WARNING "osst%i:W: Couldn't position tape\n", dev);
                if (osst_initiate_read (STp, aSCpnt)) {
-                       printk(KERN_WARNING "osst%i: Couldn't initiate read\n", dev);
+                       printk(KERN_WARNING "osst%i:W: Couldn't initiate read\n", dev);
                        return 0;
                }
        }
-       if (osst_read_block(STp, aSCpnt, 180)) {
+       if (osst_read_frame(STp, aSCpnt, 180)) {
 #if DEBUG
-               printk(OSST_DEB_MSG "osst%i: Couldn't read header frame\n", dev);
+               printk(OSST_DEB_MSG "osst%d:D: Couldn't read header frame\n", dev);
 #endif
                return 0;
        }
@@ -1916,7 +2094,20 @@ static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int b
        aux = STp->buffer->aux;
        if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
 #if DEBUG
-               printk(OSST_DEB_MSG "osst%i: Skipping non-header frame (%d)\n", dev, block);
+               printk(OSST_DEB_MSG "osst%d:D: Skipping non-header frame (%d)\n", dev, ppos);
+#endif
+               return 0;
+       }
+       if (ntohl(aux->frame_seq_num)              != 0                   ||
+           ntohl(aux->logical_blk_num)            != 0                   ||
+                 aux->partition.partition_num     != OS_CONFIG_PARTITION ||
+           ntohl(aux->partition.first_frame_ppos) != 0                   ||
+           ntohl(aux->partition.last_frame_ppos)  != 0xbb7               ) {
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Invalid header frame (%d,%d,%d,%d,%d)\n", dev,
+                               ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
+                               aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
+                               ntohl(aux->partition.last_frame_ppos));
 #endif
                return 0;
        }
@@ -1924,51 +2115,57 @@ static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int b
            strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
                 strncpy(id_string, header->ident_str, 7);
                id_string[7] = 0;
-               printk(KERN_INFO "osst%i: Invalid header identification string %s\n", dev, id_string);
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Invalid header identification string %s\n", dev, id_string);
+#endif
                return 0;
        }
        update_frame_cntr = ntohl(aux->update_frame_cntr);
        if (update_frame_cntr < STp->update_frame_cntr) {
 #if DEBUG
-               printk(OSST_DEB_MSG "osst%i: Skipping frame %d with update_frame_counter %d<%d\n",
-                                  dev, block, update_frame_cntr, STp->update_frame_cntr);
+               printk(OSST_DEB_MSG "osst%d:D: Skipping frame %d with update_frame_counter %d<%d\n",
+                                  dev, ppos, update_frame_cntr, STp->update_frame_cntr);
 #endif
                return 0;
        }
        if (header->major_rev != 1 || header->minor_rev != 4 ) {
-               printk(KERN_INFO "osst%i: %s revision %d.%d detected (1.4 supported)\n", 
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: %s revision %d.%d detected (1.4 supported)\n", 
                                 dev, (header->major_rev != 1 || header->minor_rev < 2 || 
                                       header->minor_rev  > 4 )? "Invalid" : "Warning:",
                                 header->major_rev, header->minor_rev);
+#endif
                if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
                        return 0;
        }
+#if DEBUG
        if (header->pt_par_num != 1)
-               printk(KERN_INFO "osst%i: Warning: %d partitions defined, only one supported\n", 
+               printk(KERN_INFO "osst%i:W: %d partitions defined, only one supported\n", 
                                 dev, header->pt_par_num);
+#endif
        memcpy(id_string, aux->application_sig, 4);
        id_string[4] = 0;
        if (memcmp(id_string, "LIN", 3) == 0) {
                STp->linux_media = 1;
                linux_media_version = id_string[3] - '0';
                if (linux_media_version != 4)
-                       printk(KERN_INFO "osst%i: Linux media version %d detected (current 4)\n",
+                       printk(KERN_INFO "osst%i:I: Linux media version %d detected (current 4)\n",
                                         dev, linux_media_version);
        } else {
-               printk(KERN_WARNING "osst%i: non Linux media detected (%s)\n", dev, id_string);
+               printk(KERN_WARNING "osst%i:W: Non Linux media detected (%s)\n", dev, id_string);
                return 0;
        }
        if (linux_media_version < STp->linux_media_version) {
 #if DEBUG
-               printk(OSST_DEB_MSG "osst%i: Skipping frame %d with linux_media_version %d\n",
-                                 dev, block, linux_media_version);
+               printk(OSST_DEB_MSG "osst%d:D: Skipping frame %d with linux_media_version %d\n",
+                                 dev, ppos, linux_media_version);
 #endif
                return 0;
        }
        if (linux_media_version > STp->linux_media_version) {
 #if DEBUG
-               printk(OSST_DEB_MSG "osst%i: Frame %d sets linux_media_version to %d\n",
-                                  dev, block, linux_media_version);
+               printk(OSST_DEB_MSG "osst%d:D: Frame %d sets linux_media_version to %d\n",
+                                  dev, ppos, linux_media_version);
 #endif
                memcpy(STp->application_sig, id_string, 5);
                STp->linux_media_version = linux_media_version;
@@ -1976,16 +2173,16 @@ static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int b
        }
        if (update_frame_cntr > STp->update_frame_cntr) {
 #if DEBUG
-               printk(OSST_DEB_MSG "osst%i: Frame %d sets update_frame_counter to %d\n",
-                                  dev, block, update_frame_cntr);
+               printk(OSST_DEB_MSG "osst%d:D: Frame %d sets update_frame_counter to %d\n",
+                                  dev, ppos, update_frame_cntr);
 #endif
                if (STp->header_cache == NULL) {
                        if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
-                               printk(KERN_ERR "osst%i: Failed to allocate header cache\n", dev);
+                               printk(KERN_ERR "osst%i:E: Failed to allocate header cache\n", dev);
                                return 0;
                        }
 #if DEBUG
-                       printk(OSST_DEB_MSG "osst%d: Allocated memory for header cache\n", dev);
+                       printk(OSST_DEB_MSG "osst%d:D: Allocated memory for header cache\n", dev);
 #endif
                }
                osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
@@ -1998,19 +2195,22 @@ static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int b
                STp->filemark_cnt      = ntohl(aux->filemark_cnt);
                STp->first_mark_ppos   = ntohl(aux->next_mark_ppos);
                STp->last_mark_ppos    = ntohl(aux->last_mark_ppos);
+               STp->last_mark_lbn     = ntohl(aux->last_mark_lbn);
                STp->update_frame_cntr = update_frame_cntr;
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%i: detected write pass %d, update frame counter %d, filemark counter %d\n",
+       printk(OSST_DEB_MSG "osst%d:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
                          dev, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
-       printk(OSST_DEB_MSG "osst%i: first data frame on tape = %d, last = %d, eod frame = %d\n", dev,
+       printk(OSST_DEB_MSG "osst%d:D: first data frame on tape = %d, last = %d, eod frame = %d\n", dev,
                          STp->first_data_ppos,
                          ntohl(header->partition[0].last_frame_ppos),
                          ntohl(header->partition[0].eod_frame_ppos));
-       printk(OSST_DEB_MSG "osst%i: first mark on tape = %d, last = %d, eod frame = %d\n", 
+       printk(OSST_DEB_MSG "osst%d:D: first mark on tape = %d, last = %d, eod frame = %d\n", 
                          dev, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
 #endif
                if (header->minor_rev < 4 && STp->linux_media_version == 4) {
-                       printk(OSST_DEB_MSG "osst%i: Moving filemark list to ADR 1.4 location\n", dev);
+#if DEBUG
+                       printk(OSST_DEB_MSG "osst%i:D: Moving filemark list to ADR 1.4 location\n", dev);
+#endif
                        memcpy((void *)header->dat_fm_tab.fm_tab_ent, 
                               (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
                        memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
@@ -2034,9 +2234,8 @@ static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int b
                     header->dat_fm_tab.fm_tab_ent_sz                != 4                          ||
                     header->dat_fm_tab.fm_tab_ent_cnt               !=
                             htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
-                       printk(KERN_WARNING "osst%i: Failed consistency check ADR 1.4 format\n", dev);
+                       printk(KERN_WARNING "osst%i:W: Failed consistency check ADR 1.4 format\n", dev);
 
-//             memcpy(STp->header_cache, header, sizeof(os_header_t));
        }
 
        return 1;
@@ -2044,7 +2243,7 @@ static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int b
 
 static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
 {
-       int position, block;
+       int position, ppos;
        int first, last;
        int valid = 0;
        int dev = TAPE_NR(STp->devt);
@@ -2059,37 +2258,37 @@ static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
        STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
        STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
        STp->eod_frame_ppos = STp->first_data_ppos = -1;
-       STp->first_mark_ppos = STp->last_mark_ppos = -1;
+       STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%i: Reading header\n", dev);
+       printk(OSST_DEB_MSG "osst%d:D: Reading header\n", dev);
 #endif
 
-       /* optimization for speed - if we are positioned at block 10, read second group first */        
+       /* optimization for speed - if we are positioned at ppos 10, read second group first  */        
        /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
 
        first = position==10?0xbae: 5;
        last  = position==10?0xbb3:10;
 
-       for (block = first; block < last; block++)
-               if (__osst_analyze_headers(STp, aSCpnt, block))
+       for (ppos = first; ppos < last; ppos++)
+               if (__osst_analyze_headers(STp, aSCpnt, ppos))
                        valid = 1;
 
        first = position==10? 5:0xbae;
        last  = position==10?10:0xbb3;
 
-       for (block = first; block < last; block++)
-               if (__osst_analyze_headers(STp, aSCpnt, block))
+       for (ppos = first; ppos < last; ppos++)
+               if (__osst_analyze_headers(STp, aSCpnt, ppos))
                        valid = 1;
 
        if (!valid) {
-               printk(KERN_ERR "osst%i: Failed to find valid ADRL header, new media?\n", dev);
+               printk(KERN_ERR "osst%i:E: Failed to find valid ADRL header, new media?\n", dev);
                STp->eod_frame_ppos = STp->first_data_ppos = 0;
                osst_set_frame_position(STp, aSCpnt, 10, 0);
                return 0;
        }
        if (position <= STp->first_data_ppos) {
                position = STp->first_data_ppos;
-               STp->ps[0].drv_file = STp->ps[0].drv_block = STp->logical_blk_num = 0;
+               STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
        }
        osst_set_frame_position(STp, aSCpnt, position, 0);
        STp->header_ok = 1;
@@ -2100,18 +2299,21 @@ static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
 static int osst_verify_position(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
 {
        int frame_position  = STp->first_frame_position;
+       int frame_seq_numbr = STp->frame_seq_number;
        int logical_blk_num = STp->logical_blk_num;
+               int halfway_frame   = STp->frame_in_buffer;
+       int read_pointer    = STp->buffer->read_pointer;
        int prev_mark_ppos  = -1;
        int actual_mark_ppos, i, n;
-#if 1 //DEBUG
+#if DEBUG
        int dev = TAPE_NR(STp->devt);
 
-       printk(OSST_DEB_MSG "osst%i: Verify that the tape is really the one we think before writing\n", dev);
+       printk(OSST_DEB_MSG "osst%d:D: Verify that the tape is really the one we think before writing\n", dev);
 #endif
        osst_set_frame_position(STp, aSCpnt, frame_position - 1, 0);
-       if (osst_get_logical_blk(STp, aSCpnt, -1, 0) < 0) {
+       if (osst_get_logical_frame(STp, aSCpnt, -1, 0) < 0) {
 #if DEBUG
-               printk(OSST_DEB_MSG "osst%i: Couldn't get logical blk num in verify_position\n", dev);
+               printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in verify_position\n", dev);
 #endif
                return (-EIO);
        }
@@ -2123,42 +2325,48 @@ static int osst_verify_position(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt)
                prev_mark_ppos = frame_position - 1;  /* usually - we don't really know */
        actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
                                frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
-       if (frame_position  != STp->first_frame_position ||
-           logical_blk_num != STp->logical_blk_num + 1  ||
-           prev_mark_ppos  != actual_mark_ppos           ) {
-#if 1 //DEBUG
-               printk(OSST_DEB_MSG "osst%i: Block mismatch: frame %d-%d, lblk %d-%d, mark %d-%d\n", dev,
-                                 STp->first_frame_position, frame_position, STp->logical_blk_num + 1,
-                                 logical_blk_num, actual_mark_ppos, prev_mark_ppos);
+       if (frame_position  != STp->first_frame_position                   ||
+           frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
+           prev_mark_ppos  != actual_mark_ppos                            ) {
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", dev,
+                                 STp->first_frame_position, frame_position, 
+                                 STp->frame_seq_number + (halfway_frame?0:1),
+                                 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
 #endif
                return (-EIO);
        }
-       STp->logical_blk_in_buffer = 0;
-       STp->logical_blk_num = logical_blk_num;
+       if (halfway_frame) {
+               /* prepare buffer for append and rewrite on top of original */
+               osst_set_frame_position(STp, aSCpnt, frame_position - 1, 0);
+               STp->buffer->buffer_bytes  = read_pointer;
+               STp->ps[STp->partition].rw = ST_WRITING;
+               STp->dirty                 = 1;
+       }
+       STp->frame_in_buffer  = halfway_frame;
+       STp->frame_seq_number = frame_seq_numbr;
+       STp->logical_blk_num  = logical_blk_num;
        return 0;
 }
 
 /* Acc. to OnStream, the vers. numbering is the following:
  * X.XX for released versions (X=digit), 
  * XXXY for unreleased versions (Y=letter)
- * Ordering 1.05 < 106A < 106a < 106B < ... < 1.06
+ * Ordering 1.05 < 106A < 106B < ...  < 106a < ... < 1.06
  * This fn makes monoton numbers out of this scheme ...
  */
 static unsigned int osst_parse_firmware_rev (const char * str)
 {
-       unsigned int rev;
        if (str[1] == '.') {
-               rev = (str[0]-0x30)*10000
-                       +(str[2]-0x30)*1000
-                       +(str[3]-0x30)*100;
+               return (str[0]-'0')*10000
+                       +(str[2]-'0')*1000
+                       +(str[3]-'0')*100;
        } else {
-               rev = (str[0]-0x30)*10000
-                       +(str[1]-0x30)*1000
-                       +(str[2]-0x30)*100 - 100;
-               rev += 2*(str[3] & 0x1f)
-                       +(str[3] >= 0x60? 1: 0);
+               return (str[0]-'0')*10000
+                       +(str[1]-'0')*1000
+                       +(str[2]-'0')*100 - 100
+                       +(str[3]-'@');
        }
-       return rev;
 }
 
 /*
@@ -2166,9 +2374,9 @@ static unsigned int osst_parse_firmware_rev (const char * str)
  */
 static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
 {
-       int                            dev   = TAPE_NR(STp->devt);
        unsigned char                  cmd[MAX_COMMAND_SIZE];
-        Scsi_Cmnd                    * SCpnt = * aSCpnt;
+       int                            dev   = TAPE_NR(STp->devt);
+       Scsi_Cmnd                    * SCpnt = * aSCpnt;
         osst_mode_parameter_header_t * header;
         osst_block_size_page_t       * bs;
        osst_capabilities_page_t     * cp;
@@ -2177,21 +2385,19 @@ static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
 
        if (STp->ready != ST_READY) {
 #if DEBUG
-           printk(OSST_DEB_MSG "osst%i: Not Ready\n", dev);
+           printk(OSST_DEB_MSG "osst%d:D: Not Ready\n", dev);
 #endif
            return (-EIO);
        }
        
        if (STp->os_fw_rev < 10600) {
-            printk("osst%i: Old OnStream firmware revision detected (%s)\n", 
-                       dev, STp->device->rev);
-            printk("osst%i: An upgrade to version 1.06 or above is recommended\n",
-                       dev);
+           printk(KERN_INFO "osst%i:I: Old OnStream firmware revision detected (%s),\n", dev, STp->device->rev);
+           printk(KERN_INFO "osst%d:I: an upgrade to version 1.06 or above is recommended\n", dev);
         }
 
         /*
          * Configure 32.5KB (data+aux) frame size.
-         * Get the current block size from the block size mode page
+         * Get the current frame size from the block size mode page
          */
        memset(cmd, 0, MAX_COMMAND_SIZE);
        cmd[0] = MODE_SENSE;
@@ -2202,13 +2408,13 @@ static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
        SCpnt = osst_do_scsi(SCpnt, STp, cmd, cmd[4], STp->timeout, 0, TRUE);
        if (SCpnt == NULL) {
 #if DEBUG
-           printk(OSST_DEB_MSG "osst: Busy\n");
+           printk(OSST_DEB_MSG "osst :D: Busy\n");
 #endif
            return (-EBUSY);
        }
        *aSCpnt = SCpnt;
        if ((STp->buffer)->last_result_fatal != 0) {
-           printk (KERN_ERR "osst%i: Can't get tape block size mode page\n", dev);
+           printk (KERN_ERR "osst%d:E: Can't get tape block size mode page\n", dev);
            return (-EIO);
        }
 
@@ -2216,10 +2422,10 @@ static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
         bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
 
 #if DEBUG
-        printk(KERN_INFO "osst%i: 32KB play back: %s\n",   dev, bs->play32     ? "Yes" : "No");
-        printk(KERN_INFO "osst%i: 32.5KB play back: %s\n", dev, bs->play32_5   ? "Yes" : "No");
-        printk(KERN_INFO "osst%i: 32KB record: %s\n",      dev, bs->record32   ? "Yes" : "No");
-        printk(KERN_INFO "osst%i: 32.5KB record: %s\n",    dev, bs->record32_5 ? "Yes" : "No");
+       printk(OSST_DEB_MSG "osst%d:D: 32KB play back: %s\n",   dev, bs->play32     ? "Yes" : "No");
+       printk(OSST_DEB_MSG "osst%d:D: 32.5KB play back: %s\n", dev, bs->play32_5   ? "Yes" : "No");
+       printk(OSST_DEB_MSG "osst%d:D: 32KB record: %s\n",      dev, bs->record32   ? "Yes" : "No");
+       printk(OSST_DEB_MSG "osst%d:D: 32.5KB record: %s\n",    dev, bs->record32_5 ? "Yes" : "No");
 #endif
 
         /*
@@ -2239,16 +2445,12 @@ static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
        SCpnt = osst_do_scsi(SCpnt, STp, cmd, cmd[4], STp->timeout, 0, TRUE);
        *aSCpnt = SCpnt;
         if ((STp->buffer)->last_result_fatal != 0) {
-            printk (KERN_ERR "osst%i: Couldn't set tape block size mode page\n", dev);
+            printk (KERN_ERR "osst%d:E: Couldn't set tape block size mode page\n", dev);
            return (-EIO);
        }
 
-       STp->block_size = (STp->raw) ? OS_FRAME_SIZE : OS_DATA_SIZE;
-       STp->min_block  = OS_FRAME_SIZE; /* FIXME */
-       STp->max_block  = STp->block_size;
-
 #if DEBUG
-        printk(KERN_INFO "osst%i: Block Size changed to 32.5K\n", dev);
+        printk(KERN_INFO "osst%d:D: Block Size changed to 32.5K\n", dev);
          /*
          * In debug mode, we want to see as many errors as possible
          * to test the error recovery mechanism.
@@ -2284,7 +2486,7 @@ static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
        *aSCpnt = SCpnt;
 
         if ((STp->buffer)->last_result_fatal != 0) {
-            printk (KERN_ERR "osst%i: Couldn't set vendor name to %s\n", dev, 
+            printk (KERN_ERR "osst%d:E: Couldn't set vendor name to %s\n", dev, 
                        (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
            return (-EIO);
        }
@@ -2299,7 +2501,7 @@ static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
        *aSCpnt = SCpnt;
 
        if ((STp->buffer)->last_result_fatal != 0) {
-           printk (KERN_ERR "osst%i: can't get capabilities page\n", dev);
+           printk (KERN_ERR "osst%d:E: Can't get capabilities page\n", dev);
            return (-EIO);
        }
 
@@ -2319,7 +2521,7 @@ static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
        *aSCpnt = SCpnt;
 
        if ((STp->buffer)->last_result_fatal != 0) {
-           printk (KERN_ERR "osst%i: can't get tape parameter page\n", dev);
+           printk (KERN_ERR "osst%d:E: Can't get tape parameter page\n", dev);
            return (-EIO);
        }
 
@@ -2330,7 +2532,7 @@ static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
        STp->density  = prm->density;
        STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%d: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
+       printk(OSST_DEB_MSG "osst%d:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
                          dev, STp->density, STp->capacity / 32, drive_buffer_size);
 #endif
 
@@ -2348,7 +2550,7 @@ static int cross_eof(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int forward)
 
 #if DEBUG
        if (debugging)
-               printk(OSST_DEB_MSG "osst%d: Stepping over filemark %s.\n",
+          printk(OSST_DEB_MSG "osst%d:D: Stepping over filemark %s.\n",
                                  dev, forward ? "forward" : "backward");
 #endif
 
@@ -2361,7 +2563,7 @@ static int cross_eof(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int forward)
           result = osst_seek_logical_blk(STp, aSCpnt, STp->logical_blk_num - 1);
 
        if (result < 0)
-          printk(KERN_ERR "osst%d: Stepping over filemark %s failed.\n",
+          printk(KERN_WARNING "osst%d:W: Stepping over filemark %s failed.\n",
                                dev, forward ? "forward" : "backward");
 
        return result;
@@ -2401,7 +2603,7 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
       result = ((SCpnt->sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL;
 
     if (result == -EINVAL)
-      printk(KERN_ERR "osst%d: Can't read tape position.\n", dev);
+      printk(KERN_ERR "osst%d:E: Can't read tape position.\n", dev);
     else {
 
       if (result == -EIO) {    /* re-read position */
@@ -2425,7 +2627,7 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
       STp->cur_frames           =  (STp->buffer)->b_data[15];
 #if DEBUG
       if (debugging) {
-       printk(OSST_DEB_MSG "osst%d: Drive Positions: host %d, tape %d%s, buffer %d\n", dev,
+         printk(OSST_DEB_MSG "osst%d:D: Drive Positions: host %d, tape %d%s, buffer %d\n", dev,
                           STp->first_frame_position, STp->last_frame_position,
                           ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
                           ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
@@ -2434,7 +2636,7 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
 #endif
       if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
 #if DEBUG
-         printk(KERN_WARNING "osst%d: Correcting read position %d, %d, %d\n", dev,
+         printk(KERN_WARNING "osst%d:D: Correcting read position %d, %d, %d\n", dev,
                                STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
 #endif
          STp->first_frame_position = STp->last_frame_position;
@@ -2446,60 +2648,66 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
 }
 
 
-/* Set the tape block */
-static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int block, int skip)
+/* Set the physical tape position */
+static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int ppos, int skip)
 {
-    ST_partstat *STps;
-    int result = 0;
-    int timeout;
+    ST_partstat * STps;
+    int result  = 0;
+    int pp      = (ppos == 3000 && !skip) ? 0 : ppos;
     unsigned char scmd[MAX_COMMAND_SIZE];
     Scsi_Cmnd   * SCpnt;
-    int dev = TAPE_NR(STp->devt);
+    int dev     = TAPE_NR(STp->devt);
 
     if (STp->ready != ST_READY)
       return (-EIO);
-    timeout = STp->long_timeout;
     STps = &(STp->ps[STp->partition]);
 
-    if (block < 0 || block > STp->capacity) {
-      printk(KERN_ERR "osst%d: Reposition request %d out of range\n", dev, block);
-      block = block < 0 ? 0 : (STp->capacity - 1);
+    if (ppos < 0 || ppos > STp->capacity) {
+      printk(KERN_WARNING "osst%d:W: Reposition request %d out of range\n", dev, ppos);
+      pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
       result = (-EINVAL);
     }
+
+    do {
 #if DEBUG
-    if (debugging)
-      printk(OSST_DEB_MSG "osst%d: Setting block to %d.\n", dev, block);
+      if (debugging)
+       printk(OSST_DEB_MSG "osst%d:D: Setting physical position to %d.\n", dev, pp);
 #endif
-    memset (scmd, 0, MAX_COMMAND_SIZE);
-    scmd[0] = SEEK_10;
-    scmd[1] = 1;
-    scmd[3] = (block >> 24);
-    scmd[4] = (block >> 16);
-    scmd[5] = (block >> 8);
-    scmd[6] = block;
-    if (skip)
-      scmd[9] = 0x80;
-
-    SCpnt = osst_do_scsi(*aSCpnt, STp, scmd, 20, timeout, MAX_READY_RETRIES, TRUE);
-    if (!SCpnt) {
+      memset (scmd, 0, MAX_COMMAND_SIZE);
+      scmd[0] = SEEK_10;
+      scmd[1] = 1;
+      scmd[3] = (pp >> 24);
+      scmd[4] = (pp >> 16);
+      scmd[5] = (pp >> 8);
+      scmd[6] =  pp;
+      if (skip)
+       scmd[9] = 0x80;
+
+      SCpnt = osst_do_scsi(*aSCpnt, STp, scmd, 20, STp->long_timeout, MAX_READY_RETRIES, TRUE);
+      if (!SCpnt) {
 #if DEBUG
-      printk(OSST_DEB_MSG "osst%d: Busy\n", dev);
+       printk(OSST_DEB_MSG "osst%d:D: Busy\n", dev);
 #endif
-      return (-EBUSY);
-    }
-    *aSCpnt  = SCpnt;
+       return (-EBUSY);
+      }
+      *aSCpnt  = SCpnt;
 
-    STp->first_frame_position = STp->last_frame_position = block;
-    STps->eof = ST_NOEOF;
-    if ((STp->buffer)->last_result_fatal != 0) {
+      if ((STp->buffer)->last_result_fatal != 0) {
 #if DEBUG
-      printk(OSST_DEB_MSG "osst%d: SEEK command failed.\n", dev);
+       printk(OSST_DEB_MSG "osst%d:D: SEEK command from %d to %d failed.\n",
+                       dev, STp->first_frame_position, pp);
 #endif
-      result = (-EIO);
-    }
+       result = (-EIO);
+      }
+      if (pp != ppos)
+       osst_wait_ready(STp, aSCpnt, 5 * 60);
+    } while ((pp != ppos) && (pp = ppos));
+
+    STp->first_frame_position = STp->last_frame_position = ppos;
+    STps->eof = ST_NOEOF;
     STps->at_sm = 0;
     STps->rw = ST_IDLE;
-    STp->logical_blk_in_buffer = 0;
+    STp->frame_in_buffer = 0;
     return result;
 }
 
@@ -2508,7 +2716,7 @@ static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int b
 /* osst versions of st functions - augmented and stripped to suit OnStream only */
 
 /* Flush the write buffer (never need to write if variable blocksize). */
-static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int file_blk)
+static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt)
 {
   int offset, transfer, blks = 0;
   int result = 0;
@@ -2521,19 +2729,19 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int f
     if (SCpnt == (STp->buffer)->last_SCpnt)
 #if DEBUG
     { printk(OSST_DEB_MSG
-        "osst%d: aSCpnt points to Scsi_Cmnd that write_behind_check will release -- cleared\n", dev);
+        "osst%d:D: aSCpnt points to Scsi_Cmnd that write_behind_check will release -- cleared\n", dev);
 #endif
       *aSCpnt = SCpnt = NULL;
 #if DEBUG
     } else if (SCpnt)
       printk(OSST_DEB_MSG
-        "osst%d: aSCpnt does not point to Scsi_Cmnd that write_behind_check will release -- strange\n", dev);
+        "osst%d:D: aSCpnt does not point to Scsi_Cmnd that write_behind_check will release -- strange\n", dev);
 #endif 
     osst_write_behind_check(STp);
     if ((STp->buffer)->last_result_fatal) {
 #if DEBUG
       if (debugging)
-       printk(OSST_DEB_MSG "osst%d: Async write error (flush) %x.\n",
+       printk(OSST_DEB_MSG "osst%d:D: Async write error (flush) %x.\n",
               dev, (STp->buffer)->last_result);
 #endif
       if ((STp->buffer)->last_result == INT_MAX)
@@ -2545,15 +2753,13 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int f
   result = 0;
   if (STp->dirty == 1) {
 
+    STp->write_count++;
+    STps     = &(STp->ps[STp->partition]);
+    STps->rw = ST_WRITING;
     offset   = STp->buffer->buffer_bytes;
+    blks     = (offset + STp->block_size - 1) / STp->block_size;
     transfer = OS_FRAME_SIZE;
-    blks     = 1;
     
-#if DEBUG
-    if (debugging)
-      printk(OSST_DEB_MSG "osst%d: Flushing %d bytes, Tranfering %d bytes in %d blocks.\n",
-                        dev, offset, transfer, blks);
-#endif
     if (offset < OS_DATA_SIZE)
       osst_zero_buffer_tail(STp->buffer);
 
@@ -2564,17 +2770,48 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int f
     memset(cmd, 0, MAX_COMMAND_SIZE);
     cmd[0] = WRITE_6;
     cmd[1] = 1;
-    cmd[4] = blks;
+    cmd[4] = 1;
+
+    switch (STp->write_type) {
+      case OS_WRITE_DATA:
+#if DEBUG
+          if (debugging)
+              printk(OSST_DEB_MSG "osst%d:D: Writing %d blocks to frame %d, lblks %d-%d\n",
+                                  dev, blks, STp->frame_seq_number,
+                                  STp->logical_blk_num - blks, STp->logical_blk_num - 1);
+#endif
+          osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
+                        STp->logical_blk_num - blks, STp->block_size, blks);
+          break;
+      case OS_WRITE_EOD:
+          osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++, STp->logical_blk_num, 0, 0);
+          break;
+      case OS_WRITE_NEW_MARK:
+          osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++, STp->logical_blk_num++,
+                          0, blks=1);
+          break;
+      case OS_WRITE_HEADER:
+          osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
+          break;
+      default: /* probably FILLER */
+          osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
+    }
+#if DEBUG
+    if (debugging)
+       printk(OSST_DEB_MSG "osst%d:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
+                                                dev, offset, transfer, blks);
+#endif
 
     SCpnt = osst_do_scsi(*aSCpnt, STp, cmd, transfer, STp->timeout, MAX_WRITE_RETRIES, TRUE);
     *aSCpnt = SCpnt;
     if (!SCpnt)
       return (-EBUSY);
 
-    STps = &(STp->ps[STp->partition]);
     if ((STp->buffer)->last_result_fatal != 0) {
-       printk(OSST_DEB_MSG "osst%d: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n", TAPE_NR(STp->devt),
+#if DEBUG
+      printk(OSST_DEB_MSG "osst%d:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n", TAPE_NR(STp->devt),
                SCpnt->sense_buffer[0], SCpnt->sense_buffer[2], SCpnt->sense_buffer[12], SCpnt->sense_buffer[13]);
+#endif
       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
          (SCpnt->sense_buffer[2] & 0x40) &&                    /* FIXME - SC-30 drive doesn't assert EOM bit */
          (SCpnt->sense_buffer[2] & 0x0f) == NO_SENSE) {
@@ -2584,7 +2821,7 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int f
       }
       else {
        if (osst_write_error_recovery(STp, aSCpnt, 1)) {
-         printk(KERN_ERR "osst%d: Error on flush.\n", dev);
+         printk(KERN_ERR "osst%d:E: Error on flush write.\n", dev);
          result = (-EIO);
         }
       }
@@ -2592,15 +2829,12 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int f
     }
     else {
       STp->first_frame_position++;
-      if (file_blk && STps->drv_block >= 0)
-       STps->drv_block += blks;
-      STp->first_frame_position += blks;
       STp->dirty = 0;
       (STp->buffer)->buffer_bytes = 0;
     }
   }
 #if DEBUG
-  printk(OSST_DEB_MSG "osst%d: Exit flush write buffer with code %d\n", dev, result);
+  printk(OSST_DEB_MSG "osst%d:D: Exit flush write buffer with code %d\n", dev, result);
 #endif
   return result;
 }
@@ -2610,15 +2844,12 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Cmnd ** aSCpnt, int f
    seek_next is true. */
 static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int seek_next)
 {
-  int backspace, result;
-  OSST_buffer    * STbuffer;
+  int backspace = 0, result = 0;
   ST_partstat  * STps;
 #if DEBUG
   int dev = TAPE_NR(STp->devt);
 #endif
 
-  STbuffer = STp->buffer;
-
   /*
    * If there was a bus reset, block further access
    * to this device.
@@ -2631,21 +2862,25 @@ static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int seek_n
 
   STps = &(STp->ps[STp->partition]);
   if (STps->rw == ST_WRITING)  /* Writing */
-    return osst_flush_write_buffer(STp, aSCpnt, 1);
+    return osst_flush_write_buffer(STp, aSCpnt);
 
   if (STp->block_size == 0)
     return 0;
 
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%i: Reached flush (read) buffer\n", dev);
+  printk(OSST_DEB_MSG "osst%d:D: Reached flush (read) buffer\n", dev);
 #endif
-  backspace = ((STp->buffer)->buffer_bytes +
-    (STp->buffer)->read_pointer) / STp->block_size -
-      ((STp->buffer)->read_pointer + STp->block_size - 1) /
-       STp->block_size;
-  (STp->buffer)->buffer_bytes = 0;
-  (STp->buffer)->read_pointer = 0;
-  result = 0;
+
+  if (!STp->can_bsr) {
+    backspace = ((STp->buffer)->buffer_bytes +
+                (STp->buffer)->read_pointer) / STp->block_size -
+                     ((STp->buffer)->read_pointer + STp->block_size - 1) /
+                 STp->block_size;                                      /* FIXME is this relevant w. OSST? */
+    STp->buffer->buffer_bytes = 0;
+    STp->buffer->read_pointer = 0;
+    STp->frame_in_buffer = 0;
+  }
+
   if (!seek_next) {
     if (STps->eof == ST_FM_HIT) {
       result = cross_eof(STp, aSCpnt, FALSE); /* Back over the EOF hit */
@@ -2671,6 +2906,87 @@ static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int seek_n
 
 }
 
+static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, int synchronous)
+{
+       unsigned char   cmd[MAX_COMMAND_SIZE];
+       Scsi_Cmnd     * SCpnt;
+       int             blks;
+#if DEBUG
+       int             dev = TAPE_NR(STp->devt);
+#endif
+
+       if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
+#if DEBUG
+               printk(OSST_DEB_MSG "osst%d:D: Reaching config partition.\n", dev);
+#endif
+               if (osst_flush_drive_buffer(STp, aSCpnt) < 0) {
+                       return (-EIO);
+               }
+               /* error recovery may have bumped us past the header partition */
+               if (osst_get_frame_position(STp, aSCpnt) < 0xbb8) {
+#if DEBUG
+                       printk(OSST_DEB_MSG "osst%d:D: Skipping over config partition.\n", dev);
+#endif
+                       osst_position_tape_and_confirm(STp, aSCpnt, 0xbb8);
+               }
+       }
+
+       if (STp->poll)
+               osst_wait_frame (STp, aSCpnt, STp->first_frame_position, -50, 60);
+       /* TODO: Check for an error ! */
+
+//     osst_build_stats(STp, &SCpnt);
+
+       STp->ps[STp->partition].rw = ST_WRITING;
+       STp->write_type            = OS_WRITE_DATA;
+                       
+       memset(cmd, 0, MAX_COMMAND_SIZE);
+       cmd[0]   = WRITE_6;
+       cmd[1]   = 1;
+       cmd[4]   = 1;                                           /* one frame at a time... */
+       blks     = STp->buffer->buffer_bytes / STp->block_size;
+#if DEBUG
+       if (debugging)
+               printk(OSST_DEB_MSG "osst%d:D: Writing %d blocks to frame %d, lblks %d-%d\n", dev, blks, 
+                       STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
+#endif
+       osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
+                     STp->logical_blk_num - blks, STp->block_size, blks);
+
+#if DEBUG
+       if (!synchronous)
+               STp->write_pending = 1;
+#endif
+       SCpnt = osst_do_scsi(*aSCpnt, STp, cmd, OS_FRAME_SIZE, STp->timeout, MAX_WRITE_RETRIES, synchronous);
+       if (!SCpnt)
+               return (-EBUSY);
+       *aSCpnt = SCpnt;
+
+       if (synchronous) {
+               if (STp->buffer->last_result_fatal != 0) {
+#if DEBUG
+                       if (debugging)
+                               printk(OSST_DEB_MSG "osst%d:D: Error on write:\n", dev);
+#endif
+                       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
+                           (SCpnt->sense_buffer[2] & 0x40)) {
+                               if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW)
+                                       return (-ENOSPC);
+                       }
+                       else {
+                               if (osst_write_error_recovery(STp, aSCpnt, 1))
+                                       return (-EIO);
+                       }
+               }
+               else
+                       STp->first_frame_position++;
+       }
+
+       STp->write_count++;
+
+       return 0;
+}
+
 \f
 /* Entry points to osst */
 
@@ -2682,7 +2998,6 @@ static ssize_t osst_write(struct file * filp, const char * buf, size_t count, lo
     ssize_t i, do_count, blks, retval, transfer;
     int write_threshold;
     int doing_write = 0;
-    unsigned char cmd[MAX_COMMAND_SIZE];
     const char *b_point;
     Scsi_Cmnd * SCpnt = NULL;
     OS_Scsi_Tape * STp;
@@ -2728,7 +3043,7 @@ static ssize_t osst_write(struct file * filp, const char * buf, size_t count, lo
 
 #if DEBUG
     if (!STp->in_use) {
-      printk(OSST_DEB_MSG "osst%d: Incorrect device.\n", dev);
+      printk(OSST_DEB_MSG "osst%d:D: Incorrect device.\n", dev);
       return (-EIO);
     }
 #endif
@@ -2738,13 +3053,13 @@ static ssize_t osst_write(struct file * filp, const char * buf, size_t count, lo
 
     /* Write must be integral number of blocks */
     if (STp->block_size != 0 && (count % STp->block_size) != 0) {
-       printk(KERN_WARNING "osst%d: Write (%d bytes) not multiple of tape block size (32k).\n",
-              dev, count);
+       printk(KERN_ERR "osst%d:E: Write (%d bytes) not multiple of tape block size (%d%c).\n", dev, count,
+                   STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
        return (-EIO);
     }
 
-    if (STp->first_frame_position >= STp->capacity - 164) {
-       printk(KERN_WARNING "osst%d: Write truncated at EOM early warning (frame %d).\n",
+    if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
+       printk(KERN_ERR "osst%d:E: Write truncated at EOM early warning (frame %d).\n",
               dev, STp->first_frame_position);
        return (-ENOSPC);
     }
@@ -2765,63 +3080,64 @@ static ssize_t osst_write(struct file * filp, const char * buf, size_t count, lo
     }
     else if (STps->rw != ST_WRITING) {
       /* Are we totally rewriting this tape? */
-      if (!STp->header_ok || STp->first_frame_position == STp->first_data_ppos ||
-                           (STps->drv_file == 0 && STps->drv_block == 0)) {
+      if (!STp->header_ok ||
+         (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
+         (STps->drv_file == 0 && STps->drv_block == 0)) {
        STp->wrt_pass_cntr++;
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%d: Allocating next write pass counter: %d\n",
+       printk(OSST_DEB_MSG "osst%d:D: Allocating next write pass counter: %d\n",
                                  dev, STp->wrt_pass_cntr);
 #endif
        osst_reset_header(STp, &SCpnt);
-       STps->drv_file = STps->drv_block = STp->logical_blk_num = 0;
+       STps->drv_file = STps->drv_block = 0;
       }
       /* Do we know where we'll be writing on the tape? */
       else {
        if ((STp->fast_open && osst_verify_position(STp, &SCpnt)) ||
                STps->drv_file < 0 || STps->drv_block < 0) {
-         if (STp->first_frame_position == STp->eod_frame_ppos) {
+         if (STp->first_frame_position == STp->eod_frame_ppos) {       /* at EOD */
            STps->drv_file = STp->filemark_cnt;
            STps->drv_block = 0;
          }
          else {
            /* We have no idea where the tape is positioned - give up */
 #if DEBUG
-           printk(OSST_DEB_MSG "osst%d: Cannot write at indeterminate position.\n", dev);
+           printk(OSST_DEB_MSG "osst%d:D: Cannot write at indeterminate position.\n", dev);
 #endif
            if (SCpnt) scsi_release_command(SCpnt);
            return (-EIO);
          }
        }         
-       if (STps->drv_file > 0 && STps->drv_file < STp->filemark_cnt) {
-         STp->filemark_cnt = STps->drv_file;
+       if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
+         STp->filemark_cnt   = STps->drv_file;
          STp->last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
-         printk(KERN_WARNING "osst%d: Overwriting file %d with old write pass counter %d\n",
+         STp->last_mark_lbn  = STp->logical_blk_num - STps->drv_block;
+         printk(KERN_WARNING "osst%d:W: Overwriting file %d with old write pass counter %d\n",
                      dev, STps->drv_file, STp->wrt_pass_cntr);
-         printk(KERN_WARNING "osst%d: may lead to stale data being accepted on reading back!\n",
+         printk(KERN_WARNING "osst%d:W: may lead to stale data being accepted on reading back!\n",
                      dev);
 #if DEBUG
-         printk(OSST_DEB_MSG "osst%d: resetting filemark count to %d and last mark ppos to %d\n",
-               dev, STp->filemark_cnt, STp->last_mark_ppos);
+         printk(OSST_DEB_MSG "osst%d:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
+                     dev, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
 #endif
        }
       }
       STp->fast_open = FALSE;
-//printk(OSST_DEB_MSG "osst%d: Starting write next file\n",dev);
     }
     if (!STp->header_ok) {
 #if DEBUG
-      printk(OSST_DEB_MSG "osst%d: Write cannot proceed without valid headers\n", dev);
+      printk(OSST_DEB_MSG "osst%d:D: Write cannot proceed without valid headers\n", dev);
 #endif
       if (SCpnt) scsi_release_command(SCpnt);
       return (-EIO);
     }
     if ((STp->buffer)->writing) {
-if (SCpnt) printk(KERN_ERR "osst%d: Not supposed to have SCpnt at line %d\n", dev, __LINE__);
+if (SCpnt) printk(KERN_ERR "osst%d:A: Not supposed to have SCpnt at line %d\n", dev, __LINE__);
       osst_write_behind_check(STp);
       if ((STp->buffer)->last_result_fatal) {
 #if DEBUG
        if (debugging)
-         printk(OSST_DEB_MSG "osst%d: Async write error (write) %x.\n", dev,
+         printk(OSST_DEB_MSG "osst%d:D: Async write error (write) %x.\n", dev,
                 (STp->buffer)->last_result);
 #endif
        if ((STp->buffer)->last_result == INT_MAX)
@@ -2844,10 +3160,6 @@ if (SCpnt) printk(KERN_ERR "osst%d: Not supposed to have SCpnt at line %d\n", de
        return (-EFAULT);
 
     if (!STm->do_buffer_writes) {
-#if 0
-      if (STp->block_size != 0 && (count % STp->block_size) != 0)
-       return (-EIO);   /* Write must be integral number of blocks */
-#endif
       write_threshold = 1;
     }
     else
@@ -2856,35 +3168,11 @@ if (SCpnt) printk(KERN_ERR "osst%d: Not supposed to have SCpnt at line %d\n", de
       write_threshold--;
 
     total = count;
-
-    if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) {
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%d: Skipping over config partition.\n", dev);
-#endif
-       if (osst_flush_drive_buffer(STp, &SCpnt) < 0) {
-           if (SCpnt) scsi_release_command(SCpnt);
-           return (-EIO);
-       }
-       /* error recovery may have bumped us past the header partition */
-       if (osst_get_frame_position(STp, &SCpnt) < 0xbb8)
-           osst_position_tape_and_confirm(STp, &SCpnt, 0xbb8);
-    }
-       
-    if (STp->poll)
-       retval = osst_wait_frame (STp, &SCpnt, STp->first_frame_position, -50, 60);
-    /* TODO: Check for an error ! */
-//osst_build_stats(STp, &SCpnt);       
-    memset(cmd, 0, MAX_COMMAND_SIZE);
-    cmd[0] = WRITE_6;
-    cmd[1] = 1;
-
-    STps->rw = ST_WRITING;
-    STp->write_type = OS_WRITE_DATA;
-
-#if DEBUG
-       printk(OSST_DEB_MSG "osst%d: Writing %d bytes to file %d block %d lblk %d frame %d\n",
+    if (debugging)
+      printk(OSST_DEB_MSG "osst%d:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
                          dev, count, STps->drv_file, STps->drv_block,
-                         STp->logical_blk_num, STp->first_frame_position);
+                         STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
 #endif
 
     b_point = buf;
@@ -2905,84 +3193,60 @@ if (SCpnt) printk(KERN_ERR "osst%d: Not supposed to have SCpnt at line %d\n", de
          return i;
       }
 
-      transfer = OS_FRAME_SIZE;
-      blks     = 1;
+      blks = do_count / STp->block_size;
+      STp->logical_blk_num += blks;    /* logical_blk_num is incremented as data is moved from user */
 
-      osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->logical_blk_num++ );
+      i = osst_write_frame(STp, &SCpnt, TRUE);
 
-      cmd[2] = blks >> 16;
-      cmd[3] = blks >> 8;
-      cmd[4] = blks;
-
-      SCpnt = osst_do_scsi(SCpnt, STp, cmd, transfer, STp->timeout, MAX_WRITE_RETRIES, TRUE);
-      if (!SCpnt)
-       return (-EBUSY);
-
-      if ((STp->buffer)->last_result_fatal != 0) {
-#if DEBUG
-       if (debugging)
-         printk(OSST_DEB_MSG "osst%d: Error on write:\n", dev);
-#endif
-       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
-           (SCpnt->sense_buffer[2] & 0x40)) {
-         if ((SCpnt->sense_buffer[0] & 0x80) != 0)
-           transfer = (SCpnt->sense_buffer[3] << 24) |
-                      (SCpnt->sense_buffer[4] << 16) |
-                      (SCpnt->sense_buffer[5] <<  8) | SCpnt->sense_buffer[6];
-         else
-           transfer = 0;
-         transfer *= STp->block_size;
+      if (i == (-ENOSPC)) {
+         transfer = STp->buffer->writing;              /* FIXME -- check this logic */
          if (transfer <= do_count) {
-           filp->f_pos += do_count - transfer;
-           count -= do_count - transfer;
-           if (STps->drv_block >= 0) {
-               STps->drv_block += (do_count - transfer) / STp->block_size;
-           }
-           STps->eof = ST_EOM_OK;
-           retval = (-ENOSPC); /* EOM within current request */
+             filp->f_pos += do_count - transfer;       /* some of the data made it */
+             count -= do_count - transfer;
+             if (STps->drv_block >= 0) {
+                 STps->drv_block += (do_count - transfer) / STp->block_size;
+             }
+             STps->eof = ST_EOM_OK;
+             retval = (-ENOSPC);                       /* EOM within current request */
 #if DEBUG
-           if (debugging)
-             printk(OSST_DEB_MSG "osst%d: EOM with %d bytes unwritten.\n",
-                    dev, transfer);
+             if (debugging)
+                 printk(OSST_DEB_MSG "osst%d:D: EOM with %d bytes unwritten.\n", dev, transfer);
 #endif
          }
          else {
-           STps->eof = ST_EOM_ERROR;
-           STps->drv_block = (-1);    /* Too cautious? */
-           retval = (-EIO); /* EOM for old data */
+             STps->eof = ST_EOM_ERROR;
+             STps->drv_block = (-1);                   /* Too cautious? */
+             retval = (-EIO);                          /* EOM for old data */
 #if DEBUG
-           if (debugging)
-             printk(OSST_DEB_MSG "osst%d: EOM with lost data.\n", dev);
+             if (debugging)
+                 printk(OSST_DEB_MSG "osst%d:D: EOM with lost data.\n", dev);
 #endif
          }
-       }
-       else {
-         if (osst_write_error_recovery(STp, &SCpnt, 1) == 0) goto ok;
-         STps->drv_block = (-1);    /* Too cautious? */
-         retval = (-EIO);
-       }
+      } else
+         retval = i;
 
-       scsi_release_command(SCpnt);
-       SCpnt = NULL;
-       (STp->buffer)->buffer_bytes = 0;
-       STp->dirty = 0;
-       if (count < total)
-         return total - count;
-       else
-         return retval;
-      }
-      STp->first_frame_position++;
-ok:
+      if (retval < 0) {
+         if (SCpnt != NULL) {
+             scsi_release_command(SCpnt);
+             SCpnt = NULL;
+         }
+         STp->buffer->buffer_bytes = 0;
+         STp->dirty = 0;
+         if (count < total)
+             return total - count;
+         else
+             return retval;
+      }                                                                                                                        
       filp->f_pos += do_count;
       b_point += do_count;
       count -= do_count;
       if (STps->drv_block >= 0) {
          STps->drv_block += blks;
       }
-      STp->first_frame_position += blks;
-      (STp->buffer)->buffer_bytes = 0;
+      STp->buffer->buffer_bytes = 0;
       STp->dirty = 0;
-    }
+    }  /* end while write threshold exceeded */
+
     if (count != 0) {
       STp->dirty = 1;
       i = append_to_buffer(b_point, STp->buffer, count);
@@ -2993,6 +3257,11 @@ ok:
          }
          return i;
       }
+      blks = count / STp->block_size;
+      STp->logical_blk_num += blks;
+      if (STps->drv_block >= 0) {
+         STps->drv_block += blks;
+      }
       filp->f_pos += count;
       count = 0;
     }
@@ -3004,28 +3273,15 @@ ok:
     }
 
     if (STm->do_async_writes &&
-       ((STp->buffer)->buffer_bytes >= STp->write_threshold &&
-        (STp->buffer)->buffer_bytes >= OS_DATA_SIZE)      ) { 
+       (STp->buffer->buffer_bytes >= STp->write_threshold)) {
       /* Schedule an asynchronous write */
       (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
          STp->block_size) * STp->block_size;
       STp->dirty = !((STp->buffer)->writing ==
                     (STp->buffer)->buffer_bytes);
 
-      transfer = OS_FRAME_SIZE;
-      blks     = 1;
-
-      osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->logical_blk_num++ );
-
-      cmd[2] = blks >> 16;
-      cmd[3] = blks >> 8;
-      cmd[4] = blks;
-#if DEBUG
-      STp->write_pending = 1;
-#endif
-
-      SCpnt = osst_do_scsi(SCpnt, STp, cmd, transfer, STp->timeout, MAX_WRITE_RETRIES, FALSE);
-      if (SCpnt == NULL)
+      i = osst_write_frame(STp, &SCpnt, FALSE);
+      if (i < 0)
          return (-EIO);
     }
     else if (SCpnt != NULL) {
@@ -3036,7 +3292,7 @@ ok:
     if (total > 0)
        STps->eof = ST_NOEOF;
 
-    return( total);
+    return total;
 }
 
 
@@ -3081,19 +3337,13 @@ static ssize_t osst_read(struct file * filp, char * buf, size_t count, loff_t *p
       return (-ENXIO);
 #if DEBUG
     if (!STp->in_use) {
-      printk(OSST_DEB_MSG "osst%d: Incorrect device.\n", dev);
+      printk(OSST_DEB_MSG "osst%d:D: Incorrect device.\n", dev);
       return (-EIO);
     }
 #endif
     /* Must have initialized medium */
     if (!STp->header_ok) return (-EIO);
 
-    if ((count % STp->block_size) != 0) {
-      printk(KERN_WARNING "osst%d: Use multiple of %d bytes as block size (%d requested)\n",
-                         dev, STp->block_size, count);
-      return (-EIO);   /* Read must be integral number of blocks */
-    }
-
     if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
        !osst_int_ioctl(STp, &SCpnt, MTLOCK, 0))
       STp->door_locked = ST_LOCKED_AUTO;
@@ -3108,9 +3358,14 @@ static ssize_t osst_read(struct file * filp, char * buf, size_t count, loff_t *p
       STps->rw = ST_IDLE;
     }
 
+    if ((count % STp->block_size) != 0) {
+       printk(KERN_WARNING "osst%d:W: Read (%d bytes) not multiple of tape block size (%d%c).\n", dev, count,
+                  STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
+    }
+
 #if DEBUG
     if (debugging && STps->eof != ST_NOEOF)
-      printk(OSST_DEB_MSG "osst%d: EOF/EOM flag up (%d). Bytes %d\n", dev,
+      printk(OSST_DEB_MSG "osst%d:D: EOF/EOM flag up (%d). Bytes %d\n", dev,
             STps->eof, (STp->buffer)->buffer_bytes);
 #endif
     if ((STp->buffer)->buffer_bytes == 0 &&
@@ -3134,39 +3389,49 @@ static ssize_t osst_read(struct file * filp, char * buf, size_t count, loff_t *p
     }
 
     /* Loop until enough data in buffer or a special condition found */
-    for (total = 0, special = 0; total < count && !special; ) {
+    for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
 
       /* Get new data if the buffer is empty */
       if ((STp->buffer)->buffer_bytes == 0) {
-         special = osst_get_logical_blk(STp, &SCpnt, STp->logical_blk_num, 0);
-         STp->buffer->buffer_bytes = special ? 0 : OS_DATA_SIZE; 
-         STp->buffer->read_pointer = 0;
-         STp->logical_blk_num++;               /* block to look for next time */
-         STp->logical_blk_in_buffer = 0;
+         if (STps->eof == ST_FM_HIT)
+             break;
+         special = osst_get_logical_frame(STp, &SCpnt, STp->frame_seq_number, 0);
          if (special < 0) {                    /* No need to continue read */
+             STp->frame_in_buffer = 0;
              if (SCpnt) scsi_release_command(SCpnt);
              return special;
-          }
-         STps->drv_block++;
+         }
       }
 
       /* Move the data from driver buffer to user buffer */
       if ((STp->buffer)->buffer_bytes > 0) {
 #if DEBUG
        if (debugging && STps->eof != ST_NOEOF)
-         printk(OSST_DEB_MSG "osst%d: EOF up (%d). Left %d, needed %d.\n", dev,
+           printk(OSST_DEB_MSG "osst%d:D: EOF up (%d). Left %d, needed %d.\n", dev,
                 STps->eof, (STp->buffer)->buffer_bytes, count - total);
 #endif
-       transfer = (STp->buffer)->buffer_bytes < count - total ?
-         (STp->buffer)->buffer_bytes : count - total;
+       transfer = (((STp->buffer)->buffer_bytes < count - total ?
+                    (STp->buffer)->buffer_bytes : count - total)/
+                     STp->block_size) * STp->block_size;               /* force multiple of block size */
        i = from_buffer(STp->buffer, buf, transfer);
        if (i) {
            if (SCpnt) scsi_release_command(SCpnt);
            return i;
        }
-       filp->f_pos += transfer;
-       buf += transfer;
-       total += transfer;
+       STp->logical_blk_num += transfer / STp->block_size;
+       STps->drv_block      += transfer / STp->block_size;
+       filp->f_pos          += transfer;
+       buf                  += transfer;
+       total                += transfer;
+      }
+
+      if ((STp->buffer)->buffer_bytes == 0) {
+#if DEBUG
+         if (debugging)
+             printk(OSST_DEB_MSG "osst%d:D: Finished with frame %d\n", dev, STp->frame_seq_number);
+#endif
+         STp->frame_in_buffer = 0;
+         STp->frame_seq_number++;              /* frame to look for next time */
       }
 
     } /* for (total = 0, special = 0; total < count && !special; ) */
@@ -3200,21 +3465,21 @@ static ssize_t osst_read(struct file * filp, char * buf, size_t count, loff_t *p
 static void osst_log_options(OS_Scsi_Tape *STp, ST_mode *STm, int dev)
 {
   printk(KERN_INFO
-"osst%d: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
+"osst%d:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
         dev, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
         STm->do_read_ahead);
   printk(KERN_INFO
-"osst%d:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
+"osst%d:I:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
         dev, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
   printk(KERN_INFO
-"osst%d:    defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
+"osst%d:I:    defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
         dev, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
         STp->scsi2_logical);
   printk(KERN_INFO
-"osst%d:    sysv: %d\n", dev, STm->sysv);
+"osst%d:I:    sysv: %d\n", dev, STm->sysv);
 #if DEBUG
   printk(KERN_INFO
-        "osst%d:    debugging: %d\n",
+        "osst%d:D:    debugging: %d\n",
         dev, debugging);
 #endif
 }
@@ -3233,7 +3498,7 @@ static int osst_set_options(OS_Scsi_Tape *STp, long options)
     modes_defined = TRUE;
 #if DEBUG
     if (debugging)
-      printk(OSST_DEB_MSG "osst%d: Initialized mode %d definition from mode 0\n",
+       printk(OSST_DEB_MSG "osst%d:D: Initialized mode %d definition from mode 0\n",
             dev, STp->current_mode);
 #endif
   }
@@ -3294,23 +3559,28 @@ static int osst_set_options(OS_Scsi_Tape *STp, long options)
   else if (code == MT_ST_WRITE_THRESHOLD) {
     value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
     if (value < 1 || value > osst_buffer_size) {
-      printk(KERN_WARNING "osst%d: Write threshold %d too small or too large.\n",
+      printk(KERN_WARNING "osst%d:W: Write threshold %d too small or too large.\n",
             dev, value);
       return (-EIO);
     }
     STp->write_threshold = value;
-    printk(KERN_INFO "osst%d: Write threshold set to %d bytes.\n",
+    printk(KERN_INFO "osst%d:I: Write threshold set to %d bytes.\n",
           dev, value);
   }
   else if (code == MT_ST_DEF_BLKSIZE) {
     value = (options & ~MT_ST_OPTIONS);
     if (value == ~MT_ST_OPTIONS) {
       STm->default_blksize = (-1);
-      printk(KERN_INFO "osst%d: Default block size disabled.\n", dev);
+      printk(KERN_INFO "osst%d:I: Default block size disabled.\n", dev);
     }
     else {
+      if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
+        printk(KERN_WARNING "osst%d:W: Default block size cannot be set to %d.\n",
+                            dev, value);
+         return (-EINVAL);
+      }
       STm->default_blksize = value;
-      printk(KERN_INFO "osst%d: Default block size set to %d bytes.\n",
+      printk(KERN_INFO "osst%d:I: Default block size set to %d bytes.\n",
             dev, STm->default_blksize);
     }
   }
@@ -3318,12 +3588,12 @@ static int osst_set_options(OS_Scsi_Tape *STp, long options)
     value = (options & ~MT_ST_OPTIONS);
     if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
       STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
-      printk(KERN_INFO "osst%d: Long timeout set to %d seconds.\n", dev,
+      printk(KERN_INFO "osst%d:I: Long timeout set to %d seconds.\n", dev,
             (value & ~MT_ST_SET_LONG_TIMEOUT));
     }
     else {
       STp->timeout = value * HZ;
-      printk(KERN_INFO "osst%d: Normal timeout set to %d seconds.\n", dev,
+      printk(KERN_INFO "osst%d:I: Normal timeout set to %d seconds.\n", dev,
             value);
     }
   }
@@ -3333,33 +3603,33 @@ static int osst_set_options(OS_Scsi_Tape *STp, long options)
     if (code == MT_ST_DEF_DENSITY) {
       if (value == MT_ST_CLEAR_DEFAULT) {
        STm->default_density = (-1);
-       printk(KERN_INFO "osst%d: Density default disabled.\n", dev);
+       printk(KERN_INFO "osst%d:I: Density default disabled.\n", dev);
       }
       else {
        STm->default_density = value & 0xff;
-       printk(KERN_INFO "osst%d: Density default set to %x\n",
+       printk(KERN_INFO "osst%d:I: Density default set to %x\n",
               dev, STm->default_density);
       }
     }
     else if (code == MT_ST_DEF_DRVBUFFER) {
       if (value == MT_ST_CLEAR_DEFAULT) {
        STp->default_drvbuffer = 0xff;
-       printk(KERN_INFO "osst%d: Drive buffer default disabled.\n", dev);
+       printk(KERN_INFO "osst%d:I: Drive buffer default disabled.\n", dev);
       }
       else {
        STp->default_drvbuffer = value & 7;
-       printk(KERN_INFO "osst%d: Drive buffer default set to %x\n",
+       printk(KERN_INFO "osst%d:I: Drive buffer default set to %x\n",
               dev, STp->default_drvbuffer);
       }
     }
     else if (code == MT_ST_DEF_COMPRESSION) {
       if (value == MT_ST_CLEAR_DEFAULT) {
        STm->default_compression = ST_DONT_TOUCH;
-       printk(KERN_INFO "osst%d: Compression default disabled.\n", dev);
+       printk(KERN_INFO "osst%d:I: Compression default disabled.\n", dev);
       }
       else {
        STm->default_compression = (value & 1 ? ST_YES : ST_NO);
-       printk(KERN_INFO "osst%d: Compression default set to %x\n",
+       printk(KERN_INFO "osst%d:I: Compression default set to %x\n",
               dev, (value & 1));
       }
     }
@@ -3382,7 +3652,7 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
    Scsi_Cmnd * SCpnt = *aSCpnt;
    ST_partstat * STps;
    int fileno, blkno, at_sm, datalen;
-   int logical_blk_num;
+   int frame_seq_numbr, logical_blk_num;
    int dev = TAPE_NR(STp->devt);
 
    if (STp->ready != ST_READY && cmd_in != MTLOAD) {
@@ -3396,6 +3666,7 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
    fileno = STps->drv_file;
    blkno = STps->drv_block;
    at_sm = STps->at_sm;
+   frame_seq_numbr = STp->frame_seq_number;
    logical_blk_num = STp->logical_blk_num;
 
    memset(cmd, 0, MAX_COMMAND_SIZE);
@@ -3410,7 +3681,6 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
           ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SCpnt, cmd_in, arg);
        else
           ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SCpnt, cmd_in, arg);
-       logical_blk_num = STp->logical_blk_num;
        if (fileno >= 0)
           fileno += arg;
        blkno = 0;
@@ -3423,7 +3693,6 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
        if (STp->raw)
           return (-EIO);
        ioctl_result = osst_space_over_filemarks_backward(STp, &SCpnt, cmd_in, arg);
-       logical_blk_num = STp->logical_blk_num;
        if (fileno >= 0)
           fileno -= arg;
        blkno = (-1);  /* We can't know the block number */
@@ -3434,7 +3703,7 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
      case MTBSR:
 #if DEBUG
        if (debugging)
-          printk(OSST_DEB_MSG "osst%i: Skipping %lu blocks %s from logical block %d\n",
+          printk(OSST_DEB_MSG "osst%d:D: Skipping %lu blocks %s from logical block %d\n",
                                dev, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
 #endif
        if (cmd_in == MTFSR) {
@@ -3445,8 +3714,9 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
           logical_blk_num -= arg;
           if (blkno >= 0) blkno -= arg;
        }
-       ioctl_result = osst_seek_logical_blk(STp, &SCpnt, logical_blk_num-1);
-       STp->logical_blk_in_buffer = 0;
+       ioctl_result = osst_seek_logical_blk(STp, &SCpnt, logical_blk_num);
+       fileno = STps->drv_file;
+       blkno  = STps->drv_block;
        at_sm &= (arg == 0);
        goto os_bypass;
 
@@ -3458,7 +3728,7 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
        cmd[4] = arg;
 #if DEBUG
        if (debugging)
-        printk(OSST_DEB_MSG "osst%d: Spacing tape forward %d setmarks.\n", dev,
+         printk(OSST_DEB_MSG "osst%d:D: Spacing tape forward %d setmarks.\n", dev,
                cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
 #endif
        if (arg != 0) {
@@ -3478,7 +3748,7 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
         if (cmd[2] & 0x80)
           ltmp = 0xff000000;
         ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
-        printk(OSST_DEB_MSG "osst%d: Spacing tape backward %ld setmarks.\n",
+        printk(OSST_DEB_MSG "osst%d:D: Spacing tape backward %ld setmarks.\n",
                dev, (-ltmp));
        }
 #endif
@@ -3489,12 +3759,11 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
        break;
      case MTWEOF:
        if ( STps->rw == ST_WRITING && !(STp->device)->was_reset)
-         ioctl_result = osst_flush_write_buffer(STp, &SCpnt, 1);
+         ioctl_result = osst_flush_write_buffer(STp, &SCpnt);
        else
         ioctl_result = 0;
        for (i=0; i<arg; i++)
          ioctl_result |= osst_write_filemark(STp, &SCpnt);
-       logical_blk_num = STp->logical_blk_num;
        if (fileno >= 0) fileno += arg;
        if (blkno  >= 0) blkno   = 0;
        goto os_bypass;
@@ -3514,10 +3783,10 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
 #if DEBUG
        if (debugging) {
         if (cmd_in == MTWEOF)
-          printk(OSST_DEB_MSG "osst%d: Writing %d filemarks.\n", dev,
+           printk(OSST_DEB_MSG "osst%d:D: Writing %d filemarks.\n", dev,
                  cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
         else
-          printk(OSST_DEB_MSG "osst%d: Writing %d setmarks.\n", dev,
+           printk(OSST_DEB_MSG "osst%d:D: Writing %d setmarks.\n", dev,
                  cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
        }
 #endif
@@ -3543,50 +3812,49 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
        if (debugging) {
         switch (cmd_in) {
             case MTUNLOAD:
-                printk(OSST_DEB_MSG "osst%d: Unloading tape.\n", dev);
+                printk(OSST_DEB_MSG "osst%d:D: Unloading tape.\n", dev);
                 break;
             case MTLOAD:
-                printk(OSST_DEB_MSG "osst%d: Loading tape.\n", dev);
+                printk(OSST_DEB_MSG "osst%d:D: Loading tape.\n", dev);
                 break;
             case MTRETEN:
-                printk(OSST_DEB_MSG "osst%d: Retensioning tape.\n", dev);
+                printk(OSST_DEB_MSG "osst%d:D: Retensioning tape.\n", dev);
                 break;
             case MTOFFL:
-                printk(OSST_DEB_MSG "osst%d: Ejecting tape.\n", dev);
+                printk(OSST_DEB_MSG "osst%d:D: Ejecting tape.\n", dev);
                 break;
         }
        }
 #endif
-       fileno = blkno = at_sm = logical_blk_num = 0 ;
+       fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
        break;
      case MTNOP:
 #if DEBUG
        if (debugging)
-        printk(OSST_DEB_MSG "osst%d: No op on tape.\n", dev);
+         printk(OSST_DEB_MSG "osst%d:D: No-op on tape.\n", dev);
 #endif
        return 0;  /* Should do something ? */
        break;
      case MTEOM:
 #if DEBUG
        if (debugging)
-          printk(OSST_DEB_MSG "osst%d: Spacing to end of recorded medium.\n", dev);
+          printk(OSST_DEB_MSG "osst%d:D: Spacing to end of recorded medium.\n", dev);
 #endif
        osst_set_frame_position(STp, &SCpnt, STp->eod_frame_ppos, 0);
-       if (osst_get_logical_blk(STp, &SCpnt, -1, 0) < 0) {
+       if (osst_get_logical_frame(STp, &SCpnt, -1, 0) < 0) {
           ioctl_result = -EIO;
           goto os_bypass;
        }
        if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
 #if DEBUG
-          printk(OSST_DEB_MSG "osst%d: No EOD frame found where expected.\n", dev);
+          printk(OSST_DEB_MSG "osst%d:D: No EOD frame found where expected.\n", dev);
 #endif
           ioctl_result = -EIO;
           goto os_bypass;
        }
        ioctl_result = osst_set_frame_position(STp, &SCpnt, STp->eod_frame_ppos, 0);
-       logical_blk_num = STp->logical_blk_num;
-       fileno          = STp->filemark_cnt;
-       blkno  = at_sm  = 0;
+       fileno = STp->filemark_cnt;
+       blkno  = at_sm = 0;
        goto os_bypass;
 
      case MTERASE:
@@ -3597,7 +3865,7 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
        if (i < ioctl_result) ioctl_result = i;
        i = osst_position_tape_and_confirm(STp, &SCpnt, STp->eod_frame_ppos);
        if (i < ioctl_result) ioctl_result = i;
-       fileno = blkno = at_sm = logical_blk_num = 0 ;
+       fileno = blkno = at_sm = 0 ;
        goto os_bypass;
 
      case MTREW:
@@ -3605,9 +3873,9 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
        cmd[1] = 1;
 #if DEBUG
        if (debugging)
-          printk(OSST_DEB_MSG "osst%d: Rewinding tape, Immed=%d.\n", dev, cmd[1]);
+          printk(OSST_DEB_MSG "osst%d:D: Rewinding tape, Immed=%d.\n", dev, cmd[1]);
 #endif
-       fileno = blkno = at_sm = logical_blk_num = 0 ;
+       fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
        break;
 
      case MTLOCK:
@@ -3616,8 +3884,8 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
        cmd[4] = SCSI_REMOVAL_PREVENT;
 #if DEBUG
        if (debugging)
-           printk(OSST_DEB_MSG "osst%d: Locking drive door.\n", dev);
-#endif;
+          printk(OSST_DEB_MSG "osst%d:D: Locking drive door.\n", dev);
+#endif
        break;
 
      case MTUNLOCK:
@@ -3626,8 +3894,8 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
        cmd[4] = SCSI_REMOVAL_ALLOW;
 #if DEBUG
        if (debugging)
-          printk(OSST_DEB_MSG "osst%d: Unlocking drive door.\n", dev);
-#endif;
+          printk(OSST_DEB_MSG "osst%d:D: Unlocking drive door.\n", dev);
+#endif
        break;
 
      case MTSETBLK:           /* Set block length */
@@ -3642,10 +3910,10 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
           ((arg & MT_ST_BLKSIZE_MASK) < STp->min_block ||
            (arg & MT_ST_BLKSIZE_MASK) > STp->max_block ||
            (arg & MT_ST_BLKSIZE_MASK) > osst_buffer_size)) {
-        printk(KERN_WARNING "osst%d: Illegal block size.\n", dev);
+        printk(KERN_WARNING "osst%d:W: Illegal block size.\n", dev);
         return (-EINVAL);
        }
-       return 0;  /* silently ignore if block size didn't change */
+                return 0;  /* FIXME silently ignore if block size didn't change */
 
      default:
        return (-ENOSYS);
@@ -3654,20 +3922,25 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Cmnd ** aSCpnt, unsigned int
    SCpnt = osst_do_scsi(SCpnt, STp, cmd, datalen, timeout, MAX_RETRIES, TRUE);
    if (!SCpnt) {
 #if DEBUG
-      printk(OSST_DEB_MSG "osst%d: Couldn't exec scsi cmd for IOCTL\n", dev);
+      printk(OSST_DEB_MSG "osst%d:D: Couldn't exec scsi cmd for IOCTL\n", dev);
 #endif
       return (-EBUSY);
    }
 
    ioctl_result = (STp->buffer)->last_result_fatal;
 
+   if (!ioctl_result) {  /* SCSI command successful */
+      STp->frame_seq_number = frame_seq_numbr;
+      STp->logical_blk_num  = logical_blk_num;
+   }
+
 os_bypass:
 #if DEBUG
    if (debugging)
-      printk(OSST_DEB_MSG "osst%d: IOCTL (%d) Result=%d\n", dev, cmd_in, ioctl_result);
+      printk(OSST_DEB_MSG "osst%d:D: IOCTL (%d) Result=%d\n", dev, cmd_in, ioctl_result);
 #endif
 
-   if (!ioctl_result) {  /* SCSI command successful */
+   if (!ioctl_result) {
 
       if (cmd_in == MTFSFM) {
         fileno--;
@@ -3680,7 +3953,6 @@ os_bypass:
       STps->drv_block = blkno;
       STps->drv_file = fileno;
       STps->at_sm = at_sm;
-      STp->logical_blk_num = logical_blk_num;
 
       if (cmd_in == MTLOCK)
          STp->door_locked = ST_LOCKED_EXPLICIT;
@@ -3700,7 +3972,7 @@ os_bypass:
 /*       STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;  FIXME */
         for (i=0; i < ST_NBR_PARTITIONS; i++) {
            STp->ps[i].rw = ST_IDLE;
-           STp->ps[i].last_block_valid = FALSE;
+           STp->ps[i].last_block_valid = FALSE;        /* FIXME - where else is this field maintained? */
         }
         STp->partition = 0;
       }
@@ -3769,12 +4041,12 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
       return (-ENXIO);
 
     if( !scsi_block_when_processing_errors(STp->device) ) {
-        return -ENXIO;
+      return (-ENXIO);
     }
 
     if (STp->in_use) {
 #if DEBUG
-      printk(OSST_DEB_MSG "osst%d: Device already in use.\n", dev);
+      printk(OSST_DEB_MSG "osst%d:D: Device already in use.\n", dev);
 #endif
       return (-EBUSY);
     }
@@ -3789,7 +4061,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
     if (mode != STp->current_mode) {
 #if DEBUG
       if (debugging)
-       printk(OSST_DEB_MSG "osst%d: Mode change from %d to %d.\n",
+       printk(OSST_DEB_MSG "osst%d:D: Mode change from %d to %d.\n",
               dev, STp->current_mode, mode);
 #endif
       new_session = TRUE;
@@ -3811,7 +4083,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
     if (i >= osst_nbr_buffers) {
       STp->buffer = new_tape_buffer(FALSE, need_dma_buffer);
       if (STp->buffer == NULL) {
-       printk(KERN_WARNING "osst%d: Can't allocate tape buffer.\n", dev);
+       printk(KERN_WARNING "osst%d:W: Can't allocate tape buffer.\n", dev);
        STp->in_use = 0;
        if (STp->device->host->hostt->module)
            __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
@@ -3842,7 +4114,6 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
        STps->rw = ST_IDLE;
     }
     STp->ready = ST_READY;
-    STp->recover_count = 0;
 #if DEBUG
     STp->nbr_waits = STp->nbr_finished = 0;
 #endif
@@ -3865,7 +4136,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
        (SCpnt->sense_buffer[2] & 0x0f) == NOT_READY &&
         SCpnt->sense_buffer[12]        == 4         ) {
 #if DEBUG
-      printk(OSST_DEB_MSG "osst%d: Unit not ready, cause %x\n", dev, SCpnt->sense_buffer[13]);
+      printk(OSST_DEB_MSG "osst%d:D: Unit not ready, cause %x\n", dev, SCpnt->sense_buffer[13]);
 #endif
       if (SCpnt->sense_buffer[13] == 2) {      /* initialize command required (LOAD) */
        memset (cmd, 0, MAX_COMMAND_SIZE);
@@ -3879,7 +4150,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
     if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
        (SCpnt->sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
 #if DEBUG
-      printk(OSST_DEB_MSG "osst%d: Unit wants attention\n", dev);
+      printk(OSST_DEB_MSG "osst%d:D: Unit wants attention\n", dev);
 #endif
       STp->header_ok = 0;
 
@@ -3900,7 +4171,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
        STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
       for (i=0; i < ST_NBR_PARTITIONS; i++) {
          STps = &(STp->ps[i]);
-         STps->rw = ST_IDLE;
+         STps->rw = ST_IDLE;                   /* FIXME - seems to be redundant... */
          STps->eof = ST_NOEOF;
          STps->at_sm = 0;
          STps->last_block_valid = FALSE;
@@ -3908,6 +4179,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
          STps->drv_file = 0 ;
       }
       new_session = TRUE;
+      STp->recover_count = 0;
     }
     /*
      * if we have valid headers from before, and the drive/tape seem untouched,
@@ -3930,7 +4202,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
          STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
          STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4'  ) {
 #if DEBUG
-       printk(OSST_DEB_MSG "osst%d: signature was changed to %c%c%c%c\n", dev,
+       printk(OSST_DEB_MSG "osst%d:D: Signature was changed to %c%c%c%c\n", dev,
                          STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
                          STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
                          STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
@@ -3942,17 +4214,23 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
       if (STp->header_ok && i == osst_get_frame_position(STp, &SCpnt)) {
        if (STp->door_locked == ST_UNLOCKED) {
          if (osst_int_ioctl(STp, &SCpnt, MTLOCK, 0))
-           printk(KERN_WARNING "osst%d: Can't lock drive door\n", dev);
+           printk(KERN_INFO "osst%d:I: Can't lock drive door\n", dev);
          else
            STp->door_locked = ST_LOCKED_AUTO;
        }
+       if (!STp->frame_in_buffer) {
+           STp->block_size = (STp->raw) ? OS_FRAME_SIZE : (
+                             (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
+           STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
+       }
+       STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
        STp->fast_open = TRUE;
        scsi_release_command(SCpnt);
        return 0;
       }
 #if DEBUG
       if (i != STp->first_frame_position)
-       printk(OSST_DEB_MSG "osst%d: tape position changed from %d to %d\n", dev, i, STp->first_frame_position);
+       printk(OSST_DEB_MSG "osst%d:D: Tape position changed from %d to %d\n", dev, i, STp->first_frame_position);
 #endif
       STp->header_ok = 0;
     }
@@ -3975,8 +4253,8 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
       (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
       (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
 
-#if 1 //DEBUG
-      printk(OSST_DEB_MSG "osst%i: Applying soft reset\n", dev);
+#if DEBUG
+      printk(OSST_DEB_MSG "osst%d:D: Applying soft reset\n", dev);
 #endif
       SCpnt = osst_do_scsi(SCpnt, STp, cmd, cmd[4], STp->timeout, 0, TRUE);
 
@@ -4012,7 +4290,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
     }
 
     if (osst_wait_ready(STp, &SCpnt,  3 * 60))         /* FIXME - not allowed with NOBLOCK */
-       printk(KERN_WARNING "osst%i: Device did not become Ready in open\n",dev);
+       printk(KERN_INFO "osst%i:I: Device did not become Ready in open\n",dev);
 
     if ((STp->buffer)->last_result_fatal != 0) {
       if ((STp->device)->scsi_level >= SCSI_2 &&
@@ -4041,7 +4319,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
 
     if (OS_FRAME_SIZE > (STp->buffer)->buffer_size &&
        !enlarge_buffer(STp->buffer, OS_FRAME_SIZE, STp->restr_dma)) {
-      printk(KERN_NOTICE "osst%d: Framesize %d too large for buffer.\n", dev,
+      printk(KERN_NOTICE "osst%d:A: Framesize %d too large for buffer.\n", dev,
             OS_FRAME_SIZE);
       scsi_release_command(SCpnt);
       SCpnt = NULL;
@@ -4061,22 +4339,26 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
            b_size += STp->buffer->sg[i++].length);
       STp->buffer->aux = (os_aux_t *) (STp->buffer->sg[i].address + OS_DATA_SIZE - b_size);
 #if DEBUG
-      printk(OSST_DEB_MSG "osst%d: b_data points to %p in segment 0 at %p\n", dev,
+      printk(OSST_DEB_MSG "osst%d:D: b_data points to %p in segment 0 at %p\n", dev,
                        STp->buffer->b_data, STp->buffer->sg[0].address);
-      printk(OSST_DEB_MSG "osst%d: AUX points to %p in segment %d at %p\n", dev,
+      printk(OSST_DEB_MSG "osst%d:D: AUX points to %p in segment %d at %p\n", dev,
                          STp->buffer->aux, i, STp->buffer->sg[i].address);
 #endif
     } else
       STp->buffer->aux = NULL; /* this had better never happen! */
 
-    (STp->buffer)->buffer_blocks = 1;
+    STp->block_size = (STp->raw) ? OS_FRAME_SIZE : (
+                     (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
+    STp->min_block  = 512;
+    STp->max_block  = OS_DATA_SIZE;
+    (STp->buffer)->buffer_blocks = OS_DATA_SIZE / STp->block_size;
     (STp->buffer)->buffer_bytes  =
     (STp->buffer)->read_pointer  =
-    STp->logical_blk_in_buffer   = 0;
+    STp->frame_in_buffer   = 0;
 
 #if DEBUG
     if (debugging)
-      printk(OSST_DEB_MSG "osst%d: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
+      printk(OSST_DEB_MSG "osst%d:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
             dev, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
             (STp->buffer)->buffer_blocks);
 #endif
@@ -4085,7 +4367,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
       STp->write_prot = 1;
 #if DEBUG
       if (debugging)
-       printk(OSST_DEB_MSG "osst%d: Write protected\n", dev);
+       printk(OSST_DEB_MSG "osst%d:D: Write protected\n", dev);
 #endif
       if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
        (STp->buffer)->in_use = 0;
@@ -4105,7 +4387,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
     if (new_session) {  /* Change the drive parameters for the new mode */
 #if DEBUG
       if (debugging)
-       printk(OSST_DEB_MSG "osst%d: New Session\n", dev);
+       printk(OSST_DEB_MSG "osst%d:D: New Session\n", dev);
 #endif
       STp->density_changed = STp->blksize_changed = FALSE;
       STp->compression_changed = FALSE;
@@ -4116,7 +4398,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
      */
     if (STp->door_locked == ST_UNLOCKED) {
        if (osst_int_ioctl(STp, &SCpnt, MTLOCK, 0))
-          printk(KERN_WARNING "osst%d: Can't lock drive door\n", dev);
+         printk(KERN_INFO "osst%d:I: Can't lock drive door\n", dev);
        else
          STp->door_locked = ST_LOCKED_AUTO;
     }
@@ -4152,7 +4434,7 @@ static int os_scsi_tape_flush(struct file * filp)
     STps = &(STp->ps[STp->partition]);
 
     if ( STps->rw == ST_WRITING && !(STp->device)->was_reset) {
-      result = osst_flush_write_buffer(STp, &SCpnt, 1);
+      result = osst_flush_write_buffer(STp, &SCpnt);
       if (result != 0 && result != (-ENOSPC))
          goto out;
     }
@@ -4161,9 +4443,9 @@ static int os_scsi_tape_flush(struct file * filp)
 
 #if DEBUG
       if (debugging) {
-       printk(OSST_DEB_MSG "osst%d: File length %ld bytes.\n",
+       printk(OSST_DEB_MSG "osst%d:D: File length %ld bytes.\n",
               dev, (long)(filp->f_pos));
-       printk(OSST_DEB_MSG "osst%d: Async write waits %d, finished %d.\n",
+       printk(OSST_DEB_MSG "osst%d:D: Async write waits %d, finished %d.\n",
               dev, STp->nbr_waits, STp->nbr_finished);
       }
 #endif
@@ -4184,7 +4466,7 @@ static int os_scsi_tape_flush(struct file * filp)
 
 #if DEBUG
       if (debugging)
-       printk(OSST_DEB_MSG "osst%d: Buffer flushed, %d EOF(s) written\n",
+       printk(OSST_DEB_MSG "osst%d:D: Buffer flushed, %d EOF(s) written\n",
               dev, 1+STp->two_fm);
 #endif
     }
@@ -4192,7 +4474,7 @@ static int os_scsi_tape_flush(struct file * filp)
        STps = &(STp->ps[STp->partition]);
        if (!STm->sysv || STps->rw != ST_READING) {
            if (STp->can_bsr)
-               result = osst_flush_buffer(STp, &SCpnt, 0);
+               result = osst_flush_buffer(STp, &SCpnt, 0);     /* this is the default path */
            else if (STps->eof == ST_FM_HIT) {
                result = cross_eof(STp, &SCpnt, FALSE);
                if (result) {
@@ -4218,12 +4500,24 @@ static int os_scsi_tape_flush(struct file * filp)
 out:
     if (STp->rew_at_close) {
       result2 = osst_position_tape_and_confirm(STp, &SCpnt, STp->first_data_ppos);
-      STps->drv_file = STps->drv_block = STp->logical_blk_num = 0;
-      if (result == 0)
+      STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
+      if (result == 0 && result2 < 0)
          result = result2;
     }
     if (SCpnt) scsi_release_command(SCpnt);
 
+    if (STp->recover_count) {
+       printk(KERN_INFO "osst%d:I: %d recovered errors in", dev, STp->recover_count);
+       if (STp->write_count)
+          printk(" %d frames written", STp->write_count);
+       if (STp->read_count)
+          printk(" %d frames read", STp->read_count);
+       printk("\n");
+       STp->recover_count = 0;
+    }
+    STp->write_count = 0;
+    STp->read_count  = 0;
+
     return result;
 }
 
@@ -4275,7 +4569,7 @@ static int osst_ioctl(struct inode * inode,struct file * file,
    STp = os_scsi_tapes[dev];
 #if DEBUG
    if (debugging && !STp->in_use) {
-     printk(OSST_DEB_MSG "osst%d: Incorrect device.\n", dev);
+     printk(OSST_DEB_MSG "osst%d:D: Incorrect device.\n", dev);
      return (-EIO);
    }
 #endif
@@ -4304,7 +4598,7 @@ static int osst_ioctl(struct inode * inode,struct file * file,
         return (-EFAULT);
 
      if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
-       printk(KERN_WARNING "osst%d: MTSETDRVBUFFER only allowed for root.\n", dev);
+       printk(KERN_WARNING "osst%d:W: MTSETDRVBUFFER only allowed for root.\n", dev);
        return (-EPERM);
      }
      if (!STm->defined &&
@@ -4359,7 +4653,7 @@ static int osst_ioctl(struct inode * inode,struct file * file,
        if (STp->door_locked != ST_UNLOCKED &&
           STp->door_locked != ST_LOCK_FAILS) {
         if (osst_int_ioctl(STp, &SCpnt, MTLOCK, 0)) {
-          printk(KERN_NOTICE "osst%d: Could not relock door after bus reset.\n",
+          printk(KERN_NOTICE "osst%d:I: Could not relock door after bus reset.\n",
                  dev);
           STp->door_locked = ST_UNLOCKED;
         }
@@ -4409,7 +4703,7 @@ static int osst_ioctl(struct inode * inode,struct file * file,
        return 0;
      }
      if (mtc.mt_op == MTSEEK) {
-       i = osst_seek_frame(STp, &SCpnt, mtc.mt_count);
+       i = osst_seek_sector(STp, &SCpnt, mtc.mt_count);
        if (SCpnt) scsi_release_command(SCpnt);
        if (!STp->can_partitions)
           STp->ps[0].rw = ST_IDLE;
@@ -4502,7 +4796,7 @@ static int osst_ioctl(struct inode * inode,struct file * file,
    if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
      if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos))
        return (-EINVAL);
-     blk = osst_get_frame_position(STp, &SCpnt);
+     blk = osst_get_sector(STp, &SCpnt);
      if (SCpnt) scsi_release_command(SCpnt);
      if (blk < 0)
        return blk;
@@ -4594,7 +4888,7 @@ static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma )
     }
   }
   if (!tb) {
-    printk(KERN_NOTICE "osst: Can't allocate new tape buffer (nbr %d).\n",
+    printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer (nbr %d).\n",
           osst_nbr_buffers);
     return NULL;
   }
@@ -4604,10 +4898,10 @@ static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma )
 #if DEBUG
   if (debugging) {
     printk(OSST_DEB_MSG
-    "osst: Allocated tape buffer %d (%d bytes, %d segments, dma: %d, a: %p).\n",
+       "osst :D: Allocated tape buffer %d (%d bytes, %d segments, dma: %d, a: %p).\n",
           osst_nbr_buffers, got, tb->sg_segs, need_dma, tb->b_data);
     printk(OSST_DEB_MSG
-          "osst: segment sizes: first %d, last %d bytes.\n",
+       "osst :D: segment sizes: first %d, last %d bytes.\n",
           tb->sg[0].length, tb->sg[segs-1].length);
   }
 #endif
@@ -4652,8 +4946,7 @@ static int enlarge_buffer(OSST_buffer *STbuffer, int new_size, int need_dma)
              order--;
              continue;
          }
-         printk(KERN_NOTICE "osst: Failed to enlarge buffer to %d bytes.\n",
-                new_size);
+         printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n", new_size);
 #if DEBUG
          STbuffer->buffer_size = got;
 #endif
@@ -4671,10 +4964,10 @@ static int enlarge_buffer(OSST_buffer *STbuffer, int new_size, int need_dma)
   if (debugging) {
     for (nbr=0; osst_buffers[nbr] != STbuffer && nbr < osst_nbr_buffers; nbr++);
     printk(OSST_DEB_MSG
-    "osst: Expanded tape buffer %d (%d bytes, %d->%d segments, dma: %d, a: %p).\n",
+          "osst :D: Expanded tape buffer %d (%d bytes, %d->%d segments, dma: %d, a: %p).\n",
           nbr, got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
     printk(OSST_DEB_MSG
-          "osst: segment sizes: first %d, last %d bytes.\n",
+          "osst :D: segment sizes: first %d, last %d bytes.\n",
           STbuffer->sg[0].length, STbuffer->sg[segs-1].length);
   }
 #endif
@@ -4699,7 +4992,7 @@ static void normalize_buffer(OSST_buffer *STbuffer)
   }
 #if DEBUG
   if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
-      printk(OSST_DEB_MSG "osst: Buffer at %p normalized to %d bytes (segs %d).\n",
+      printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
             STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
 #endif
   STbuffer->sg_segs = STbuffer->orig_sg_segs;
@@ -4716,7 +5009,7 @@ static int append_to_buffer(const char *ubp, OSST_buffer *st_bp, int do_count)
         i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
        offset -= st_bp->sg[i].length;
     if (i == st_bp->sg_segs) {  /* Should never happen */
-       printk(KERN_WARNING "osst: Append_to_buffer offset overflow.\n");
+       printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
        return (-EIO);
     }
     for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
@@ -4731,7 +5024,7 @@ static int append_to_buffer(const char *ubp, OSST_buffer *st_bp, int do_count)
        offset = 0;
     }
     if (do_count) {  /* Should never happen */
-       printk(KERN_WARNING "osst: Append_to_buffer overflow (left %d).\n",
+       printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
               do_count);
        return (-EIO);
     }
@@ -4749,7 +5042,7 @@ static int from_buffer(OSST_buffer *st_bp, char *ubp, int do_count)
         i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
        offset -= st_bp->sg[i].length;
     if (i == st_bp->sg_segs) {  /* Should never happen */
-       printk(KERN_WARNING "osst: From_buffer offset overflow.\n");
+       printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
        return (-EIO);
     }
     for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
@@ -4765,7 +5058,7 @@ static int from_buffer(OSST_buffer *st_bp, char *ubp, int do_count)
        offset = 0;
     }
     if (do_count) {  /* Should never happen */
-       printk(KERN_WARNING "osst: From_buffer overflow (left %d).\n",
+       printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n",
               do_count);
        return (-EIO);
     }
@@ -4782,10 +5075,10 @@ static int osst_zero_buffer_tail(OSST_buffer *st_bp)
             i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
                offset -= st_bp->sg[i].length;
        if (i == st_bp->sg_segs) {  /* Should never happen */
-               printk(KERN_WARNING "osst: Zero_buffer offset overflow.\n");
+               printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
                return (-EIO);
        }
-       for (do_count = OS_DATA_SIZE - st_bp->read_pointer;
+       for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
             i < st_bp->sg_segs && do_count > 0; i++) {
                cnt = st_bp->sg[i].length - offset < do_count ?
                      st_bp->sg[i].length - offset : do_count ;
@@ -4794,13 +5087,13 @@ static int osst_zero_buffer_tail(OSST_buffer *st_bp)
                offset = 0;
        }
        if (do_count) {  /* Should never happen */
-               printk(KERN_WARNING "osst: Zero_buffer overflow (left %d).\n", do_count);
+               printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
                return (-EIO);
        }
        return 0;
 }
 
-/* Copy a osst 32K block of memory into the buffer.
+/* Copy a osst 32K chunk of memory into the buffer.
    Returns zero (success) or negative error code.  */
 static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
 {
@@ -4814,14 +5107,14 @@ static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
                ptr      += cnt;
        }
        if (do_count || i != st_bp->sg_segs-1) {  /* Should never happen */
-               printk(KERN_WARNING "osst: Copy_to_buffer overflow (left %d at sg %d).\n",
+               printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
                                         do_count, i);
                return (-EIO);
        }
        return 0;
 }
 
-/* Copy a osst 32K block of memory from the buffer.
+/* Copy a osst 32K chunk of memory from the buffer.
    Returns zero (success) or negative error code.  */
 static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr)
 {
@@ -4835,7 +5128,7 @@ static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr)
                ptr      += cnt;
        }
        if (do_count || i != st_bp->sg_segs-1) {  /* Should never happen */
-               printk(KERN_WARNING "osst: Copy_from_buffer overflow (left %d at sg %d).\n",
+               printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
                                         do_count, i);
                return (-EIO);
        }
@@ -4847,8 +5140,8 @@ static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr)
 
 #ifndef MODULE
 /* Set the boot options. Syntax: st=xxx,yyy
-   where xxx is buffer size in 1024 byte blocks and yyy is write threshold
-   in 1024 byte blocks. */
+   where xxx is buffer size in 1024 byte chunks and yyy is write threshold
+   in 1024 byte chunks. */
 __initfunc( void osst_setup(char *str, int *ints))
 {
   if (ints[0] > 0 && ints[1] > 0)
@@ -4883,7 +5176,7 @@ static int osst_attach(Scsi_Device * SDp){
    OS_Scsi_Tape * tpnt;
    ST_mode * STm;
    ST_partstat * STps;
-   int i;
+   int i, dev;
 #ifdef CONFIG_DEVFS_FS
    int mode;
 #endif
@@ -4904,16 +5197,17 @@ static int osst_attach(Scsi_Device * SDp){
    tpnt = (OS_Scsi_Tape *)kmalloc(sizeof(OS_Scsi_Tape), GFP_ATOMIC);
    if (tpnt == NULL) {
        SDp->attached--;
-       printk(KERN_ERR "osst: Can't allocate device descriptor.\n");
+       printk(KERN_WARNING "osst :W: Can't allocate device descriptor.\n");
        return 1;
    }
    memset(tpnt, 0, sizeof(OS_Scsi_Tape));
    os_scsi_tapes[i] = tpnt;
+   dev = i;
    tpnt->capacity = 0xfffff;
 
    /* allocate a buffer for this device */
    if (!new_tape_buffer(TRUE, TRUE)) 
-       printk(KERN_ERR "osst: Unable to allocate a tape buffer.\n");
+       printk(KERN_ERR "osst :W: Unable to allocate a tape buffer.\n");
 
 #ifdef CONFIG_DEVFS_FS
    for (mode = 0; mode < ST_NBR_MODES; ++mode) {
@@ -4960,17 +5254,12 @@ static int osst_attach(Scsi_Device * SDp){
    tpnt->long_timeout = OSST_LONG_TIMEOUT;
 
    /* Recognize OnStream tapes */
-   printk ("osst%i: Tape driver with OnStream support osst %s\nosst%i: %s\n",
-              i, osst_version, i, cvsid);
    /* We don't need to test for OnStream, as this has been done in detect () */
    tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
-#if DEBUG
-   printk ("osst%i: OnStream tape drive recognized, Model %s\n", i, SDp->model);
-#endif
    tpnt->omit_blklims = 1;
 
    tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
-   tpnt->logical_blk_in_buffer = 0;
+   tpnt->frame_in_buffer = 0;
    tpnt->header_ok = 0;
    tpnt->linux_media = 0;
    tpnt->header_cache = NULL;
@@ -4984,7 +5273,7 @@ static int osst_attach(Scsi_Device * SDp){
      STm->do_buffer_writes = OSST_BUFFER_WRITES;
      STm->do_read_ahead = OSST_READ_AHEAD;
      STm->default_compression = ST_DONT_TOUCH;
-     STm->default_blksize = 32 * ST_KILOBYTE;  /* No forced size */
+     STm->default_blksize = 512;
      STm->default_density = (-1);  /* No forced density */
    }
 
@@ -5005,6 +5294,10 @@ static int osst_attach(Scsi_Device * SDp){
      tpnt->blksize_changed = FALSE;
 
    osst_template.nr_dev++;
+
+   printk(KERN_INFO "osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as osst%d\n",
+                   SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, dev);
+
    return 0;
 };
 
@@ -5016,10 +5309,7 @@ static int osst_detect(Scsi_Device * SDp)
    * layer (ide-scsi, usb-storage, ...) */
   if (!OSST_SUPPORTS(SDp)) return 0;
 
-  printk(KERN_WARNING
-        "Detected OnStream scsi tape osst%d at scsi%d, channel %d, id %d, lun %d\n",
-        osst_template.dev_noticed++,
-        SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
+  osst_template.dev_noticed++;
 
   return 1;
 }
@@ -5039,7 +5329,7 @@ static int osst_init()
 #else
     if (register_chrdev(MAJOR_NR,"osst",&osst_fops)) {
 #endif
-      printk(KERN_ERR "osst: Unable to get major %d for OnStream tapes\n",MAJOR_NR);
+      printk(KERN_ERR "osst :W: Unable to get major %d for OnStream tapes\n",MAJOR_NR);
       return 1;
     }
     osst_registered++;
@@ -5048,12 +5338,12 @@ static int osst_init()
   if (os_scsi_tapes) return 0;
   osst_template.dev_max = OSST_MAX_TAPES;
   if (osst_template.dev_max > 128 / ST_NBR_MODES)
-    printk(KERN_INFO "osst: Only %d tapes accessible.\n", 128 / ST_NBR_MODES);
+    printk(KERN_INFO "osst :I: Only %d tapes accessible.\n", 128 / ST_NBR_MODES);
   os_scsi_tapes =
     (OS_Scsi_Tape **)kmalloc(osst_template.dev_max * sizeof(OS_Scsi_Tape *),
                                   GFP_ATOMIC);
   if (os_scsi_tapes == NULL) {
-    printk(KERN_ERR "osst: Unable to allocate array for OnStream SCSI tapes.\n");
+    printk(KERN_ERR "osst :W: Unable to allocate array for OnStream SCSI tapes.\n");
 #ifdef CONFIG_DEVFS_FS
     devfs_unregister_chrdev(MAJOR_NR, "osst");
 #else
@@ -5069,7 +5359,7 @@ static int osst_init()
     (OSST_buffer **)kmalloc(osst_template.dev_max * sizeof(OSST_buffer *),
                                    GFP_ATOMIC);
   if (osst_buffers == NULL) {
-    printk(KERN_ERR "osst: Unable to allocate tape buffer pointers.\n");
+    printk(KERN_ERR "osst :W: Unable to allocate tape buffer pointers.\n");
 #ifdef CONFIG_DEVFS_FS
     devfs_unregister_chrdev(MAJOR_NR, "osst");
 #else
@@ -5080,8 +5370,10 @@ static int osst_init()
   }
   osst_nbr_buffers = 0;
 
+  printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
+
 #if DEBUG
-  printk(OSST_DEB_MSG "osst: Buffer size %d bytes, write threshold %d bytes.\n",
+  printk(OSST_DEB_MSG "osst :D: Buffer size %d bytes, write threshold %d bytes.\n",
         osst_buffer_size, osst_write_threshold);
 #endif
   return 0;
@@ -5135,9 +5427,12 @@ int init_module(void) {
       osst_max_buffers = max_buffers;
   if (max_sg_segs >= OSST_FIRST_SG)
       osst_max_sg_segs = max_sg_segs;
-  printk(KERN_INFO "osst: bufsize %d, wrt %d, max buffers %d, s/g segs %d.\n",
+#if DEBUG
+  printk(OSST_DEB_MSG "osst :D: bufsize %d, wrt %d, max buffers %d, s/g segs %d.\n",
         osst_buffer_size, osst_write_threshold, osst_max_buffers, osst_max_sg_segs);
-//printk(OSST_DEB_MSG "osst: sizeof(header) = %d (%s)\n",sizeof(os_header_t),sizeof(os_header_t)==OS_DATA_SIZE?"ok":"error");
+//printk(OSST_DEB_MSG "osst :D: sizeof(header) = %d (%s)\n",
+//             sizeof(os_header_t),sizeof(os_header_t)==OS_DATA_SIZE?"ok":"error");
+#endif
   osst_template.module = &__this_module;
   result = scsi_register_module(MODULE_SCSI_DEV, &osst_template);
   if (result)
@@ -5179,6 +5474,6 @@ void cleanup_module( void)
     }
   }
   osst_template.dev_max = 0;
-  printk(KERN_INFO "osst: Unloaded.\n");
+  printk(KERN_INFO "osst :I: Unloaded.\n");
 }
 #endif /* MODULE */
index 95e519ae7364b7747322aa6f7422ca3ac8027ca0..f4d1f6d010514a444b6489aefb2a2f2934eb4e74 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     $Header: /home/cvsroot/Driver/osst.h,v 1.5.2.2 2000/10/08 03:07:33 riede Exp $
+ *     $Header: /home/cvsroot/Driver/osst.h,v 1.5.2.4 2001/01/26 01:30:56 riede Exp $
  */
 
 #include <linux/config.h>
@@ -319,7 +319,8 @@ typedef struct os_aux_s {
          * Linux specific fields:
          */
          __u32          next_mark_ppos;         /* when known, points to next marker */
-         __u8           linux_specific[28];
+        __u32          last_mark_lbn;          /* storing log_blk_num of last mark is extends ADR spec */
+         __u8           linux_specific[24];
 
         __u8            reserved_256_511[256];
 } os_aux_t;
@@ -459,6 +460,8 @@ typedef struct {
   int min_block;
   int max_block;
   int recover_count;            /* from tape opening */
+  int write_count;
+  int read_count;
   int recover_erreg;            /* from last status call */
   /*
    * OnStream specific data
@@ -466,8 +469,9 @@ typedef struct {
   int     os_fw_rev;                          /* the firmware revision * 10000 */
   unsigned char  raw;                          /* flag OnStream raw access (32.5KB block size) */
   unsigned char  poll;                         /* flag that this drive needs polling (IDE|firmware) */
-  unsigned char  logical_blk_in_buffer;               /* flag that the block as per logical_blk_num
+  unsigned char  frame_in_buffer;             /* flag that the frame as per frame_seq_number
                                                * has been read into STp->buffer and is valid */
+  int      frame_seq_number;                   /* logical frame number */
   int      logical_blk_num;                    /* logical block number */
   unsigned first_frame_position;               /* physical frame to be transfered to/from host */
   unsigned last_frame_position;                /* physical frame to be transferd to/from tape */
@@ -485,6 +489,7 @@ typedef struct {
   int      filemark_cnt;
   int      first_mark_ppos;
   int      last_mark_ppos;
+  int      last_mark_lbn;                      /* storing log_blk_num of last mark is extends ADR spec */
   int      first_data_ppos;
   int      eod_frame_ppos;
   int      eod_frame_lfa;
index 7b48e1019b88f3ab4c7b06f8b81df0f1d1f9cab1..c14ae3e95445c481eaf4ec09f8bf43449b3a6597 100644 (file)
@@ -8,7 +8,7 @@
    Changed (and renamed) for OnStream SCSI drives garloff@suse.de
    2000-06-21
 
-   $Header: /home/cvsroot/Driver/osst_options.h,v 1.4 2000/06/26 01:44:01 riede Exp $
+   $Header: /home/cvsroot/Driver/osst_options.h,v 1.4.2.1 2000/11/25 22:02:44 riede Exp $
 */
 
 #ifndef _OSST_OPTIONS_H
@@ -24,7 +24,7 @@
    because of buffered reads. Should be set to zero to support also drives
    that can't space backwards over records. NOTE: The tape will be
    spaced backwards over an "accidentally" crossed filemark in any case. */
-#define OSST_IN_FILE_POS 0
+#define OSST_IN_FILE_POS 1
 
 /* The tape driver buffer size in kilobytes. */
 /* Don't change, as this is the HW blocksize */
 /* The number of kilobytes of data in the buffer that triggers an
    asynchronous write in fixed block mode. See also OSST_ASYNC_WRITES
    below. */
-#define OSST_WRITE_THRESHOLD_BLOCKS 30
+#define OSST_WRITE_THRESHOLD_BLOCKS 32
+
+/* OSST_EOM_RESERVE defines the number of frames are kept in reserve for
+ *  * write error recovery when writing near end of medium. ENOSPC is returned
+ *   * when write() is called and the tape write position is within this number
+ *    * of blocks from the tape capacity. */
+#define OSST_EOM_RESERVE 300
 
 /* The maximum number of tape buffers the driver allocates. The number
    is also constrained by the number of drives detected. Determines the
@@ -64,7 +70,7 @@
 
 /* If OSST_BUFFER_WRITES is non-zero, writes in fixed block mode are
    buffered until the driver buffer is full or asynchronous write is
-   triggered. May make detection of End-Of-Medium early enough fail. */
+   triggered. */
 #define OSST_BUFFER_WRITES 1
 
 /* If OSST_ASYNC_WRITES is non-zero, the SCSI write command may be started
index 1f8a209d2278f7b9bb569d2d73f35db0b54ca2cf..14899795b49dea92c71df56d740c748726f93180 100644 (file)
@@ -648,7 +648,8 @@ __initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
                        /* Is this a red snapper? */
                        if(strcmp(qpti_dev->prom_name, "ptisp") &&
                           strcmp(qpti_dev->prom_name, "PTI,ptisp") &&
-                          strcmp(qpti_dev->prom_name, "QLGC,isp"))
+                          strcmp(qpti_dev->prom_name, "QLGC,isp") &&
+                          strcmp(qpti_dev->prom_name, "SUNW,isp"))
                                continue;
 
                        /* Sometimes Antares cards come up not completely
index 25adc335b300292b0f913f7a62bda5a7d018319e..a365acb2aca536d0b276fb52933532525e549dbc 100644 (file)
@@ -1,10 +1,19 @@
 /*
- * bluetooth.c   Version 0.7
+ * bluetooth.c   Version 0.8
  *
  * Copyright (c) 2000 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
+ * 
+ * (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.
 #define DEBUG
 #include <linux/usb.h>
 
-/* Module information */
-MODULE_AUTHOR("Greg Kroah-Hartman, Mark Douglas Corner");
-MODULE_DESCRIPTION("USB Bluetooth driver");
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.8"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
+#define DRIVER_DESC "USB Bluetooth driver"
 
 /* define this if you have hardware that is not good */
 /*#define      BTBUGGYHARDWARE */
@@ -371,6 +383,7 @@ static void bluetooth_close (struct tty_struct *tty, struct file * filp)
        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);
 
        bluetooth->active = 0;
 }
@@ -844,7 +857,7 @@ static void bluetooth_read_bulk_callback (struct urb *urb)
 
        if (!bluetooth) {
                dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
-               goto exit;
+               return;
        }
 
        if (urb->status) {
@@ -1274,6 +1287,9 @@ int usb_bluetooth_init(void)
                return -1;
        }
 
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
+
        return 0;
 }
 
@@ -1288,4 +1304,7 @@ void usb_bluetooth_exit(void)
 module_init(usb_bluetooth_init);
 module_exit(usb_bluetooth_exit);
 
+/* Module information */
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
index 76e6c214b9d62d047ab3c92c7864469980c52d56..510cb1d80d5b5c2dbe28e4f366d6e5bec7464a2d 100644 (file)
 #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
@@ -173,8 +180,8 @@ static void dabusb_iso_complete (purb_t purb)
 
        // process if URB was not killed
        if (purb->status != -ENOENT) {
-               unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE);
-               int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe));
+               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;
@@ -456,8 +463,6 @@ static int dabusb_startrek (pdabusb_t s)
 
                        end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
 
-                       end->purb->dev=s->usbdev;
-
                        ret = usb_submit_urb (end->purb);
                        if (ret) {
                                err("usb_submit_urb returned:%d", ret);
@@ -793,11 +798,11 @@ static void dabusb_disconnect (struct usb_device *usbdev, void *ptr)
 
 static struct usb_driver dabusb_driver =
 {
-       "dabusb",
-       dabusb_probe,
-       dabusb_disconnect,
-       {NULL, NULL},
-       &dabusb_fops,
+       name:           "dabusb",
+       probe:          dabusb_probe,
+       disconnect:     dabusb_disconnect,
+       fops:           &dabusb_fops,
+       minor:          DABUSB_MINOR,
        DABUSB_MINOR
 };
 
@@ -826,6 +831,10 @@ static int __init dabusb_init (void)
                return -1;
 
        dbg("dabusb_init: driver registered");
+
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
+
        return 0;
 }
 
@@ -838,8 +847,9 @@ static void __exit dabusb_cleanup (void)
 
 /* --------------------------------------------------------------------- */
 
-MODULE_AUTHOR ("Deti Fliegl, deti@fliegl.de");
-MODULE_DESCRIPTION ("DAB-USB Interface Driver for Linux (c)1999");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
 MODULE_PARM (buffers, "i");
 MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
 
index 82877003c00874d274699cea527adcab2d810aee..ddb4d8971573fc32e01c19912b0bf88b72933dfa 100644 (file)
@@ -23,7 +23,7 @@ typedef struct
        wait_queue_head_t wait;
        wait_queue_head_t remove_ok;
        spinlock_t lock;
-       volatile atomic_t pending_io;
+       atomic_t pending_io;
        driver_state_t state;
        int remove_pending;
        int got_mem;
index b167699fd82c0d0709c953f02a6f524f778fc0ff..3b403f0e82cd66a71b2dccc1b7649445984c87c5 100644 (file)
  * 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
+ * 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 sucesses!
+ * patches, and shared their successes!
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
@@ -59,6 +61,7 @@
 #include <linux/init.h>
 #include <linux/malloc.h>
 #include <linux/module.h>
+
 #ifdef CONFIG_USB_DEBUG
        #define DEBUG
 #else
 #include <linux/usb.h>
 
 
+/*
+ * 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
@@ -170,7 +180,7 @@ static ssize_t camera_read (struct file *file,
                          usb_rcvbulkpipe (camera->dev, camera->inEP),
                          camera->buf, len, &count, HZ*10);
 
-               dbg ("read (%d) - 0x%x %d", len, retval, count);
+               dbg ("read (%Zd) - 0x%x %d", len, retval, count);
 
                if (!retval) {
                        if (copy_to_user (buf, camera->buf, count))
@@ -183,7 +193,7 @@ static ssize_t camera_read (struct file *file,
                        break;
                interruptible_sleep_on_timeout (&camera->wait, RETRY_TIMEOUT);
 
-               dbg ("read (%d) - retry", len);
+               dbg ("read (%Zd) - retry", len);
        }
        up (&camera->sem);
        return retval;
@@ -267,7 +277,7 @@ static ssize_t camera_write (struct file *file,
        }
 done:
        up (&camera->sem);
-       dbg ("wrote %d", bytes_written); 
+       dbg ("wrote %Zd", bytes_written); 
        return bytes_written;
 }
 
@@ -324,8 +334,9 @@ static int camera_release (struct inode *inode, struct file *file)
        if (!camera->dev) {
                minor_data [subminor] = NULL;
                kfree (camera);
-       }
-       up (&camera->sem);
+       } else
+               up (&camera->sem);
+       
        up (&state_table_mutex);
 
        dbg ("close #%d", subminor); 
@@ -396,7 +407,6 @@ static void * camera_probe(struct usb_device *dev, unsigned int ifnum)
        }
        if (i >= MAX_CAMERAS) {
                info ("Ignoring additional USB Camera");
-               up (&state_table_mutex);
                goto bye;
        }
 
@@ -404,7 +414,6 @@ static void * camera_probe(struct usb_device *dev, unsigned int ifnum)
        camera = minor_data [i] = kmalloc (sizeof *camera, GFP_KERNEL);
        if (!camera) {
                err ("no memory!");
-               up (&state_table_mutex);
                goto bye;
        }
 
@@ -471,13 +480,15 @@ static void camera_disconnect(struct usb_device *dev, void *ptr)
        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);
 
-       up (&camera->sem);
+       if (camera != NULL)
+               up (&camera->sem);
        up (&state_table_mutex);
 }
 
@@ -496,6 +507,8 @@ int __init usb_dc2xx_init(void)
 {
        if (usb_register (&camera_driver) < 0)
                return -1;
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
        return 0;
 }
 
@@ -504,9 +517,9 @@ void __exit usb_dc2xx_cleanup(void)
        usb_deregister (&camera_driver);
 }
 
-
-MODULE_AUTHOR("David Brownell, dbrownell@users.sourceforge.net");
-MODULE_DESCRIPTION("USB Camera Driver for Kodak DC-2xx series cameras");
-
 module_init (usb_dc2xx_init);
 module_exit (usb_dc2xx_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
index e6066a86635ae3da2f3670d8594b9f3baa0aa7f3..11b9e38762833966a76349a1310fe783bd09bda5 100644 (file)
  *     (c) 1999/2000 Henning Zabel <henning@uni-paderborn.de>
  *
  *
- *     The driver brings the USB functions of the MDC800 to Linux.
+ * 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.
+ * 
+ * (08/04/2001) gb
+ * Identify version on module load.
+ *
+ * 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
@@ -61,7 +74,7 @@
  * (09/11/1999)
  *
  * version 0.5.0:
- *     first Version that gets a version number. Most of the needed
+ * first Version that gets a version number. Most of the needed
  * functions work.
  * (20/10/1999)
  */
 
 #include <linux/usb.h>
 
-#define VERSION        "0.7.3"
-#define RELEASE_DATE   "(24/04/2000)"
+/*
+ * 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
@@ -123,7 +140,7 @@ struct mdc800_data
 
        int                     camera_busy;          // is camera busy ?
        int                     camera_request_ready; // Status to synchronize with irq
-       char                    camera_response [8];     // last Bytes send after busy
+       char                    camera_response [8];  // last Bytes send after busy
 
        purb_t                  write_urb;
        char*                   write_urb_buffer;
@@ -138,16 +155,16 @@ struct mdc800_data
 
        /* Device Data */
        char                    out [64];       // Answer Buffer
-       int                     out_ptr;                // Index to the first not readen byte
+       int                     out_ptr;        // Index to the first not readen byte
        int                     out_count;      // Bytes in the buffer
 
-       int                     open;                   // Camera device open ?
-       int                     rw_lock;                // Block read <-> write
+       int                     open;           // Camera device open ?
+       spinlock_t              io_lock;        // IO -lock     
 
-       char                    in [8];                 // Command Input Buffer
+       char                    in [8];         // Command Input Buffer
        int                     in_count;
 
-       int                     pic_index;              // Cache for the Imagesize (-1 for nothing cached )
+       int                     pic_index;      // Cache for the Imagesize (-1 for nothing cached )
        int                     pic_len;
 };
 
@@ -253,16 +270,16 @@ static void mdc800_usb_irq (struct urb *urb)
                }
        }
        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)
-                               );
+               &&
+               (
+                       ((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)
        {
@@ -362,7 +379,7 @@ static struct usb_driver mdc800_usb_driver;
  */
 static void* mdc800_usb_probe (struct usb_device *dev ,unsigned int ifnum )
 {
-       int                                                                             i,j;
+       int i,j;
        struct usb_interface_descriptor *intf_desc;
        int irq_interval=0;
 
@@ -432,10 +449,10 @@ static void* mdc800_usb_probe (struct usb_device *dev ,unsigned int ifnum )
 
        info ("Found Mustek MDC800 on USB.");
 
+       spin_lock (&mdc800->io_lock);
+
        mdc800->dev=dev;
-       mdc800->state=READY;
        mdc800->open=0;
-       mdc800->rw_lock=0;
 
        /* Setup URB Structs */
        FILL_INT_URB (
@@ -469,6 +486,10 @@ static void* mdc800_usb_probe (struct usb_device *dev ,unsigned int ifnum )
                mdc800
        );
 
+       mdc800->state=READY;
+
+       spin_unlock (&mdc800->io_lock);
+       
        return mdc800;
 }
 
@@ -539,18 +560,21 @@ static int mdc800_getAnswerSize (char command)
 static int mdc800_device_open (struct inode* inode, struct file *file)
 {
        int retval=0;
+       int errn=0;
+
+       spin_lock (&mdc800->io_lock);
        
        if (mdc800->state == NOT_CONNECTED)
        {
-               return -EBUSY;
+               errn=-EBUSY;
+               goto error_out;
        }
-
        if (mdc800->open)
        {
-               return -EBUSY;
+               errn=-EBUSY;
+               goto error_out;
        }
 
-       mdc800->rw_lock=0;
        mdc800->in_count=0;
        mdc800->out_count=0;
        mdc800->out_ptr=0;
@@ -562,16 +586,20 @@ static int mdc800_device_open (struct inode* inode, struct file *file)
        mdc800->camera_request_ready=0;
 
        retval=0;
+       mdc800->irq_urb->dev = mdc800->dev;
        if (usb_submit_urb (mdc800->irq_urb))
        {
                err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status);
-               return -EIO;
+               errn = -EIO;
+               goto error_out;
        }
 
        mdc800->open=1;
-
        dbg ("Mustek MDC800 device opened.");
-       return 0;
+
+error_out:
+       spin_unlock (&mdc800->io_lock);
+       return errn;
 }
 
 
@@ -583,7 +611,7 @@ static int mdc800_device_release (struct inode* inode, struct file *file)
        int retval=0;
        dbg ("Mustek MDC800 device closed.");
 
-       lock_kernel();
+       spin_lock (&mdc800->io_lock);
        if (mdc800->open && (mdc800->state != NOT_CONNECTED))
        {
                mdc800->open=0;
@@ -595,7 +623,7 @@ static int mdc800_device_release (struct inode* inode, struct file *file)
        {
                retval=-EIO;
        }
-       unlock_kernel();
+       spin_unlock (&mdc800->io_lock);
 
        return retval;
 }
@@ -609,23 +637,29 @@ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, lof
        int   left=len, sts=len; /* single transfer size */
        char* ptr=buf;
 
+       spin_lock (&mdc800->io_lock);
        if (mdc800->state == NOT_CONNECTED)
+       {
+               spin_unlock (&mdc800->io_lock);
                return -EBUSY;
-
+       }
        if (mdc800->state == WORKING)
        {
                warn ("Illegal State \"working\" reached during read ?!");
+               spin_unlock (&mdc800->io_lock);
                return -EBUSY;
        }
-
-       if (!mdc800->open || mdc800->rw_lock)
+       if (!mdc800->open)
+       {
+               spin_unlock (&mdc800->io_lock);
                return -EBUSY;
-       mdc800->rw_lock=1;
+       }
 
        while (left)
        {
-               if (signal_pending (current)) {
-                       mdc800->rw_lock=0;
+               if (signal_pending (current)) 
+               {
+                       spin_unlock (&mdc800->io_lock);
                        return -EINTR;
                }
 
@@ -640,24 +674,25 @@ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, lof
                                mdc800->out_ptr=0;
 
                                /* Download -> Request new bytes */
+                               mdc800->download_urb->dev = mdc800->dev;
                                if (usb_submit_urb (mdc800->download_urb))
                                {
                                        err ("Can't submit download urb (status=%i)",mdc800->download_urb->status);
-                                       mdc800->rw_lock=0;
+                                       spin_unlock (&mdc800->io_lock);
                                        return len-left;
                                }
                                interruptible_sleep_on_timeout (&mdc800->download_wait, TO_DOWNLOAD_GET_READY*HZ/1000);
                                if (mdc800->download_urb->status != 0)
                                {
                                        err ("request download-bytes fails (status=%i)",mdc800->download_urb->status);
-                                       mdc800->rw_lock=0;
+                                       spin_unlock (&mdc800->io_lock);
                                        return len-left;
                                }
                        }
                        else
                        {
                                /* No more bytes -> that's an error*/
-                               mdc800->rw_lock=0;
+                               spin_unlock (&mdc800->io_lock);
                                return -EIO;
                        }
                }
@@ -671,7 +706,7 @@ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, lof
                }
        }
 
-       mdc800->rw_lock=0;
+       spin_unlock (&mdc800->io_lock);
        return len-left;
 }
 
@@ -686,17 +721,23 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
 {
        int i=0;
 
+       spin_lock (&mdc800->io_lock);
        if (mdc800->state != READY)
+       {
+               spin_unlock (&mdc800->io_lock);
                return -EBUSY;
-
-       if (!mdc800->open || mdc800->rw_lock)
+       }
+       if (!mdc800->open )
+       {
+               spin_unlock (&mdc800->io_lock);
                return -EBUSY;
-       mdc800->rw_lock=1;
+       }
 
        while (i<len)
        {
-               if (signal_pending (current)) {
-                       mdc800->rw_lock=0;
+               if (signal_pending (current)) 
+               {
+                       spin_unlock (&mdc800->io_lock);
                        return -EINTR;
                }
 
@@ -718,7 +759,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                else
                {
                        err ("Command is to long !\n");
-                       mdc800->rw_lock=0;
+                       spin_unlock (&mdc800->io_lock);
                        return -EIO;
                }
 
@@ -730,7 +771,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                        if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
                        {
                                err ("Camera didn't get ready.\n");
-                               mdc800->rw_lock=0;
+                               spin_unlock (&mdc800->io_lock);
                                return -EIO;
                        }
 
@@ -738,17 +779,18 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
 
                        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))
                        {
                                err ("submitting write urb fails (status=%i)", mdc800->write_urb->status);
-                               mdc800->rw_lock=0;
+                               spin_unlock (&mdc800->io_lock);
                                return -EIO;
                        }
                        interruptible_sleep_on_timeout (&mdc800->write_wait, TO_WRITE_GET_READY*HZ/1000);
                        if (mdc800->state == WORKING)
                        {
                                usb_unlink_urb (mdc800->write_urb);
-                               mdc800->rw_lock=0;
+                               spin_unlock (&mdc800->io_lock);
                                return -EIO;
                        }
 
@@ -760,7 +802,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                                        {
                                                err ("call 0x07 before 0x05,0x3e");
                                                mdc800->state=READY;
-                                               mdc800->rw_lock=0;
+                                               spin_unlock (&mdc800->io_lock);
                                                return -EIO;
                                        }
                                        mdc800->pic_len=-1;
@@ -779,7 +821,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                                                if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ))
                                                {
                                                        err ("requesting answer from irq fails");
-                                                       mdc800->rw_lock=0;
+                                                       spin_unlock (&mdc800->io_lock);
                                                        return -EIO;
                                                }
 
@@ -807,7 +849,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                                                if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND))
                                                {
                                                        err ("Command Timeout.");
-                                                       mdc800->rw_lock=0;
+                                                       spin_unlock (&mdc800->io_lock);
                                                        return -EIO;
                                                }
                                        }
@@ -817,7 +859,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                }
                i++;
        }
-       mdc800->rw_lock=0;
+       spin_unlock (&mdc800->io_lock);
        return i;
 }
 
@@ -842,12 +884,11 @@ static struct file_operations mdc800_device_ops =
  */
 static struct usb_driver mdc800_usb_driver =
 {
-       "mdc800",
-       mdc800_usb_probe,
-       mdc800_usb_disconnect,
-       { 0,0 },
-       &mdc800_device_ops,
-       MDC800_DEVICE_MINOR_BASE
+       name:           "mdc800",
+       probe:          mdc800_usb_probe,
+       disconnect:     mdc800_usb_disconnect,
+       fops:           &mdc800_device_ops,
+       minor:          MDC800_DEVICE_MINOR_BASE,
 };
 
 
@@ -865,10 +906,11 @@ 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;
-       memset(mdc800, 0, sizeof(struct mdc800_data));
+       spin_lock_init (&mdc800->io_lock);
 
        init_waitqueue_head (&mdc800->irq_wait);
        init_waitqueue_head (&mdc800->write_wait);
@@ -886,8 +928,8 @@ int __init usb_mdc800_init (void)
        if (usb_register (&mdc800_usb_driver) < 0)
                goto cleanup_on_fail;
 
-       info ("Mustek Digital Camera Driver " VERSION " (MDC800)");
-       info (RELEASE_DATE " Henning Zabel <henning@uni-paderborn.de>");
+       info (DRIVER_VERSION " " DRIVER_AUTHOR);
+       info (DRIVER_DESC);
 
        return 0;
 
@@ -930,9 +972,9 @@ void __exit usb_mdc800_cleanup (void)
        mdc800=0;
 }
 
-
-MODULE_AUTHOR ("Henning Zabel <henning@uni-paderborn.de>");
-MODULE_DESCRIPTION ("USB Driver for Mustek MDC800 Digital Camera");
-
 module_init (usb_mdc800_init);
 module_exit (usb_mdc800_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
index ec72462443e2de25eaa469ffb7b1bb2184e662f1..be2a8816409538d13d63c16d921fbbd30f0d80ef 100644 (file)
@@ -30,8 +30,6 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-static const char version[] = "1.25";
-
 #define __NO_VERSION__
 
 #include <linux/config.h>
@@ -55,7 +53,12 @@ static const char version[] = "1.25";
 
 #include "ov511.h"
 
-#undef OV511_GBR422            /* Experimental -- sets the 7610 to GBR422 */
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.28"
+#define DRIVER_AUTHOR "Mark McClelland <mwm@i.am> & 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
 
@@ -64,8 +67,6 @@ static const char version[] = "1.25";
 #define MAX_DATA_SIZE (MAX_FRAME_SIZE + sizeof(struct timeval))
 
 #define GET_SEGSIZE(p) ((p) == VIDEO_PALETTE_GREY ? 256 : 384)
-#define GET_DEPTH(p) ((p) == VIDEO_PALETTE_GREY ? 8 : \
-                    ((p) == VIDEO_PALETTE_YUV422 ? 16 : 24))
 
 /* PARAMETER VARIABLES: */
 static int autoadjust = 1;    /* CCD dynamically changes exposure, etc... */
@@ -78,7 +79,7 @@ static int autoadjust = 1;    /* CCD dynamically changes exposure, etc... */
  * 5=highly repetitive mesgs
  * NOTE: This should be changed to 0, 1, or 2 for production kernels
  */
-static int debug = 3;
+static int debug = 0;
 
 /* Fix vertical misalignment of red and blue at 640x480 */
 static int fix_rgb_offset = 0;
@@ -116,6 +117,13 @@ static int compress = 0;
 /* Display test pattern - doesn't work yet either */
 static int testpat = 0;
 
+/* Setting this to 1 will make the sensor output GBR422 instead on YUV420. Only
+ * affects RGB24 mode. */
+static int sensor_gbr = 0;
+
+/* Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details. */
+static int dumppix = 0;
+
 MODULE_PARM(autoadjust, "i");
 MODULE_PARM_DESC(autoadjust, "CCD dynamically changes exposure");
 MODULE_PARM(debug, "i");
@@ -142,11 +150,13 @@ MODULE_PARM(compress, "i");
 MODULE_PARM_DESC(compress, "Turn on compression (not functional yet)");
 MODULE_PARM(testpat, "i");
 MODULE_PARM_DESC(testpat, "Replace image with vertical bar testpattern (only partially working)");
+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, in one of 3 formats. See ov511_dumppix() for details");
 
-MODULE_AUTHOR("Mark McClelland <mwm@i.am> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>");
-MODULE_DESCRIPTION("OV511 USB Camera Driver");
-
-static char kernel_version[] = UTS_RELEASE;
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 static struct usb_driver ov511_driver;
 
@@ -223,9 +233,10 @@ static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
                if (!pmd_none(*pmd)) {
                        ptep = pte_offset(pmd, adr);
                        pte = *ptep;
-                       if (pte_present(pte))
-                               ret = page_address(pte_page(pte)) |
-                                     (adr & (PAGE_SIZE-1));
+                       if (pte_present(pte)) {
+                               ret = (unsigned long) page_address(pte_page(pte));
+                               ret |= (adr & (PAGE_SIZE - 1));
+                       }
                }
        }
 
@@ -360,6 +371,7 @@ static int ov511_read_proc(char *page, char **start, off_t off,
                ov511->bridge == BRG_OV511PLUS ? "OV511+" :
                "unknown");
        out += sprintf (out, "sensor          : %s\n",
+               ov511->sensor == SEN_OV6620 ? "OV6620" :
                ov511->sensor == SEN_OV7610 ? "OV7610" :
                ov511->sensor == SEN_OV7620 ? "OV7620" :
                ov511->sensor == SEN_OV7620AE ? "OV7620AE" :
@@ -451,7 +463,6 @@ static void proc_ov511_destroy(void)
 }
 #endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
 
-
 /**********************************************************************
  *
  * Camera interface
@@ -703,7 +714,7 @@ static int ov511_reset(struct usb_device *dev, unsigned char reset_type)
 {
        int rc;
        
-       PDEBUG(3, "Reset: type=0x%X", reset_type);
+       PDEBUG(4, "Reset: type=0x%X", reset_type);
        rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type);
        rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0);
 
@@ -832,14 +843,21 @@ ov7610_set_picture(struct usb_ov511 *ov511, struct video_picture *p)
        } else if ((ov511->sensor == SEN_OV7620) 
                 || (ov511->sensor == SEN_OV7620AE)) {
 #if 0
-               cur_con = ov511_i2c_read(dev, OV7610_REG_CNT);
-               cur_brt = ov511_i2c_read(dev, OV7610_REG_BRT);
-               // DEBUG_CODE
-               PDEBUG(1, "con=%d brt=%d", ov511_i2c_read(dev, OV7610_REG_CNT),
-                ov511_i2c_read(dev, OV7610_REG_BRT)); 
+               int cur_sat, new_sat, tmp;
 
-               if (ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0)
+               cur_sat = ov511_i2c_read(dev, OV7610_REG_BLUE);
+
+               tmp = (p->hue >> 8) - cur_sat;
+               new_sat = (tmp < 0) ? (-tmp) | 0x80 : tmp;
+
+               PDEBUG(1, "cur=%d target=%d diff=%d", cur_sat, p->hue >> 8, tmp); 
+
+               if (ov511_i2c_write(dev, OV7610_REG_BLUE, new_sat) < 0)
                        return -EIO;
+
+               // DEBUG_CODE
+               PDEBUG(1, "hue=%d", ov511_i2c_read(dev, OV7610_REG_BLUE)); 
+
 #endif
        }
 
@@ -885,6 +903,23 @@ ov7610_get_picture(struct usb_ov511 *ov511, struct video_picture *p)
        return 0;
 }
 
+/* Returns number of bits per pixel (regardless of where they are located; planar or
+ * not), or zero for unsupported format.
+ */
+static int ov511_get_depth(int palette)
+{
+       switch (palette) {
+       case VIDEO_PALETTE_GREY:    return 8;
+       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_YUV420:  return 24;
+       case VIDEO_PALETTE_YUV422P: return 24; /* Planar */
+       default:                    return 0;  /* Invalid format */
+       }
+}
+
 /* LNCNT values fixed by Lawrence Glaister <lg@jfm.bc.ca> */
 static struct mode_list mlist[] = {
        /* W    H   C  PXCNT LNCNT PXDIV LNDIV M420  COMA  COML */
@@ -920,6 +955,12 @@ ov511_mode_init_regs(struct usb_ov511 *ov511,
        if (ov511_stop(ov511->dev) < 0)
                return -EIO;
 
+       /* Dumppix only works with RGB24 */
+       if (dumppix && (mode != VIDEO_PALETTE_RGB24)) {
+               err("dumppix only supported with RGB 24");
+               return -EINVAL;
+       }
+
        if (mode == VIDEO_PALETTE_GREY) {
                ov511_reg_write(dev, 0x16, 0x00);
                if (ov511->sensor == SEN_OV7610
@@ -956,9 +997,9 @@ ov511_mode_init_regs(struct usb_ov511 *ov511,
                break;
        case SEN_OV6620:
                hwsbase = 0x38;
-               hwebase = 0x39;
-               vwsbase = 0x03;
-               vwebase = 0x04;
+               hwebase = 0x3a;
+               vwsbase = 0x05;
+               vwebase = 0x06;
                break;
        case SEN_OV7620:
                hwsbase = 0x2c;
@@ -1042,13 +1083,16 @@ ov511_mode_init_regs(struct usb_ov511 *ov511,
                /* Calculate and set the clock divisor */
                clock = ((sub_flag ? ov511->subw * ov511->subh : width * height)
                        * (mlist[i].color ? 3 : 2) / 2) / 66000;
+#if 0
+               clock *= cams;
+#endif
                ov511_i2c_write(dev, 0x11, clock);
 
-#ifdef OV511_GBR422
-               ov511_i2c_write(dev, 0x12, mlist[i].common_A | 0x08);
-#else
-               ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x02:0x00));
-#endif
+               /* We only have code to convert GBR -> RGB24 */
+               if ((mode == VIDEO_PALETTE_RGB24) && sensor_gbr)
+                       ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x0a:0x08));
+               else
+                       ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x02:0x00));
 
                /* 7620/6620 don't have register 0x35, so play it safe */
                if (ov511->sensor == SEN_OV7610 ||
@@ -1116,7 +1160,7 @@ ov511_mode_init_regs(struct usb_ov511 *ov511,
 
 static inline void
 ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, 
-       int rowPixels, unsigned char * rgb)
+       int rowPixels, unsigned char * rgb, int bits)
 {
        const int rvScale = 91881;
        const int guScale = -22553;
@@ -1137,14 +1181,32 @@ ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
        yTL *= yScale; yTR *= yScale;
        yBL *= yScale; yBR *= yScale;
 
-       /* 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);
+       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;
 
-       /* 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);
+               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);
+       }
 }
 
 /*
@@ -1170,7 +1232,7 @@ ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
  * 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 OV511_DUMPPIX is defined, _parse_data just dumps the incoming segments,
+ * 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
@@ -1180,14 +1242,8 @@ ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
 #define HDIV 8
 #define WDIV (256/HDIV)
 
-#undef OV511_DUMPPIX
-
-/* #define this and OV511_DUMPPIX to disable parsing of UV data */
-#undef OV511_FORCE_MONO
-
-#ifdef OV511_GBR422
 static void
-ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0,
+ov511_parse_gbr422_to_rgb24(unsigned char *pIn0, unsigned char *pOut0,
                       int iOutY, int iOutUV, int iHalf, int iWidth)
 {
        int k, l, m;
@@ -1234,14 +1290,12 @@ ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0,
        }
 }
 
-#else
-
 static void
-ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0,
-                      int iOutY, int iOutUV, int iHalf, int iWidth)
+ov511_parse_yuv420_to_rgb(unsigned char *pIn0, unsigned char *pOut0,
+                      int iOutY, int iOutUV, int iHalf, int iWidth, int bits)
 {
-#ifndef OV511_DUMPPIX
        int k, l, m;
+       int bytes = bits >> 3;
        unsigned char *pIn;
        unsigned char *pOut, *pOut1;
 
@@ -1254,11 +1308,11 @@ ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0,
                        for (l = 0; l < 8; l++) {
                                for (m = 0; m < 8; m++) {
                                        *pOut1 = *pIn++;
-                                       pOut1 += 3;
+                                       pOut1 += bytes;
                                }
-                               pOut1 += (iWidth - 8) * 3;
+                               pOut1 += (iWidth - 8) * bytes;
                        }
-                       pOut += 8 * 3;
+                       pOut += 8 * bytes;
                }
        }
 
@@ -1268,16 +1322,16 @@ ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0,
        for (l = 0; l < 4; l++) {
                for (m=0; m<8; m++) {
                        int y00 = *(pOut);
-                       int y01 = *(pOut+3);
-                       int y10 = *(pOut+iWidth*3);
-                       int y11 = *(pOut+iWidth*3+3);
+                       int y01 = *(pOut+bytes);
+                       int y10 = *(pOut+iWidth*bytes);
+                       int y11 = *(pOut+iWidth*bytes+bytes);
                        int v   = *(pIn+64) - 128;
                        int u   = *pIn++ - 128;
                        ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth,
-                               pOut);
-                       pOut += 6;
+                               pOut, bits);
+                       pOut += 2 * bytes;
                }
-               pOut += (iWidth*2 - 16) * 3;
+               pOut += (iWidth*2 - 16) * bytes;
        }
 
        /* Just copy the other UV rows */
@@ -1285,9 +1339,9 @@ ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0,
                for (m = 0; m < 8; m++) {
                        *pOut++ = *(pIn + 64);
                        *pOut = *pIn++;
-                       pOut += 5;
+                       pOut += 2 * bytes - 1;
                }
-               pOut += (iWidth*2 - 16) * 3;
+               pOut += (iWidth*2 - 16) * bytes;
        }
 
        /* Calculate values if it's the second half */
@@ -1305,72 +1359,65 @@ ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0,
                                        int v   = *pOut1 - 128;
                                        int u   = *(pOut1+1) - 128;
                                        ov511_move_420_block(y00, y01, y10,
-                                               y11, u, v, iWidth, pOut1);
-                                       pOut1 += 6;
+                                               y11, u, v, iWidth, pOut1, bits);
+                                       pOut1 += 2 * bytes;
                                }
-                               pOut1 += (iWidth*2 - 8) * 3;
+                               pOut1 += (iWidth*2 - 8) * bytes;
                                pIn += 8;
                        }
-                       pOut += 8 * 3;
-               }
-       }
-#else
-
-#ifndef OV511_FORCE_MONO
-       /* Just dump pix data straight out for debug */
-       int i, j;
-
-       pOut0 += iOutY;
-       for (i = 0; i < HDIV; i++) {
-               for (j = 0; j < WDIV; j++) {
-                       *pOut0++ = *pIn0++;
-                       *pOut0++ = *pIn0++;
-                       *pOut0++ = *pIn0++;
+                       pOut += 8 * bytes;
                }
-               pOut0 += (iWidth - WDIV) * 3;
        }
-#else
+}
 
-#if 1
-       /* This converts the Y data to "black-and-white" RGB data */
-       /* Useful for experimenting with compression */
-       int k, l, m;
+static void
+ov511_dumppix(unsigned char *pIn0, unsigned char *pOut0,
+             int iOutY, int iOutUV, int iHalf, int iWidth)
+{
+       int i, j, k;
        unsigned char *pIn, *pOut, *pOut1;
 
-       pIn = pIn0 + 128;
-       pOut = pOut0 + iOutY;
-       for (k = 0; k < 4; k++) {
-               pOut1 = pOut;
-               for (l = 0; l < 8; l++) {
-                       for (m = 0; m < 8; m++) {
-                               *pOut1++ = *pIn;
-                               *pOut1++ = *pIn;
-                               *pOut1++ = *pIn++;
+       switch (dumppix) {
+       case 1: /* Just dump YUV data straight out for debug */
+               pOut0 += iOutY;
+               for (i = 0; i < HDIV; i++) {
+                       for (j = 0; j < WDIV; j++) {
+                               *pOut0++ = *pIn0++;
+                               *pOut0++ = *pIn0++;
+                               *pOut0++ = *pIn0++;
                        }
-                       pOut1 += (iWidth - 8) * 3;
+                       pOut0 += (iWidth - WDIV) * 3;
                }
-               pOut += 8 * 3;
-       }
-#else
-       /* This will dump the Y channel data stream as-is */ 
-       int count;
-       unsigned char *pIn, *pOut;
-
-       pIn = pIn0 + 128;
-       pOut = pOut0 + output_offset;
-       for (count = 0; count < 256; count++) {
-               *pOut++ = *pIn;
-               *pOut++ = *pIn;
-               *pOut++ = *pIn++;
-               output_offset += 3;
-       }       
-#endif
-
-#endif
-
-#endif
+               break;
+       case 2: /* This converts the Y data to "black-and-white" RGB data */
+               /* Useful for experimenting with compression */
+               pIn = pIn0 + 128;
+               pOut = pOut0 + iOutY;
+               for (i = 0; i < 4; i++) {
+                       pOut1 = pOut;
+                       for (j = 0; j < 8; j++) {
+                               for (k = 0; k < 8; k++) {
+                                       *pOut1++ = *pIn;
+                                       *pOut1++ = *pIn;
+                                       *pOut1++ = *pIn++;
+                               }
+                               pOut1 += (iWidth - 8) * 3;
+                       }
+                       pOut += 8 * 3;
+               }
+               break;
+       case 3: /* This will dump only the Y channel data stream as-is */
+               pIn = pIn0 + 128;
+               pOut = pOut0 + output_offset;
+               for (i = 0; i < 256; i++) {
+                       *pOut++ = *pIn;
+                       *pOut++ = *pIn;
+                       *pOut++ = *pIn++;
+                       output_offset += 3;
+               }
+               break;
+       } /* End switch (dumppix) */
 }
-#endif
 
 /* This converts YUV420 segments to YUYV */
 static void
@@ -1665,6 +1712,11 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
                        /* Frame start */
                        PDEBUG(4, "Frame start, framenum = %d", ov511->curframe);
 
+#if 0
+                       /* Make sure no previous data carries over; necessary
+                        * for compression experimentation */
+                       memset(frame->data, 0, MAX_DATA_SIZE);
+#endif
                        output_offset = 0;
 
                        /* Check to see if it's a snapshot frame */
@@ -1743,8 +1795,19 @@ check_middle:
                                ov511_parse_data_grey (pData, pOut, iOutY, frame->width);
                                break;
                        case VIDEO_PALETTE_RGB24:
-                               ov511_parse_data_rgb24 (pData, pOut, iOutY, iOutUV,
-                                       iY & 1, frame->width);
+                               if (dumppix)
+                                       ov511_dumppix(pData, pOut, iOutY, iOutUV,
+                                               iY & 1, frame->width);
+                               else if (sensor_gbr)
+                                       ov511_parse_gbr422_to_rgb24(pData, pOut, iOutY, iOutUV,
+                                               iY & 1, frame->width);
+                               else
+                                       ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV,
+                                               iY & 1, frame->width, 24);
+                               break;
+                       case VIDEO_PALETTE_RGB565:
+                               ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV,
+                                       iY & 1, frame->width, 16);
                                break;
                        case VIDEO_PALETTE_YUV422:
                        case VIDEO_PALETTE_YUYV:
@@ -1785,11 +1848,20 @@ check_middle:
 static void ov511_isoc_irq(struct urb *urb)
 {
        int len;
-       struct usb_ov511 *ov511 = urb->context;
+       struct usb_ov511 *ov511;
        struct ov511_sbuf *sbuf;
 
-       if (!ov511->dev)
+       if (!urb->context) {
+               PDEBUG(4, "no context");
                return;
+       }
+
+       ov511 = (struct usb_ov511 *) urb->context;
+
+       if (!ov511->dev || !ov511->user) {
+               PDEBUG(4, "no device, or not open");
+               return;
+       }
 
        if (!ov511->streaming) {
                PDEBUG(4, "hmmm... not streaming, but got interrupt");
@@ -1808,6 +1880,8 @@ static void ov511_isoc_irq(struct urb *urb)
        /* Move to the next sbuf */
        ov511->cursbuf = (ov511->cursbuf + 1) % OV511_NUMSBUF;
 
+       urb->dev = ov511->dev;
+
        return;
 }
 
@@ -1875,6 +1949,7 @@ static int ov511_init_isoc(struct usb_ov511 *ov511)
                ov511->sbuf[n].urb->next = ov511->sbuf[n+1].urb;
 
        for (n = 0; n < OV511_NUMSBUF; n++) {
+               ov511->sbuf[n].urb->dev = ov511->dev;
                err = usb_submit_urb(ov511->sbuf[n].urb);
                if (err)
                        err("init isoc: usb_submit_urb(%d) ret %d", n, err);
@@ -2082,7 +2157,7 @@ static void ov511_dealloc(struct usb_ov511 *ov511, int now)
 static int ov511_open(struct video_device *dev, int flags)
 {
        struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
-       int err = 0;
+       int err;
 
        MOD_INC_USE_COUNT;
        PDEBUG(4, "opening");
@@ -2171,14 +2246,15 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
 
                PDEBUG (4, "VIDIOCGCAP");
 
+               memset(&b, 0, sizeof(b));
                strcpy(b.name, "OV511 USB Camera");
                b.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
                b.channels = 1;
                b.audios = 0;
                b.maxwidth = ov511->maxwidth;
                b.maxheight = ov511->maxheight;
-               b.minwidth = 32;
-               b.minheight = 16;
+               b.minwidth = 160;
+               b.minheight = 120;
 
                if (copy_to_user(arg, &b, sizeof(b)))
                        return -EFAULT;
@@ -2222,9 +2298,11 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
 
                PDEBUG (4, "VIDIOCGPICT");
 
+               memset(&p, 0, sizeof(p));
+
                if (ov7610_get_picture(ov511, &p))
                        return -EIO;
-                                                       
+
                if (copy_to_user(arg, &p, sizeof(p)))
                        return -EFAULT;
 
@@ -2240,12 +2318,7 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
                if (copy_from_user(&p, arg, sizeof(p)))
                        return -EFAULT;
 
-               if (p.palette != VIDEO_PALETTE_GREY &&
-                   p.palette != VIDEO_PALETTE_RGB24 &&
-                   p.palette != VIDEO_PALETTE_YUV422 &&
-                   p.palette != VIDEO_PALETTE_YUYV &&
-                   p.palette != VIDEO_PALETTE_YUV420 &&
-                   p.palette != VIDEO_PALETTE_YUV422P)
+               if (!ov511_get_depth(p.palette))
                        return -EINVAL;
                        
                if (ov7610_set_picture(ov511, &p))
@@ -2344,11 +2417,11 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
        {
                struct video_window vw;
 
+               memset(&vw, 0, sizeof(vw));
                vw.x = 0;               /* FIXME */
                vw.y = 0;
                vw.width = ov511->frame[0].width;
                vw.height = ov511->frame[0].height;
-               vw.chromakey = 0;
                vw.flags = 30;
 
                PDEBUG (4, "VIDIOCGWIN: %dx%d", vw.width, vw.height);
@@ -2361,12 +2434,16 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
        case VIDIOCGMBUF:
        {
                struct video_mbuf vm;
+               int i;
 
                memset(&vm, 0, sizeof(vm));
                vm.size = OV511_NUMFRAMES * MAX_DATA_SIZE;
                vm.frames = OV511_NUMFRAMES;
                vm.offsets[0] = 0;
-               vm.offsets[1] = MAX_FRAME_SIZE + sizeof (struct timeval);
+               for (i = 1; i < OV511_NUMFRAMES; i++) {
+                       vm.offsets[i] = vm.offsets[i-1] + MAX_FRAME_SIZE
+                               + sizeof (struct timeval);
+               }
 
                if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
                        return -EFAULT;
@@ -2376,7 +2453,7 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
        case VIDIOCMCAPTURE:
        {
                struct video_mmap vm;
-               int ret;
+               int ret, depth;
 
                if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))
                        return -EFAULT;
@@ -2385,19 +2462,26 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
                PDEBUG(4, "frame: %d, size: %dx%d, format: %d",
                        vm.frame, vm.width, vm.height, vm.format);
 
-               if (vm.format != VIDEO_PALETTE_RGB24 &&
-                   vm.format != VIDEO_PALETTE_YUV422 &&
-                   vm.format != VIDEO_PALETTE_YUYV &&
-                   vm.format != VIDEO_PALETTE_YUV420 &&
-                   vm.format != VIDEO_PALETTE_YUV422P &&
-                   vm.format != VIDEO_PALETTE_GREY)
+               depth = ov511_get_depth(vm.format);
+               if (!depth) {
+                       err("VIDIOCMCAPTURE: invalid format (%d)", vm.format);
                        return -EINVAL;
+               }
 
-               if ((vm.frame != 0) && (vm.frame != 1))
+               if ((vm.frame != 0) && (vm.frame != 1)) {
+                       err("VIDIOCMCAPTURE: invalid frame (%d)", vm.frame);
                        return -EINVAL;
-                               
-               if (vm.width > ov511->maxwidth || vm.height > ov511->maxheight)
+               }
+
+               if ((unsigned)vm.frame >= OV511_NUMFRAMES) {
+                       err("VIDIOCMCAPTURE: invalid frame (%d)", vm.frame);
+                       return -EINVAL;
+               }
+
+               if (vm.width > ov511->maxwidth || vm.height > ov511->maxheight) {
+                       err("VIDIOCMCAPTURE: requested dimensions too big");
                        return -EINVAL;
+               }
 
                if (ov511->frame[vm.frame].grabstate == FRAME_GRABBING)
                        return -EBUSY;
@@ -2425,7 +2509,7 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
                ov511->frame[vm.frame].format = vm.format;
                ov511->frame[vm.frame].sub_flag = ov511->sub_flag;
                ov511->frame[vm.frame].segsize = GET_SEGSIZE(vm.format);
-               ov511->frame[vm.frame].depth = GET_DEPTH(vm.format);
+               ov511->frame[vm.frame].depth = depth;
 
                /* Mark it as ready */
                ov511->frame[vm.frame].grabstate = FRAME_READY;
@@ -2439,6 +2523,11 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
                if (copy_from_user((void *)&frame, arg, sizeof(int)))
                        return -EFAULT;
 
+               if ((unsigned)frame >= OV511_NUMFRAMES) {
+                       err("VIDIOCSYNC: invalid frame (%d)", frame);
+                       return -EINVAL;
+               }
+
                PDEBUG(4, "syncing to frame %d, grabstate = %d", frame,
                       ov511->frame[frame].grabstate);
 
@@ -2484,6 +2573,13 @@ redo:
                                goto redo;
                        }                       
                case FRAME_DONE:
+                       if (ov511->snap_enabled && !ov511->frame[frame].snapshot) {
+                               int ret;
+                               if ((ret = ov511_new_frame(ov511, frame)) < 0)
+                                       return ret;
+                               goto redo;
+                       }
+
                        ov511->frame[frame].grabstate = FRAME_UNUSED;
 
                        /* Reset the hardware snapshot button */
@@ -2660,7 +2756,7 @@ static int ov511_mmap(struct video_device *dev, const char *adr,
 
        PDEBUG(4, "mmap: %ld (%lX) bytes", size, size);
 
-       if (size > (((2 * MAX_DATA_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
+       if (size > (((OV511_NUMFRAMES * MAX_DATA_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
                return -EINVAL;
 
        pos = (unsigned long)ov511->fbuf;
@@ -3171,7 +3267,7 @@ static void* ov511_probe(struct usb_device *dev, unsigned int ifnum)
                return NULL;
 
        /* Checking vendor/product should be enough, but what the hell */
-       if (interface->bInterfaceClass != 0xFF) 
+       if (interface->bInterfaceClass != 0xFF)
                return NULL;
        if (interface->bInterfaceSubClass != 0x00)
                return NULL;
@@ -3266,7 +3362,8 @@ error:
 }
 
 
-static void ov511_disconnect(struct usb_device *dev, void *ptr)
+static void
+ov511_disconnect(struct usb_device *dev, void *ptr)
 {
        struct usb_ov511 *ov511 = (struct usb_ov511 *) ptr;
        int n;
@@ -3324,10 +3421,9 @@ static void ov511_disconnect(struct usb_device *dev, void *ptr)
 }
 
 static struct usb_driver ov511_driver = {
-       "ov511",
-       ov511_probe,
-       ov511_disconnect,
-       { NULL, NULL }
+       name:           "ov511",
+       probe:          ov511_probe,
+       disconnect:     ov511_disconnect
 };
 
 
@@ -3346,7 +3442,8 @@ static int __init usb_ov511_init(void)
        if (usb_register(&ov511_driver) < 0)
                return -1;
 
-       info("ov511 driver version %s registered", version);
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
 
        return 0;
 }
index 635780888b4a2f8b26538c0d573958affecdff3e..3de5fc28171650f5af78aeeaa5b11ddf486e62d4 100644 (file)
 
 #include "rio500_usb.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#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 */
@@ -121,16 +128,21 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
                data = (void *) arg;
                if (data == NULL)
                        break;
-               if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand)))
-                       return -EFAULT;
-               if (rio_cmd.length > PAGE_SIZE)
-                       return -EINVAL;
+               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)
                        return -ENOMEM;
                if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) {
+                       retval = -EFAULT;
                        free_page((unsigned long) buffer);
-                       return -EFAULT;
+                       goto err_out;
                }
 
                requesttype = rio_cmd.requesttype | USB_DIR_IN |
@@ -466,8 +478,7 @@ file_operations usb_rio_fops = {
        release:        close_rio,
 };
 
-static struct
-usb_driver rio_driver = {
+static struct usb_driver rio_driver = {
        name:           "rio500",
        probe:          probe_rio,
        disconnect:     disconnect_rio,
@@ -481,6 +492,9 @@ int usb_rio_init(void)
                return -1;
 
        info("USB Rio support registered.");
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
+
        return 0;
 }
 
@@ -498,5 +512,6 @@ void usb_rio_cleanup(void)
 module_init(usb_rio_init);
 module_exit(usb_rio_cleanup);
 
-MODULE_AUTHOR("Cesar Miquel <miquel@df.uba.ar>");
-MODULE_DESCRIPTION("USB Rio 500 driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
index 8dbf577e1afc069f67980dbf6a517373487cc81a..2777f706b49572e4e75814dd636c95149af4fe44 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- linux-c -*- */
 
 /* 
- * Driver for USB Scanners (linux-2.4.0test1-ac7)
+ * Driver for USB Scanners (linux-2.4.0)
  *
  * Copyright (C) 1999, 2000 David E. Nelson
  *
  *    - 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>.
  *
  *  TODO
  *
  */ 
 #include "scanner.h"
 
+
 static void
 irq_scanner(struct urb *urb)
 {
@@ -266,13 +295,18 @@ open_scanner(struct inode * inode, struct file * file)
 
        kdev_t scn_minor;
 
+       int err=0;
+
+       lock_kernel();
+
        scn_minor = USB_SCN_MINOR(inode);
 
        dbg("open_scanner: scn_minor:%d", scn_minor);
 
        if (!p_scn_table[scn_minor]) {
                err("open_scanner(%d): Unable to access minor data", scn_minor);
-               return -ENODEV;
+               err = -ENODEV;
+               goto out_error;
        }
 
        scn = p_scn_table[scn_minor];
@@ -281,17 +315,20 @@ open_scanner(struct inode * inode, struct file * file)
 
        if (!dev) {
                err("open_scanner(%d): Scanner device not present", scn_minor);
-               return -ENODEV;
+               err = -ENODEV;
+               goto out_error;
        }
 
        if (!scn->present) {
                err("open_scanner(%d): Scanner is not present", scn_minor);
-               return -ENODEV;
+               err = -ENODEV;
+               goto out_error;
        }
 
        if (scn->isopen) {
                err("open_scanner(%d): Scanner device is already open", scn_minor);
-               return -EBUSY;
+               err = -EBUSY;
+               goto out_error;
        }
 
        init_waitqueue_head(&scn->rd_wait_q);
@@ -302,7 +339,11 @@ open_scanner(struct inode * inode, struct file * file)
 
        MOD_INC_USE_COUNT;
 
-       return 0;
+out_error:
+
+       unlock_kernel();
+
+       return err;
 }
 
 static int
@@ -338,7 +379,7 @@ write_scanner(struct file * file, const char * buffer,
 {
        struct scn_usb_data *scn;
        struct usb_device *dev;
-       
+
        ssize_t bytes_written = 0; /* Overall count of bytes written */
        ssize_t ret = 0;
 
@@ -347,7 +388,7 @@ write_scanner(struct file * file, const char * buffer,
        int this_write;         /* Number of bytes to write */
        int partial;            /* Number of bytes successfully written */
        int result = 0;
-       
+
        char *obuf;
 
        scn = file->private_data;
@@ -360,6 +401,8 @@ write_scanner(struct file * file, const char * buffer,
 
        file->f_dentry->d_inode->i_atime = CURRENT_TIME;
 
+       down(&(scn->gen_lock));
+
        while (count > 0) {
 
                if (signal_pending(current)) {
@@ -368,7 +411,7 @@ write_scanner(struct file * file, const char * buffer,
                }
 
                this_write = (count >= OBUF_SIZE) ? OBUF_SIZE : count;
-               
+
                if (copy_from_user(scn->obuf, buffer, this_write)) {
                        ret = -EFAULT;
                        break;
@@ -377,15 +420,15 @@ write_scanner(struct file * file, const char * buffer,
                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 == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */
+               if (result == -ETIMEDOUT) {     /* NAK -- shouldn't happen */
                        warn("write_scanner: NAK received.");
-                       ret = -ETIME;
+                       ret = result;
                        break;
                } else if (result < 0) { /* We should not get any I/O errors */
                        warn("write_scanner(%d): funky result: %d. Please notify the maintainer.", scn_minor, result);
                        ret = -EIO;
                        break;
-               } 
+               }
 
 #ifdef WR_DATA_DUMP
                if (partial) {
@@ -412,6 +455,7 @@ write_scanner(struct file * file, const char * buffer,
                        break;
                }
        }
+       up(&(scn->gen_lock));
        mdelay(5);              /* This seems to help with SANE queries */
        return ret ? ret : bytes_written;
 }
@@ -450,6 +494,7 @@ read_scanner(struct file * file, char * buffer,
                                                             atime of
                                                             the device
                                                             node */
+       down(&(scn->gen_lock));
 
        while (count > 0) {
                if (signal_pending(current)) {
@@ -458,11 +503,11 @@ read_scanner(struct file * file, char * buffer,
                }
 
                this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
-               
-               result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, scn->bulk_in_ep), ibuf, this_read, &partial, RD_NAK_TIMEOUT);
+
+               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
@@ -473,26 +518,38 @@ read_scanner(struct file * file, char * buffer,
  * 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. 
+ * Ctrl-C's are acted upon in a reasonable amount of time.
  */
 
-               if (result == USB_ST_TIMEOUT && !partial) { /* Timeout
-                                                               and no
-                                                               data */
-                       if (--rd_expire <= 0) {
-                               warn("read_scanner(%d): excessive NAK's received", scn_minor);
-                               ret = -ETIME;
-                               break;
-                       } else {
-                               interruptible_sleep_on_timeout(&scn->rd_wait_q, RD_NAK_TIMEOUT);
-                               continue;
+               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 != USB_ST_DATAUNDERRUN)) {
                        warn("read_scanner(%d): funky result:%d. Please notify the maintainer.", scn_minor, (int)result);
                        ret = -EIO;
                        break;
                }
 
+       data_recvd:
+
 #ifdef RD_DATA_DUMP
                if (partial) {
                        unsigned char cnt, cnt_max;
@@ -518,7 +575,8 @@ read_scanner(struct file * file, char * buffer,
                        break;
                }
        }
-       
+       up(&(scn->gen_lock));
+
        return ret ? ret : bytes_read;
 }
 
@@ -528,7 +586,7 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum)
        struct scn_usb_data *scn;
        struct usb_interface_descriptor *interface;
        struct usb_endpoint_descriptor *endpoint;
-       
+
        int ep_cnt;
        int ix;
 
@@ -550,7 +608,7 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum)
  * 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
@@ -577,7 +635,7 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum)
            dev->descriptor.idProduct == product) { /* User specified */
                valid_device = 1;
        }
-       
+
         if (!valid_device)
                 return NULL;    /* We didn't find anything pleasing */
 
@@ -599,7 +657,7 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum)
        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...
@@ -622,7 +680,7 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum)
                        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;
@@ -665,7 +723,7 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum)
        }
 
 
-/* 
+/*
  * 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
@@ -695,7 +753,7 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum)
 /* 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, 
+               FILL_INT_URB(&scn->scn_irq, dev,
                             usb_rcvintpipe(dev, have_intr),
                             &scn->button, 1, irq_scanner, scn,
                             // endpoint[(int)have_intr].bInterval);
@@ -724,6 +782,26 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum)
                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;
@@ -733,6 +811,8 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum)
        scn->scn_minor = scn_minor;
        scn->isopen = 0;
 
+       init_MUTEX(&(scn->gen_lock));
+
        return p_scn_table[scn_minor] = scn;
 }
 
@@ -740,7 +820,7 @@ static void
 disconnect_scanner(struct usb_device *dev, void *ptr)
 {
        struct scn_usb_data *scn = (struct scn_usb_data *) ptr;
-       
+
        if(scn->intr_ep) {
                dbg("disconnect_scanner(%d): Unlinking IRQ URB", scn->scn_minor);
                usb_unlink_urb(&scn->scn_irq);
@@ -762,11 +842,11 @@ ioctl_scanner(struct inode *inode, struct file *file,
              unsigned int cmd, unsigned long arg)
 {
        struct usb_device *dev;
-       
+
        int result;
 
        kdev_t scn_minor;
-       
+
        scn_minor = USB_SCN_MINOR(inode);
 
        if (!p_scn_table[scn_minor]) {
@@ -775,7 +855,7 @@ ioctl_scanner(struct inode *inode, struct file *file,
        }
 
        dev = p_scn_table[scn_minor]->scn_dev;
-       
+
        switch (cmd)
        {
        case PV8630_IOCTL_INREQUEST :
@@ -786,10 +866,10 @@ ioctl_scanner(struct inode *inode, struct file *file,
                        __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,
@@ -802,7 +882,7 @@ ioctl_scanner(struct inode *inode, struct file *file,
                        return -EFAULT;
 
                dbg("ioctl_scanner(%d): inreq: result:%d\n", scn_minor, result);
-               
+
                return result;
        }
        case PV8630_IOCTL_OUTREQUEST :
@@ -812,10 +892,10 @@ ioctl_scanner(struct inode *inode, struct file *file,
                        __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),
@@ -825,7 +905,7 @@ ioctl_scanner(struct inode *inode, struct file *file,
                                         0, HZ*5);
 
                dbg("ioctl_scanner(%d): outreq: result:%d\n", scn_minor, result);
-               
+
                return result;
        }
        default:
@@ -848,12 +928,11 @@ file_operations usb_scanner_fops = {
 
 static struct
 usb_driver scanner_driver = {
-       "usbscanner",
-       probe_scanner,
-       disconnect_scanner,
-       { NULL, NULL },
-       &usb_scanner_fops,
-       SCN_BASE_MNR
+       name:           "usbscanner",
+       probe:          probe_scanner,
+       disconnect:     disconnect_scanner,
+       fops:           &usb_scanner_fops,
+       minor:          SCN_BASE_MNR,
 };
 
 void __exit
index f62690f0653c38b38dac6e5b3be4455cb1861266..ed0ff80ed610e220f04059953cfc221b7efb029a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Driver for USB Scanners (linux-2.4.0test1-ac7)
+ * Driver for USB Scanners (linux-2.4.0)
  *
  * Copyright (C) 1999, 2000 David E. Nelson
  *
 #include <linux/delay.h>
 #include <linux/ioctl.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 
 // #define DEBUG
 
 #include <linux/usb.h>
 
-static __s32 vendor=-1, product=-1;
+static __s32 vendor=-1, product=-1, read_timeout=0;
 
 MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson");
 MODULE_DESCRIPTION("USB Scanner Driver");
@@ -46,6 +47,9 @@ 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");
+
 
 /* Enable to activate the ioctl interface.  This is mainly meant for */
 /* development purposes until an ioctl number is officially registered */
@@ -72,7 +76,7 @@ MODULE_PARM_DESC(product, "User specified USB idProduct");
 #define OBUF_SIZE 4096
 
 /* read_scanner timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
-#define RD_NAK_TIMEOUT (10*HZ) /* Number of X seconds to wait */
+#define RD_NAK_TIMEOUT (10*HZ) /* Default number of X seconds to wait */
 #define RD_EXPIRE 12           /* Number of attempts to wait X seconds */
 
 
@@ -89,11 +93,13 @@ struct scn_usb_data {
        unsigned int ifnum;     /* Interface number of the USB device */
        kdev_t scn_minor;       /* Scanner minor - used in disconnect() */
        unsigned char button;   /* Front panel buffer */
-        char isopen;           /* Not zero if the device is open */
+       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 gen_lock; /* lock to prevent concurrent reads or writes */
+       unsigned int rd_nak_timeout; /* Seconds to wait before read() timeout. */
 };
 
 static struct scn_usb_data *p_scn_table[SCN_MAX_MNR] = { NULL, /* ... */};
@@ -106,8 +112,10 @@ static const struct scanner_device {
        /* Acer */
                { 0x04a5, 0x2060 },     /* Prisa Acerscan 620U & 640U (!) */
                { 0x04a5, 0x2040 },     /* Prisa AcerScan 620U (!) */
+               { 0x04a5, 0x2022 },     /* Vuego Scan Brisa 340U */
        /* Agfa */
                { 0x06bd, 0x0001 },     /* SnapScan 1212U */
+               { 0x06bd, 0x0002 },     /* SnapScan 1236U */
                { 0x06bd, 0x2061 },     /* Another SnapScan 1212U (?) */
                { 0x06bd, 0x0100 },     /* SnapScan Touch */
        /* Colorado -- See Primax/Colorado below */
@@ -120,20 +128,28 @@ static const struct scanner_device {
                { 0x03f0, 0x0105 },     /* 4200C */
                { 0x03f0, 0x0102 },     /* PhotoSmart S20 */
                { 0x03f0, 0x0401 },     /* 5200C */
+       //      { 0x03f0, 0x0701 },     /* 5300C - NOT SUPPORTED - see http://www.neatech.nl/oss/HP5300C/ */
                { 0x03f0, 0x0201 },     /* 6200C */
                { 0x03f0, 0x0601 },     /* 6300C */
        /* iVina */
                { 0x0638, 0x0268 },     /* 1200U */
-       /* Microtek */
-               { 0x05da, 0x0099 },     /* ScanMaker X6 - X6U */
-               { 0x05da, 0x0094 },     /* Phantom 336CX - C3 */
-               { 0x05da, 0x00a0 },     /* Phantom 336CX - C3 #2 */
-               { 0x05da, 0x009a },     /* Phantom C6 */
-               { 0x05da, 0x00a3 },     /* ScanMaker V6USL */
-               { 0x05da, 0x80a3 },     /* ScanMaker V6USL #2 */
-               { 0x05da, 0x80ac },     /* ScanMaker V6UL - SpicyU */
+       /* Microtek No longer supported - Enable SCSI and USB Microtek in kernel config */
+       //      { 0x05da, 0x0099 },     /* ScanMaker X6 - X6U */
+       //      { 0x05da, 0x0094 },     /* Phantom 336CX - C3 */
+       //      { 0x05da, 0x00a0 },     /* Phantom 336CX - C3 #2 */
+       //      { 0x05da, 0x009a },     /* Phantom C6 */
+       //      { 0x05da, 0x00a3 },     /* ScanMaker V6USL */
+       //      { 0x05da, 0x80a3 },     /* ScanMaker V6USL #2 */
+       //      { 0x05da, 0x80ac },     /* ScanMaker V6UL - SpicyU */
        /* Mustek */
                { 0x055f, 0x0001 },     /* 1200 CU */
+               { 0x0400, 0x1000 },     /* BearPaw 1200 */
+               { 0x055f, 0x0002 },     /* 600 CU */
+               { 0x055f, 0x0003 },     /* 1200 USB */
+               { 0x055f, 0x0006 },     /* 1200 UB */
+               { 0x0400, 0x1001 },     /* BearPaw 2400 */
+               { 0x055f, 0x0008 },     /* 1200 CU Plus */
+               { 0x0ff5, 0x0010 },     /* BearPaw 1200F */
        /* Primax/Colorado */
                { 0x0461, 0x0300 },     /* G2-300 #1 */
                { 0x0461, 0x0380 },     /* G2-600 #1 */
@@ -151,7 +167,11 @@ static const struct scanner_device {
                { 0x04b8, 0x0101 },     /* Perfection 636U and 636Photo */
                { 0x04b8, 0x0103 },     /* Perfection 610 */
                { 0x04b8, 0x0104 },     /* Perfection 1200U and 1200Photo */
+               { 0x04b8, 0x0106 },     /* Stylus Scan 2500 */
+               { 0x04b8, 0x0107 },     /* Expression 1600 */
+               { 0x04b8, 0x010a },     /* Perfection 1640SU and 1640SU Photo */
                { 0x04b8, 0x010b },     /* Perfection 1240U and 1240Photo */
+               { 0x04b8, 0x010c },     /* Perfection 640U */
        /* Umax */
                { 0x1606, 0x0010 },     /* Astra 1220U */
                { 0x1606, 0x0002 },     /* Astra 1236U */
@@ -161,6 +181,10 @@ static const struct scanner_device {
                { 0x04a7, 0x0221 },     /* OneTouch 5300 */
                { 0x04a7, 0x0221 },     /* OneTouch 7600 duplicate ID (!) */
                { 0x04a7, 0x0231 },     /* 6100 */
+               { 0x04a7, 0x0211 },     /* OneTouch 7600 USB */
+               { 0x04a7, 0x0311 },     /* 6200 EPP/USB */
+               { 0x04a7, 0x0321 },     /* OneTouch 8100 EPP/USB */
+               { 0x04a7, 0x0331 },     /* OneTouch 8600 EPP/USB */
 };
 
 /* Forward declarations */
index e4e1682691780ab51b20c9edd595bdf055b6adae..2b91d038e3aefb8f70f86895262bb9832475b584 100644 (file)
@@ -6,7 +6,9 @@ comment 'USB Serial Converter support'
 
 tristate 'USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
 if [ "$CONFIG_USB_SERIAL" != "n" ]; then
-  bool '  USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG
+  if [ "$CONFIG_USB_SERIAL" = "y" ]; then
+     bool '  USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG
+  fi
   bool '  USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC
   dep_tristate '  USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
   dep_tristate '  USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
@@ -14,9 +16,10 @@ if [ "$CONFIG_USB_SERIAL" != "n" ]; then
   dep_tristate '  USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
   dep_tristate '  USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
   dep_tristate '  USB Handspring Visor Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
+  dep_tristate '  USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
   dep_tristate '  USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
   dep_tristate '  USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  if [ "$CONFIG_USB_SERIAL_KEYSPAN" = "y" -o "$CONFIG_USB_SERIAL_KEYSPAN" = "m" ]; then
+  if [ "$CONFIG_USB_SERIAL_KEYSPAN" != "n" ]; then
      bool '    USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28
      bool '    USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X
      bool '    USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19
@@ -24,6 +27,7 @@ if [ "$CONFIG_USB_SERIAL" != "n" ]; then
      bool '    USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W
      bool '    USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W
   fi
+  dep_tristate '  USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
   dep_tristate '  USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 fi
 
index 97481d2ae726457ade359eaa95eeb82489bc35b1..2cdc73eb822b3345c683fcc6292fee04e5bb9536 100644 (file)
@@ -24,6 +24,8 @@ obj-$(CONFIG_USB_SERIAL_OMNINET)              += omninet.o
 obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT)       += digi_acceleport.o
 obj-$(CONFIG_USB_SERIAL_BELKIN)                        += belkin_sa.o
 obj-$(CONFIG_USB_SERIAL_EMPEG)                 += empeg.o
+obj-$(CONFIG_USB_SERIAL_MCT_U232)              += mct_u232.o
+obj-$(CONFIG_USB_SERIAL_EDGEPORT)              += io_edgeport.o
  
 # Objects that export symbols.
 export-objs    := usbserial.o
index c56dbf624c5b70e26b04079bba623a735bf117be..dcd9e557cf24968f540f1260e2f4bd4641fc3d23 100644 (file)
  *    framework in, but haven't analyzed the "tty_flip" interface yet.
  * -- Add support for flush commands
  * -- Add everything that is missing :)
+ * 
+ * 08-Apr-2001 gb
+ *     - Identify version on module load.
  *
- * (11/06/2000) gkh
+ * 12-Mar-2001 gkh
+ *     - Added support for the GoHubs GO-COM232 device which is the same as the
+ *       Peracom device.
+ *
+ * 06-Nov-2000 gkh
  *     - Added support for the old Belkin and Peracom devices.
  *     - Made the port able to be opened multiple times.
  *     - Added some defaults incase the line settings are things these devices
 #include <linux/init.h>
 #include <linux/malloc.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/usb.h>
 
 #ifdef CONFIG_USB_SERIAL_DEBUG
-       #define DEBUG
+       static int debug = 1;
 #else
-       #undef DEBUG
+       static int debug;
 #endif
-#include <linux/usb.h>
 
 #include "usb-serial.h"
 #include "belkin_sa.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
+#define DRIVER_DESC "USB Belkin Serial converter driver"
+
 /* function prototypes for a Belkin USB Serial Adapter F5U103 */
 static int  belkin_sa_startup          (struct usb_serial *serial);
 static void belkin_sa_shutdown         (struct usb_serial *serial);
@@ -158,6 +172,30 @@ struct usb_serial_device_type peracom_device = {
        shutdown:               belkin_sa_shutdown,
 };
 
+/* the GoHubs Go-COM232 device is the same as the Peracom single port adapter */
+static __u16   gocom232_vendor_id      = PERACOM_VID;
+static __u16   gocom232_product_id     = PERACOM_PID;
+struct usb_serial_device_type gocom232_device = {
+       name:                   "GO-COM232 USB Serial Converter",
+       idVendor:               &gocom232_vendor_id,            /* the Go-COM232 vendor ID */
+       idProduct:              &gocom232_product_id,           /* the Go-COM232 product id */
+       needs_interrupt_in:     MUST_HAVE,                      /* this device must have an interrupt in endpoint */
+       needs_bulk_in:          MUST_HAVE,                      /* this device must have a bulk in endpoint */
+       needs_bulk_out:         MUST_HAVE,                      /* this device must have a bulk out endpoint */
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              1,
+       open:                   belkin_sa_open,
+       close:                  belkin_sa_close,
+       read_int_callback:      belkin_sa_read_int_callback,    /* How we get the status info */
+       ioctl:                  belkin_sa_ioctl,
+       set_termios:            belkin_sa_set_termios,
+       break_ctl:              belkin_sa_break_ctl,
+       startup:                belkin_sa_startup,
+       shutdown:               belkin_sa_shutdown,
+};
+
 
 struct belkin_sa_private {
        unsigned long           control_state;
@@ -217,8 +255,8 @@ static void belkin_sa_shutdown (struct usb_serial *serial)
                        belkin_sa_close (&serial->port[i], NULL);
                }
                /* My special items, the standard routines free my urbs */
-               if (serial->port->private)
-                       kfree(serial->port->private);
+               if (serial->port[i].private)
+                       kfree(serial->port[i].private);
        }
 }
 
@@ -284,7 +322,6 @@ static void belkin_sa_read_int_callback (struct urb *urb)
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct belkin_sa_private *priv = (struct belkin_sa_private *)port->private;
        struct usb_serial *serial;
-       struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
 
        /* the urb might have been killed. */
@@ -360,7 +397,7 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios
        unsigned int cflag = port->tty->termios->c_cflag;
        unsigned int old_iflag = old_termios->c_iflag;
        unsigned int old_cflag = old_termios->c_cflag;
-       __u16 urb_value; /* Will hold the new flags */
+       __u16 urb_value = 0; /* Will hold the new flags */
        
        /* Set the baud rate */
        if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
@@ -543,6 +580,9 @@ static int __init belkin_sa_init (void)
        usb_serial_register (&belkin_sa_device);
        usb_serial_register (&belkin_old_device);
        usb_serial_register (&peracom_device);
+       usb_serial_register (&gocom232_device);
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
        return 0;
 }
 
@@ -552,10 +592,16 @@ static void __exit belkin_sa_exit (void)
        usb_serial_deregister (&belkin_sa_device);
        usb_serial_deregister (&belkin_old_device);
        usb_serial_deregister (&peracom_device);
+       usb_serial_deregister (&gocom232_device);
 }
 
 
 module_init (belkin_sa_init);
-module_exit(belkin_sa_exit);
+module_exit (belkin_sa_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
 
-MODULE_DESCRIPTION("USB Belkin Serial converter driver");
index ee36038634daf2558e1309b02419735adf8e92a9..daf51f7ece298bf51dafa29dc83a23bb3429d2a5 100644 (file)
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
- * (11/06/2000) gkh
+ * 12-Mar-2001 gkh
+ *     Added GoHubs GO-COM232 device id.
+ *
+ * 06-Nov-2000 gkh
  *     Added old Belkin and Peracom device ids, which this driver supports
  *
  * 12-Oct-2000 William Greathouse
@@ -39,6 +42,9 @@
 #define PERACOM_VID    0x0565  /* Peracom's vendor id */
 #define PERACOM_PID    0x0001  /* Peracom's single port serial converter's id */
 
+#define GOHUBS_VID     0x0921  /* GoHubs vendor id */
+#define GOHUBS_PID     0x1000  /* GoHubs single port serial converter's id (identical to the Peracom device) */
+
 /* Vendor Request Interface */
 #define BELKIN_SA_SET_BAUDRATE_REQUEST 0  /* Set baud rate */
 #define BELKIN_SA_SET_STOP_BITS_REQUEST        1  /* Set stop bits (1,2) */
index 5d0ac544ce238901de67b1587ea3c0c8e6dc31eb..8860180b84fd9ed810e5700c6aba268930342c7a 100644 (file)
@@ -13,6 +13,9 @@
 *
 *  Peter Berger (pberger@brimson.com)
 *  Al Borchers (borchers@steinerpoint.com)
+* 
+* (04/08/2001) gb
+*      Identify version on module load.
 *
 * (11/01/2000) pberger and borchers
 *    -- Turned off the USB_DISABLE_SPD flag for write bulk urbs--it caused
 #include <linux/init.h>
 #include <linux/malloc.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/tqueue.h>
+#include <linux/usb.h>
 
 #ifdef CONFIG_USB_SERIAL_DEBUG
-       #define DEBUG
+       static int debug = 1;
 #else
-       #undef DEBUG
+       static int debug;
 #endif
 
-#include <linux/usb.h>
 #include "usb-serial.h"
 
 
 /* Defines */
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.80.1.2"
+#define DRIVER_AUTHOR "Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>"
+#define DRIVER_DESC "Digi AccelePort USB-2/USB-4 Serial Converter driver"
+
 /* port output buffer length -- must be <= transfer buffer length - 2 */
 /* so we can be sure to send the full buffer in one urb */
 #define DIGI_OUT_BUF_SIZE              8
@@ -585,7 +595,7 @@ static void digi_wakeup_write_lock( struct usb_serial_port *port )
        spin_lock_irqsave( &priv->dp_port_lock, flags );
        digi_wakeup_write( port );
        spin_unlock_irqrestore( &priv->dp_port_lock, flags );
-
+       MOD_DEC_USE_COUNT;
 }
 
 static void digi_wakeup_write( struct usb_serial_port *port )
@@ -1266,12 +1276,10 @@ priv->dp_port_num, count, from_user, in_interrupt() );
        || priv->dp_write_urb_in_use ) {
 
                /* buffer data if count is 1 (probably put_char) if possible */
-               if( count == 1 ) {
-                       new_len = MIN( count,
-                               DIGI_OUT_BUF_SIZE-priv->dp_out_buf_len );
-                       memcpy( priv->dp_out_buf+priv->dp_out_buf_len, buf,
-                               new_len );
-                       priv->dp_out_buf_len += new_len;
+               if( count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE ) {
+                       priv->dp_out_buf[priv->dp_out_buf_len++]
+                               = *(from_user ? user_buf : buf);
+                       new_len = 1;
                } else {
                        new_len = 0;
                }
@@ -1393,7 +1401,9 @@ dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status );
 
        /* also queue up a wakeup at scheduler time, in case we */
        /* lost the race in write_chan(). */
-       queue_task( &priv->dp_wakeup_task, &tq_scheduler );
+       MOD_INC_USE_COUNT;
+       if (schedule_task(&priv->dp_wakeup_task) == 0)
+               MOD_DEC_USE_COUNT;
 
        spin_unlock( &priv->dp_port_lock );
 
@@ -2052,6 +2062,8 @@ static int __init digi_init (void)
 {
        usb_serial_register (&digi_acceleport_2_device);
        usb_serial_register (&digi_acceleport_4_device);
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
        return 0;
 }
 
@@ -2067,6 +2079,9 @@ module_init(digi_init);
 module_exit(digi_exit);
 
 
-MODULE_AUTHOR("Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>");
-MODULE_DESCRIPTION("Digi AccelePort USB-2/USB-4 Serial Converter driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
 
index 1316c3b3c1631966b42064424635236ca764fa3e..9387c08d1771b7d7806afaca8d68077c877e5212 100644 (file)
@@ -13,6 +13,9 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (04/08/2001) gb
+ *      Identify version on module load.
+ * 
  * (01/22/2001) gb
  *     Added write_room() and chars_in_buffer() support. 
  * 
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/usb.h>
+
 #ifdef CONFIG_USB_SERIAL_DEBUG
-       #define DEBUG
+       static int debug = 1;
 #else
-       #undef DEBUG
+       static int debug;
 #endif
-#include <linux/usb.h>
 
 #include "usb-serial.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Gary Brubaker <xavyer@ix.netcom.com>"
+#define DRIVER_DESC "USB Empeg Mark I/II Driver"
+
 #define EMPEG_VENDOR_ID                        0x084f
 #define EMPEG_PRODUCT_ID               0x0001
 
@@ -665,6 +676,9 @@ static int __init empeg_init (void)
                }
        }
 
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
+
        return 0;
 
 }
@@ -699,5 +713,9 @@ static void __exit empeg_exit (void)
 module_init(empeg_init);
 module_exit(empeg_exit);
 
-MODULE_AUTHOR("Gary Brubaker <xavyer@ix.netcom.com>");
-MODULE_DESCRIPTION("USB Empeg Mark I/II Driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
index d3e8a92d01f6ed5868e0944ee74f791607d3dd2c..6a4083f8737783916b942b44619b16e713badd2d 100644 (file)
  *
  * See http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date testing info
  *     and extra documentation
+ * 
+ * (23/May/2001)   Bill Ryder
+ *     Added runtime debug patch (thanx Tyson D Sawyer).
+ *     Cleaned up comments for 8U232
+ *     Added parity, framing and overrun error handling
+ *     Added receive break handling.
+ * 
+ * (04/08/2001) gb
+ *     Identify version on module load.
  *       
+ * (18/March/2001) Bill Ryder
+ *     (Not released)
+ *     Added send break handling. (requires kernel patch too)
+ *     Fixed 8U232AM hardware RTS/CTS etc status reporting.
+ *     Added flipbuf fix copied from generic device
+ * 
  * (12/3/2000) Bill Ryder
  *     Added support for 8U232AM device.
  *     Moved PID and VIDs into header file only.
 #include <linux/init.h>
 #include <linux/malloc.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/usb.h>
 
 #ifdef CONFIG_USB_SERIAL_DEBUG
-       #define DEBUG
+       static int debug = 1;
 #else
-       #undef DEBUG
+       static int debug;
 #endif
-#include <linux/usb.h>
 
 #include "usb-serial.h"
-
 #include "ftdi_sio.h"
 
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.1.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>"
+#define DRIVER_DESC "USB FTDI RS232 Converters Driver"
+
 
 
 struct ftdi_private {
        ftdi_type_t ftdi_type;
-       char last_status_byte; /* device sends this every 40ms when open */
-       
-       
+       __u16 last_set_data_urb_value ; /* the last data state set - needed for doing a break */
 };
 /* function prototypes for a FTDI serial converter */
 static int  ftdi_sio_startup           (struct usb_serial *serial);
@@ -107,6 +126,10 @@ static void ftdi_sio_write_bulk_callback (struct urb *urb);
 static void ftdi_sio_read_bulk_callback        (struct urb *urb);
 static void ftdi_sio_set_termios       (struct usb_serial_port *port, struct termios * old);
 static int  ftdi_sio_ioctl             (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
+static void ftdi_sio_break_ctl         (struct usb_serial_port *port, int break_state );
+
+/* Should rename most ftdi_sio's to ftdi_ now since there are two devices 
+   which share common code */ 
 
 /* All of the device info needed for the FTDI SIO serial converter */
 static __u16   ftdi_vendor_id          = FTDI_VID;
@@ -130,6 +153,7 @@ struct usb_serial_device_type ftdi_sio_device = {
        write_bulk_callback:    ftdi_sio_write_bulk_callback,
        ioctl:                  ftdi_sio_ioctl,
        set_termios:            ftdi_sio_set_termios,
+       break_ctl:              ftdi_sio_break_ctl,
        startup:                ftdi_sio_startup,
         shutdown:               ftdi_sio_shutdown,
 };
@@ -152,6 +176,7 @@ struct usb_serial_device_type ftdi_8U232AM_device = {
        write_bulk_callback:    ftdi_sio_write_bulk_callback,
        ioctl:                  ftdi_sio_ioctl,
        set_termios:            ftdi_sio_set_termios,
+       break_ctl:              ftdi_sio_break_ctl,
        startup:                ftdi_8U232AM_startup,
         shutdown:               ftdi_sio_shutdown,
 };
@@ -269,7 +294,8 @@ static int  ftdi_sio_open (struct usb_serial_port *port, struct file *filp)
 
                spin_unlock_irqrestore (&port->port_lock, flags);
 
-               /* do not allow a task to be queued to deliver received data */
+               /* This will push the characters through immediately rather 
+                  than queue a task to deliver them */
                port->tty->low_latency = 1;
 
                /* No error checking for this (will get errors later anyway) */
@@ -498,9 +524,9 @@ static void ftdi_sio_write_bulk_callback (struct urb *urb)
 static void ftdi_sio_read_bulk_callback (struct urb *urb)
 { /* ftdi_sio_serial_buld_callback */
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
-       struct ftdi_private *priv = (struct ftdi_private *)port->private;
        struct usb_serial *serial;
                struct tty_struct *tty = port->tty ;
+       char error_flag;
                unsigned char *data = urb->transfer_buffer;
 
        const int data_offset = 2;
@@ -527,23 +553,76 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb)
        if (urb->actual_length > 2) {
                usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
        } else {
-                dbg("Just status");
+                dbg("Just status 0o%03o0o%03o",data[0],data[1]);
         }
 
-       priv->last_status_byte = data[0]; /* this has modem control lines */
 
        /* TO DO -- check for hung up line and handle appropriately: */
        /*   send hangup  */
        /* See acm.c - you do a tty_hangup  - eg tty_hangup(tty) */
        /* if CD is dropped and the line is not CLOCAL then we should hangup */
 
-
+       /* Handle errors and break */
+       error_flag = TTY_NORMAL;
+        /* Although the device uses a bitmask and hence can have multiple */
+        /* errors on a packet - the order here sets the priority the */
+        /* error is returned to the tty layer  */
+       
+       if ( data[1] & FTDI_RS_OE ) { 
+               error_flag = TTY_OVERRUN;
+                dbg("OVERRRUN error");
+       }
+       if ( data[1] & FTDI_RS_BI ) { 
+               error_flag = TTY_BREAK;
+                dbg("BREAK received");
+       }
+       if ( data[1] & FTDI_RS_PE ) { 
+               error_flag = TTY_PARITY;
+                dbg("PARITY error");
+       }
+       if ( data[1] & FTDI_RS_FE ) { 
+               error_flag = TTY_FRAME;
+                dbg("FRAMING error");
+       }
        if (urb->actual_length > data_offset) {
+
                for (i = data_offset ; i < urb->actual_length ; ++i) {
-                       tty_insert_flip_char(tty, data[i], 0);
-               }
+                       /* have to make sure we don't overflow the buffer
+                         with tty_insert_flip_char's */
+                       if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+                               tty_flip_buffer_push(tty);
+                       }
+                       /* Note that the error flag is duplicated for 
+                          every character received since we don't know
+                          which character it applied to */
+                       tty_insert_flip_char(tty, data[i], error_flag);
+               }
                tty_flip_buffer_push(tty);
+
+
+       } 
+
+#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW
+       /* if a parity error is detected you get status packets forever
+          until a character is sent without a parity error.
+          This doesn't work well since the application receives a never
+          ending stream of bad data - even though new data hasn't been sent.
+          Therefore I (bill) have taken this out.
+          However - this might make sense for framing errors and so on 
+          so I am leaving the code in for now.
+       */
+      else {
+               if (error_flag != TTY_NORMAL){
+                       dbg("error_flag is not normal");
+                               /* In this case it is just status - if that is an error send a bad character */
+                               if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+                                       tty_flip_buffer_push(tty);
+                               }
+                               tty_insert_flip_char(tty, 0xff, error_flag);
+                               tty_flip_buffer_push(tty);
+               }
        }
+#endif
 
        /* Continue trying to always read  */
        FILL_BULK_URB(urb, serial->dev, 
@@ -605,6 +684,38 @@ __u16 translate_baudrate_to_ftdi(unsigned int cflag, ftdi_type_t ftdi_type)
        return(urb_value);
 }
 
+static void ftdi_sio_break_ctl( struct usb_serial_port *port, int break_state )
+{
+       struct usb_serial *serial = port->serial;
+       struct ftdi_private *priv = (struct ftdi_private *)port->private;
+       __u16 urb_value = 0; 
+       char buf[1];
+       
+       /* break_state = -1 to turn on break, and 0 to turn off break */
+       /* see drivers/char/tty_io.c to see it used */
+       /* last_set_data_urb_value NEVER has the break bit set in it */
+
+       if (break_state) {
+               urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK;
+       } else {
+               urb_value = priv->last_set_data_urb_value; 
+       }
+
+       
+       if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                           FTDI_SIO_SET_DATA_REQUEST, 
+                           FTDI_SIO_SET_DATA_REQUEST_TYPE,
+                           urb_value , 0,
+                           buf, 0, WDR_TIMEOUT) < 0) {
+               err(__FUNCTION__ " FAILED to enable/disable break state (state was %d)",break_state);
+       }          
+
+       dbg(__FUNCTION__ " break state is %d - urb is %d",break_state, urb_value);
+       
+}
+
+
+
 /* As I understand this - old_termios contains the original termios settings */
 /*  and tty->termios contains the new setting to be used */
 /* */
@@ -648,6 +759,11 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
                        err("CSIZE was set but not CS5-CS8");
                }
        }
+
+       /* This is needed by the break command since it uses the same command - but is
+        *  or'ed with this value  */
+       priv->last_set_data_urb_value = urb_value;
+       
        if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                            FTDI_SIO_SET_DATA_REQUEST, 
                            FTDI_SIO_SET_DATA_REQUEST_TYPE,
@@ -721,7 +837,7 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns
        struct usb_serial *serial = port->serial;
        struct ftdi_private *priv = (struct ftdi_private *)port->private;
        __u16 urb_value=0; /* Will hold the new flags */
-       char buf[1];
+       char buf[2];
        int  ret, mask;
        
        dbg(__FUNCTION__ " cmd 0x%04x", cmd);
@@ -731,12 +847,7 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns
 
        case TIOCMGET:
                dbg(__FUNCTION__ " TIOCMGET");
-               /* The MODEM_STATUS_REQUEST works for the sio but not the 232 */
                if (priv->ftdi_type == sio){
-                       /* TO DECIDE - use the 40ms status packets or not? */
-                       /*   PRO: No need to send urb */
-                       /*   CON: Could be 40ms out of date */
-
                        /* Request the status from the device */
                        if ((ret = usb_control_msg(serial->dev, 
                                                   usb_rcvctrlpipe(serial->dev, 0),
@@ -749,8 +860,18 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns
                                return(ret);
                        }
                } else {
-                       /* This gets updated every 40ms - so just copy it in */
-                       buf[0] = priv->last_status_byte;
+                       /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same 
+                          format as the data returned from the in point */
+                       if ((ret = usb_control_msg(serial->dev, 
+                                                  usb_rcvctrlpipe(serial->dev, 0),
+                                                  FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
+                                                  FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+                                                  0, 0, 
+                                                  buf, 2, WDR_TIMEOUT)) < 0 ) {
+                               err(__FUNCTION__ " Could not get modem status of device - err: %d",
+                                   ret);
+                               return(ret);
+                       }
                }
 
                return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
@@ -841,6 +962,8 @@ static int __init ftdi_sio_init (void)
        dbg(__FUNCTION__);
        usb_serial_register (&ftdi_sio_device);
        usb_serial_register (&ftdi_8U232AM_device);
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
        return 0;
 }
 
@@ -856,5 +979,9 @@ static void __exit ftdi_sio_exit (void)
 module_init(ftdi_sio_init);
 module_exit(ftdi_sio_exit);
 
-MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>");
-MODULE_DESCRIPTION("USB FTDI RS232 converters driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
index 626aeb6773150fcac63768cc645bde9bb033792f..321ae1914799dde80781256c7a1b56856dd45cd9 100644 (file)
@@ -146,7 +146,7 @@ typedef enum {
 #define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11 )
 #define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11 )
 #define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11 )
-
+#define FTDI_SIO_SET_BREAK (0x1 << 14)
 /* FTDI_SIO_SET_DATA */
 
 /*
@@ -170,7 +170,10 @@ typedef enum {
  *           0 = 1
  *           1 = 1.5
  *           2 = 2
- *   B14..15 Reserved
+ *   B14
+ *           1 = TX ON (break)
+ *           0 = TX OFF (normal state)
+ *   B15 Reserved
  *
  */
 
@@ -434,6 +437,17 @@ typedef enum {
  * B6  Transmitter Empty (TEMT)
  * B7  Error in RCVR FIFO
  * 
+ */
+#define FTDI_RS_DR  1
+#define FTDI_RS_OE (1<<1)
+#define FTDI_RS_PE (1<<2)
+#define FTDI_RS_FE (1<<3)
+#define FTDI_RS_BI (1<<4)
+#define FTDI_RS_THRE (1<<5)
+#define FTDI_RS_TEMT (1<<6)
+#define FTDI_RS_FIFO  (1<<7)
+
+/*
  * OUT Endpoint
  * 
  * This device reserves the first bytes of data on this endpoint contain the length
diff --git a/drivers/usb/serial/io_16654.h b/drivers/usb/serial/io_16654.h
new file mode 100644 (file)
index 0000000..b2019d6
--- /dev/null
@@ -0,0 +1,195 @@
+/************************************************************************
+ *
+ *     16654.H         Definitions for 16C654 UART used on EdgePorts
+ *
+ *     Copyright (c) 1998 Inside Out Networks, Inc.
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ ************************************************************************/
+
+#if !defined(_16654_H)
+#define        _16654_H
+
+/************************************************************************
+ *
+ *                     D e f i n e s   /   T y p e d e f s
+ *
+ ************************************************************************/
+
+       //
+       // UART register numbers
+       // Numbers 0-7 are passed to the Edgeport directly. Numbers 8 and
+       // above are used internally to indicate that we must enable access
+       // to them via LCR bit 0x80 or LCR = 0xBF.
+       // The register number sent to the Edgeport is then (x & 0x7).
+       //
+       // Driver must not access registers that affect operation of the
+       // the EdgePort firmware -- that includes THR, RHR, IER, FCR.
+
+
+#define THR                    0       // ! Transmit Holding Register (Write)
+#define RDR                    0       // ! Receive Holding Register (Read)
+#define IER                    1       // ! Interrupt Enable Register
+#define FCR                    2       // ! Fifo Control Register (Write)
+#define ISR                    2       // Interrupt Status Register (Read)
+#define LCR                    3       // Line Control Register
+#define MCR                    4       // Modem Control Register
+#define LSR                    5       // Line Status Register
+#define MSR                    6       // Modem Status Register
+#define SPR                    7       // ScratchPad Register
+#define DLL                    8       // Bank2[ 0 ] Divisor Latch LSB
+#define DLM                    9       // Bank2[ 1 ] Divisor Latch MSB
+#define EFR                    10      // Bank2[ 2 ] Extended Function Register
+//efine unused                 11      // Bank2[ 3 ]
+#define XON1                   12      // Bank2[ 4 ] Xon-1
+#define XON2                   13      // Bank2[ 5 ] Xon-2
+#define XOFF1                  14      // Bank2[ 6 ] Xoff-1
+#define XOFF2                  15      // Bank2[ 7 ] Xoff-2
+
+#define        NUM_16654_REGS          16
+
+#define IS_REG_2ND_BANK(x)     ((x) >= 8)
+
+       //
+       // Bit definitions for each register
+       //
+
+#define IER_RX                 0x01    // Enable receive interrupt
+#define IER_TX                 0x02    // Enable transmit interrupt
+#define IER_RXS                        0x04    // Enable receive status interrupt
+#define IER_MDM                        0x08    // Enable modem status interrupt
+#define IER_SLEEP              0x10    // Enable sleep mode
+#define IER_XOFF               0x20    // Enable s/w flow control (XOFF) interrupt
+#define IER_RTS                        0x40    // Enable RTS interrupt
+#define IER_CTS                        0x80    // Enable CTS interrupt
+#define IER_ENABLE_ALL         0xFF    // Enable all ints
+
+
+#define FCR_FIFO_EN            0x01    // Enable FIFOs
+#define FCR_RXCLR              0x02    // Reset Rx FIFO
+#define FCR_TXCLR              0x04    // Reset Tx FIFO
+#define FCR_DMA_BLK            0x08    // Enable DMA block mode
+#define FCR_TX_LEVEL_MASK      0x30    // Mask for Tx FIFO Level
+#define FCR_TX_LEVEL_8         0x00    // Tx FIFO Level =  8 bytes
+#define FCR_TX_LEVEL_16                0x10    // Tx FIFO Level = 16 bytes
+#define FCR_TX_LEVEL_32                0x20    // Tx FIFO Level = 32 bytes
+#define FCR_TX_LEVEL_56                0x30    // Tx FIFO Level = 56 bytes
+#define FCR_RX_LEVEL_MASK      0xC0    // Mask for Rx FIFO Level
+#define FCR_RX_LEVEL_8         0x00    // Rx FIFO Level =  8 bytes
+#define FCR_RX_LEVEL_16                0x40    // Rx FIFO Level = 16 bytes
+#define FCR_RX_LEVEL_56                0x80    // Rx FIFO Level = 56 bytes
+#define FCR_RX_LEVEL_60                0xC0    // Rx FIFO Level = 60 bytes
+
+
+#define ISR_INT_MDM_STATUS     0x00    // Modem status int pending
+#define ISR_INT_NONE           0x01    // No interrupt pending
+#define ISR_INT_TXRDY          0x02    // Tx ready int pending
+#define ISR_INT_RXRDY          0x04    // Rx ready int pending
+#define ISR_INT_LINE_STATUS    0x06    // Line status int pending
+#define ISR_INT_RX_TIMEOUT     0x0C    // Rx timeout int pending
+#define ISR_INT_RX_XOFF                0x10    // Rx Xoff int pending
+#define ISR_INT_RTS_CTS                0x20    // RTS/CTS change int pending
+#define ISR_FIFO_ENABLED       0xC0    // Bits set if FIFOs enabled
+#define ISR_INT_BITS_MASK      0x3E    // Mask to isolate valid int causes
+
+
+#define LCR_BITS_5             0x00    // 5 bits/char
+#define LCR_BITS_6             0x01    // 6 bits/char
+#define LCR_BITS_7             0x02    // 7 bits/char
+#define LCR_BITS_8             0x03    // 8 bits/char
+#define LCR_BITS_MASK          0x03    // Mask for bits/char field
+
+#define LCR_STOP_1             0x00    // 1 stop bit
+#define LCR_STOP_1_5           0x04    // 1.5 stop bits (if 5   bits/char)
+#define LCR_STOP_2             0x04    // 2 stop bits   (if 6-8 bits/char)
+#define LCR_STOP_MASK          0x04    // Mask for stop bits field
+
+#define LCR_PAR_NONE           0x00    // No parity
+#define LCR_PAR_ODD            0x08    // Odd parity
+#define LCR_PAR_EVEN           0x18    // Even parity
+#define LCR_PAR_MARK           0x28    // Force parity bit to 1
+#define LCR_PAR_SPACE          0x38    // Force parity bit to 0
+#define LCR_PAR_MASK           0x38    // Mask for parity field
+
+#define LCR_SET_BREAK          0x40    // Set Break condition
+#define LCR_DL_ENABLE          0x80    // Enable access to divisor latch
+
+#define LCR_ACCESS_EFR         0xBF    // Load this value to access DLL,DLM,
+                                       // and also the '654-only registers
+                                       // EFR, XON1, XON2, XOFF1, XOFF2
+
+
+#define MCR_DTR                        0x01    // Assert DTR
+#define MCR_RTS                        0x02    // Assert RTS
+#define MCR_OUT1               0x04    // Loopback only: Sets state of RI
+#define MCR_MASTER_IE          0x08    // Enable interrupt outputs
+#define MCR_LOOPBACK           0x10    // Set internal (digital) loopback mode
+#define MCR_XON_ANY            0x20    // Enable any char to exit XOFF mode
+#define MCR_IR_ENABLE          0x40    // Enable IrDA functions
+#define MCR_BRG_DIV_4          0x80    // Divide baud rate clk by /4 instead of /1
+
+
+#define LSR_RX_AVAIL           0x01    // Rx data available
+#define LSR_OVER_ERR           0x02    // Rx overrun
+#define LSR_PAR_ERR            0x04    // Rx parity error
+#define LSR_FRM_ERR            0x08    // Rx framing error
+#define LSR_BREAK              0x10    // Rx break condition detected
+#define LSR_TX_EMPTY           0x20    // Tx Fifo empty
+#define LSR_TX_ALL_EMPTY       0x40    // Tx Fifo and shift register empty
+#define LSR_FIFO_ERR           0x80    // Rx Fifo contains at least 1 erred char
+
+
+#define MSR_DELTA_CTS          0x01    // CTS changed from last read
+#define MSR_DELTA_DSR          0x02    // DSR changed from last read
+#define MSR_DELTA_RI           0x04    // RI  changed from 0 -> 1
+#define MSR_DELTA_CD           0x08    // CD  changed from last read
+#define MSR_CTS                        0x10    // Current state of CTS
+#define MSR_DSR                        0x20    // Current state of DSR
+#define MSR_RI                 0x40    // Current state of RI
+#define MSR_CD                 0x80    // Current state of CD
+
+
+
+                                       //      Tx              Rx
+                                       //-------------------------------
+#define EFR_SWFC_NONE          0x00    //      None            None
+#define EFR_SWFC_RX1           0x02    //      None            XOFF1
+#define EFR_SWFC_RX2           0x01    //      None            XOFF2
+#define EFR_SWFC_RX12          0x03    //      None            XOFF1 & XOFF2
+#define EFR_SWFC_TX1           0x08    //      XOFF1           None
+#define EFR_SWFC_TX1_RX1       0x0a    //      XOFF1           XOFF1
+#define EFR_SWFC_TX1_RX2       0x09    //      XOFF1           XOFF2
+#define EFR_SWFC_TX1_RX12      0x0b    //      XOFF1           XOFF1 & XOFF2
+#define EFR_SWFC_TX2           0x04    //      XOFF2           None
+#define EFR_SWFC_TX2_RX1       0x06    //      XOFF2           XOFF1
+#define EFR_SWFC_TX2_RX2       0x05    //      XOFF2           XOFF2
+#define EFR_SWFC_TX2_RX12      0x07    //      XOFF2           XOFF1 & XOFF2
+#define EFR_SWFC_TX12          0x0c    //      XOFF1 & XOFF2   None
+#define EFR_SWFC_TX12_RX1      0x0e    //      XOFF1 & XOFF2   XOFF1
+#define EFR_SWFC_TX12_RX2      0x0d    //      XOFF1 & XOFF2   XOFF2
+#define EFR_SWFC_TX12_RX12     0x0f    //      XOFF1 & XOFF2   XOFF1 & XOFF2
+
+#define EFR_TX_FC_MASK         0x0c    // Mask to isolate Rx flow control
+#define EFR_TX_FC_NONE         0x00    // No Tx Xon/Xoff flow control
+#define EFR_TX_FC_X1           0x08    // Transmit Xon1/Xoff1
+#define EFR_TX_FC_X2           0x04    // Transmit Xon2/Xoff2
+#define EFR_TX_FC_X1_2         0x0c    // Transmit Xon1&2/Xoff1&2
+
+#define EFR_RX_FC_MASK         0x03    // Mask to isolate Rx flow control
+#define EFR_RX_FC_NONE         0x00    // No Rx Xon/Xoff flow control
+#define EFR_RX_FC_X1           0x02    // Receiver compares Xon1/Xoff1
+#define EFR_RX_FC_X2           0x01    // Receiver compares Xon2/Xoff2
+#define EFR_RX_FC_X1_2         0x03    // Receiver compares Xon1&2/Xoff1&2
+
+
+#define EFR_SWFC_MASK          0x0F    // Mask for software flow control field
+#define EFR_ENABLE_16654       0x10    // Enable 16C654 features
+#define EFR_SPEC_DETECT                0x20    // Enable special character detect interrupt
+#define EFR_AUTO_RTS           0x40    // Use RTS for Rx flow control
+#define EFR_AUTO_CTS           0x80    // Use CTS for Tx flow control
+
+#endif // if !defined(_16654_H)
+
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
new file mode 100644 (file)
index 0000000..abc750b
--- /dev/null
@@ -0,0 +1,3080 @@
+/*
+ * Edgeport USB Serial Converter driver
+ *
+ * Copyright(c) 2000 Inside Out Networks, All rights reserved.
+ * 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.
+ *
+ * Supports the following devices:
+ *     Edgeport/4
+ *     Edgeport/4t
+ *     Edgeport/2
+ *     Edgeport/4i
+ *     Edgeport/2i
+ *     Edgeport/421
+ *     Edgeport/21
+ *     Rapidport/4
+ *     Edgeport/8
+ *     Edgeport/2D8
+ *     Edgeport/4D8
+ *     Edgeport/8i
+ *
+ * Version history:
+ * 
+ *     (04/08/2001) gb
+ *     - Identify version on module load.
+ *
+ * 2.0 2001_03_05 greg kroah-hartman
+ *     - reworked entire driver to fit properly in with the other usb-serial
+ *       drivers.  Occasional oopses still happen, but it's a good start.
+ *
+ * 1.2.3 (02/23/2001) greg kroah-hartman
+ *     - changed device table to work properly for 2.4.x final format.
+ *     - fixed problem with dropping data at high data rates.
+ *
+ * 1.2.2 (11/27/2000) greg kroah-hartman
+ *     - cleaned up more NTisms.
+ *     - Added device table for 2.4.0-test11
+ *
+ * 1.2.1 (11/08/2000) greg kroah-hartman
+ *     - Started to clean up NTisms.
+ *     - Fixed problem with dev field of urb for kernels >= 2.4.0-test9
+ *
+ * 1.2 (10/17/2000) David Iacovelli
+ *     Remove all EPIC code and GPL source
+ *  Fix RELEVANT_IFLAG macro to include flow control 
+ *  changes port configuration changes.
+ *  Fix redefinition of SERIAL_MAGIC
+ *  Change all timeout values to 5 seconds
+ *  Tried to fix the UHCI multiple urb submission, but failed miserably.
+ *  it seems to work fine with OHCI.
+ *  ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must 
+ *    find a way to work arount this UHCI bug )
+ *
+ * 1.1 (10/11/2000) David Iacovelli
+ *  Fix XON/XOFF flow control to support both IXON and IXOFF
+ *
+ * 0.9.27 (06/30/2000) David Iacovelli
+ *  Added transmit queue and now allocate urb for command writes.
+ *
+ * 0.9.26 (06/29/2000) David Iacovelli
+ *  Add support for 80251 based edgeport
+ *
+ * 0.9.25 (06/27/2000) David Iacovelli
+ *  Do not close the port if it has multiple opens.
+ *
+ * 0.9.24 (05/26/2000) David Iacovelli
+ *  Add IOCTLs to support RXTX and JAVA POS 
+ *  and first cut at running BlackBox Demo
+ *
+ * 0.9.23 (05/24/2000) David Iacovelli
+ *  Add IOCTLs to support RXTX and JAVA POS
+ *
+ * 0.9.22 (05/23/2000) David Iacovelli
+ *  fixed bug in enumeration.  If epconfig turns on mapping by
+ *  path after a device is already plugged in, we now update
+ *  the mapping correctly
+ *
+ * 0.9.21 (05/16/2000) David Iacovelli
+ *  Added BlockUntilChaseResp() to also wait for txcredits
+ *  Updated the way we allocate and handle write URBs 
+ *     Add debug code to dump buffers
+ *
+ * 0.9.20 (05/01/2000) David Iacovelli
+ *     change driver to use usb/tts/
+ *
+ * 0.9.19 (05/01/2000) David Iacovelli
+ *  Update code to compile if DEBUG is off
+ *
+ * 0.9.18 (04/28/2000) David Iacovelli
+ *  cleanup and test tty_register with devfs
+ *
+ * 0.9.17 (04/27/2000) greg kroah-hartman
+ *     changed tty_register around to be like the way it
+ *     was before, but now it works properly with devfs.
+ *
+ * 0.9.16 (04/26/2000) david iacovelli
+ *  Fixed bug in GetProductInfo()
+ *
+ * 0.9.15 (04/25/2000) david iacovelli
+ *     Updated enumeration
+ *
+ * 0.9.14 (04/24/2000) david iacovelli
+ *  Removed all config/status IOCTLS and 
+ *  converted to using /proc/edgeport
+ *  still playing with devfs
+ *
+ * 0.9.13 (04/24/2000) david iacovelli
+ *  Removed configuration based on ttyUSB0
+ *  Added support for configuration using /prod/edgeport
+ *  first attempt at using devfs (not working yet!)
+ *  Added IOCTL to GetProductInfo()
+ *  Added support for custom baud rates
+ *     Add support for random port numbers
+ *
+ * 0.9.12 (04/18/2000) david iacovelli
+ *     added additional configuration IOCTLs
+ *  use ttyUSB0 for configuration
+ *
+ * 0.9.11 (04/17/2000) greg kroah-hartman
+ *     fixed module initialization race conditions.
+ *     made all urbs dynamically allocated.
+ *     made driver devfs compatible. now it only registers the tty device
+ *     when the device is actually plugged in.
+ *
+ * 0.9.10 (04/13/2000) greg kroah-hartman
+ *     added proc interface framework.
+ *
+ * 0.9.9 (04/13/2000) david iacovelli
+ *     added enumeration code and ioctls to configure the device
+ *
+ * 0.9.8 (04/12/2000) david iacovelli
+ *  Change interrupt read start when device is plugged in
+ *  and stop when device is removed
+ *     process interrupt reads when all ports are closed 
+ *  (keep value of rxBytesAvail consistent with the edgeport)
+ *  set the USB_BULK_QUEUE flag so that we can shove a bunch 
+ *  of urbs at once down the pipe 
+ *
+ * 0.9.7 (04/10/2000) david iacovelli
+ *     start to add enumeration code.
+ *  generate serial number for epic devices
+ *  add support for kdb
+ *
+ * 0.9.6 (03/30/2000) david iacovelli
+ *  add IOCTL to get string, manufacture, and boot descriptors
+ *
+ * 0.9.5 (03/14/2000) greg kroah-hartman
+ *     more error checking added to SerialOpen to try to fix UHCI open problem
+ *
+ * 0.9.4 (03/09/2000) greg kroah-hartman
+ *     added more error checking to handle oops when data is hanging
+ *     around and tty is abruptly closed.
+ *
+ * 0.9.3 (03/09/2000) david iacovelli
+ *     Add epic support for xon/xoff chars
+ *     play with performance
+ *
+ * 0.9.2 (03/08/2000) greg kroah-hartman
+ *     changed most "info" calls to "dbg"
+ *     implemented flow control properly in the termios call
+ *
+ * 0.9.1 (03/08/2000) david iacovelli
+ *     added EPIC support
+ *     enabled bootloader update
+ *
+ * 0.9 (03/08/2000) greg kroah-hartman
+ *     Release to IO networks.
+ *     Integrated changes that David made
+ *  made getting urbs for writing SMP safe
+ *
+ * 0.8 (03/07/2000) greg kroah-hartman
+ *     Release to IO networks.
+ *     Fixed problems that were seen in code by David.
+ *  Now both Edgeport/4 and Edgeport/2 works properly.
+ *  Changed most of the functions to use port instead of serial.
+ *
+ * 0.7 (02/27/2000) greg kroah-hartman
+ *     Milestone 3 release.
+ *     Release to IO Networks
+ *     ioctl for waiting on line change implemented.
+ *     ioctl for getting statistics implemented.
+ *     multiport support working.
+ *     lsr and msr registers are now handled properly.
+ *     change break now hooked up and working.
+ *     support for all known Edgeport devices.
+ *
+ * 0.6 (02/22/2000) greg kroah-hartman
+ *     Release to IO networks.
+ *     CHASE is implemented correctly when port is closed.
+ *     SerialOpen now blocks correctly until port is fully opened.
+ *
+ * 0.5 (02/20/2000) greg kroah-hartman
+ *     Release to IO networks.
+ *     Known problems:
+ *             modem status register changes are not sent on to the user
+ *             CHASE is not implemented when the port is closed.
+ *
+ * 0.4 (02/16/2000) greg kroah-hartman
+ *     Second cut at the CeBit demo.
+ *     Doesn't leak memory on every write to the port
+ *     Still small leaks on startup.
+ *     Added support for Edgeport/2 and Edgeport/8
+ *
+ * 0.3 (02/15/2000) greg kroah-hartman
+ *     CeBit demo release.
+ *     Force the line settings to 4800, 8, 1, e for the demo.
+ *     Warning! This version leaks memory like crazy!
+ *
+ * 0.2 (01/30/2000) greg kroah-hartman
+ *     Milestone 1 release.
+ *     Device is found by USB subsystem, enumerated, fimware is downloaded
+ *     and the descriptors are printed to the debug log, config is set, and
+ *     green light starts to blink. Open port works, and data can be sent
+ *     and received at the default settings of the UART. Loopback connector
+ *     and debug log confirms this.
+ * 
+ * 0.1 (01/23/2000) greg kroah-hartman
+ *     Initial release to help IO Networks try to set up their test system. 
+ *     Edgeport4 is recognized, firmware is downloaded, config is set so 
+ *     device blinks green light every 3 sec. Port is bound, but opening,
+ *     closing, and sending data do not work properly.
+ * 
+ */
+
+#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/malloc.h>
+#include <linux/fcntl.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/serial.h>
+#include <linux/ioctl.h>
+#include <linux/proc_fs.h>
+#include <linux/usb.h>
+
+#ifdef CONFIG_USB_SERIAL_DEBUG
+       static int debug = 1;
+#else
+       static int debug;
+#endif
+
+#include "usb-serial.h"
+
+#include "io_edgeport.h"
+#include "io_ionsp.h"          /* info for the iosp messages */
+#include "io_16654.h"          /* 16654 UART defines */
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v2.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
+#define DRIVER_DESC "Edgeport USB Serial Driver"
+
+/* First, the latest boot code - for first generation edgeports */
+#define IMAGE_ARRAY_NAME       BootCodeImage_GEN1
+#define IMAGE_VERSION_NAME     BootCodeImageVersion_GEN1
+#include "io_fw_boot.h"                /* the bootloader firmware to download to a device, if it needs it */
+
+/* for second generation edgeports */
+#define IMAGE_ARRAY_NAME       BootCodeImage_GEN2
+#define IMAGE_VERSION_NAME     BootCodeImageVersion_GEN2
+#include "io_fw_boot2.h"       /* the bootloader firmware to download to a device, if it needs it */
+
+/* Then finally the main run-time operational code - for first generation edgeports */
+#define IMAGE_ARRAY_NAME       OperationalCodeImage_GEN1
+#define IMAGE_VERSION_NAME     OperationalCodeImageVersion_GEN1
+#include "io_fw_down.h"                /* Define array OperationalCodeImage[] */
+
+/* for second generation edgeports */
+#define IMAGE_ARRAY_NAME       OperationalCodeImage_GEN2
+#define IMAGE_VERSION_NAME     OperationalCodeImageVersion_GEN2
+#include "io_fw_down2.h"       /* Define array OperationalCodeImage[] */
+
+
+#define MAX_NAME_LEN           64
+
+
+#define CHASE_TIMEOUT          (5*HZ)          /* 5 seconds */
+#define OPEN_TIMEOUT           (5*HZ)          /* 5 seconds */
+#define COMMAND_TIMEOUT                (5*HZ)          /* 5 seconds */
+
+#ifndef SERIAL_MAGIC
+       #define SERIAL_MAGIC    0x6702
+#endif
+#define PORT_MAGIC             0x7301
+
+
+/* receive port state */
+enum RXSTATE {
+       EXPECT_HDR1 = 0,        /* Expect header byte 1 */
+       EXPECT_HDR2 = 1,        /* Expect header byte 2 */
+       EXPECT_DATA = 2,        /* Expect 'RxBytesRemaining' data */
+       EXPECT_HDR3 = 3,        /* Expect header byte 3 (for status hdrs only) */
+};
+
+
+/* the info for all of the devices that this driver supports */
+int EdgeportDevices[] = EDGEPORT_DEVICE_IDS;
+#define NUM_EDGEPORT_DEVICES (sizeof(EdgeportDevices) / sizeof(int))
+
+
+/* Transmit Fifo 
+ * This Transmit queue is an extension of the edgeport Rx buffer. 
+ * The maximum amount of data buffered in both the edgeport 
+ * Rx buffer (maxTxCredits) and this buffer will never exceed maxTxCredits.
+ */
+struct TxFifo {
+       unsigned int    head;   /* index to head pointer (write) */
+       unsigned int    tail;   /* index to tail pointer (read)  */
+       unsigned int    count;  /* Bytes in queue */
+       unsigned int    size;   /* Max size of queue (equal to Max number of TxCredits) */
+       unsigned char   *fifo;  /* allocated Buffer */
+};
+
+/* This structure holds all of the local port information */
+struct edgeport_port {
+       __u16                   txCredits;              /* our current credits for this port */
+       __u16                   maxTxCredits;           /* the max size of the port */
+
+       struct TxFifo           txfifo;                 /* transmit fifo -- size will be maxTxCredits */
+       struct urb              *write_urb;             /* write URB for this port */
+       char                    write_in_progress;      /* TRUE while a write URB is outstanding */
+
+       __u8                    shadowLCR;              /* last LCR value received */
+       __u8                    shadowMCR;              /* last MCR value received */
+       __u8                    shadowMSR;              /* last MSR value received */
+       __u8                    shadowLSR;              /* last LSR value received */
+       __u8                    shadowXonChar;          /* last value set as XON char in Edgeport */
+       __u8                    shadowXoffChar;         /* last value set as XOFF char in Edgeport */
+       __u8                    validDataMask;
+       __u32                   baudRate;
+
+       char                    open;
+       char                    openPending;
+       char                    commandPending;
+       char                    closePending;
+       char                    chaseResponsePending;
+
+       wait_queue_head_t       wait_chase;             /* for handling sleeping while waiting for chase to finish */
+       wait_queue_head_t       wait_open;              /* for handling sleeping while waiting for open to finish */
+       wait_queue_head_t       wait_command;           /* for handling sleeping while waiting for command to finish */
+       wait_queue_head_t       delta_msr_wait;         /* for handling sleeping while waiting for msr change to happen */
+
+       struct async_icount     icount;
+       struct usb_serial_port  *port;                  /* loop back to the owner of this object */
+};
+
+
+/* This structure holds all of the individual device information */
+struct edgeport_serial {
+       char                    name[MAX_NAME_LEN+1];           /* string name of this device */
+
+       EDGE_MANUF_DESCRIPTOR           manuf_descriptor;       /* the manufacturer descriptor */
+       EDGE_BOOT_DESCRIPTOR            boot_descriptor;        /* the boot firmware descriptor */
+       struct edgeport_product_info    product_info;           /* Product Info */
+
+       __u8                    interrupt_in_endpoint;          /* the interrupt endpoint handle */
+       unsigned char *         interrupt_in_buffer;            /* the buffer we use for the interrupt endpoint */
+       struct urb *            interrupt_read_urb;             /* our interrupt urb */
+
+       __u8                    bulk_in_endpoint;               /* the bulk in endpoint handle */
+       unsigned char *         bulk_in_buffer;                 /* the buffer we use for the bulk in endpoint */
+       struct urb *            read_urb;                       /* our bulk read urb */
+
+       __u8                    bulk_out_endpoint;              /* the bulk out endpoint handle */
+
+       __s16                   rxBytesAvail;                   /* the number of bytes that we need to read from this device */
+
+       enum RXSTATE            rxState;                        /* the current state of the bulk receive processor */
+       __u8                    rxHeader1;                      /* receive header byte 1 */
+       __u8                    rxHeader2;                      /* receive header byte 2 */
+       __u8                    rxHeader3;                      /* receive header byte 3 */
+       __u8                    rxPort;                         /* the port that we are currently receiving data for */
+       __u8                    rxStatusCode;                   /* the receive status code */
+       __u8                    rxStatusParam;                  /* the receive status paramater */
+       __s16                   rxBytesRemaining;               /* the number of port bytes left to read */
+       struct usb_serial       *serial;                        /* loop back to the owner of this object */
+};
+
+/* baud rate information */
+typedef struct _DIVISOR_TABLE_ENTRY {
+       __u32   BaudRate;
+       __u16  Divisor;
+} DIVISOR_TABLE_ENTRY, *PDIVISOR_TABLE_ENTRY;
+
+//
+// Define table of divisors for Rev A EdgePort/4 hardware
+// These assume a 3.6864MHz crystal, the standard /16, and
+// MCR.7 = 0.
+//
+static DIVISOR_TABLE_ENTRY  DivisorTable[] = {
+       {   75,         3072},  
+       {   110,        2095},          /* 2094.545455 => 230450   => .0217 % over */
+       {   134,        1713},          /* 1713.011152 => 230398.5 => .00065% under */
+       {   150,        1536},
+       {   300,        768},
+       {   600,        384},
+       {   1200,       192},
+       {   1800,       128},
+       {   2400,       96},
+       {   4800,       48},
+       {   7200,       32},
+       {   9600,       24},
+       {   14400,      16},
+       {   19200,      12},
+       {   38400,      6},
+       {   57600,      4},
+       {   115200,     2},
+       {   230400,     1},
+};
+
+/* local variables */
+static int     CmdUrbs = 0;                                                    /* Number of outstanding Command Write Urbs */
+
+
+/* local function prototypes */
+
+/* function prototypes for all URB callbacks */
+static void edge_interrupt_callback    (struct urb *urb);
+static void edge_bulk_in_callback              (struct urb *urb);
+static void edge_bulk_out_data_callback        (struct urb *urb);
+static void edge_bulk_out_cmd_callback (struct urb *urb);
+
+/* function prototypes for the usbserial callbacks */
+static int  edge_open                  (struct usb_serial_port *port, struct file *filp);
+static void edge_close                 (struct usb_serial_port *port, struct file *filp);
+static int  edge_write                 (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static int  edge_write_room            (struct usb_serial_port *port);
+static int  edge_chars_in_buffer       (struct usb_serial_port *port);
+static void edge_throttle              (struct usb_serial_port *port);
+static void edge_unthrottle            (struct usb_serial_port *port);
+static void edge_set_termios           (struct usb_serial_port *port, struct termios *old_termios);
+static int  edge_ioctl                 (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
+static void edge_break                 (struct usb_serial_port *port, int break_state);
+static int  edge_startup               (struct usb_serial *serial);
+static void edge_shutdown              (struct usb_serial *serial);
+
+
+#include "io_tables.h" /* all of the devices that this driver supports */
+
+
+/* function prototypes for all of our local functions */
+static int  process_rcvd_data          (struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength);
+static void process_rcvd_status                (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3);
+static void handle_new_msr             (struct edgeport_port *edge_port, __u8 newMsr);
+static void handle_new_lsr             (struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data);
+static int  send_iosp_ext_cmd          (struct edgeport_port *edge_port, __u8 command, __u8 param);
+static int  calc_baud_rate_divisor     (int baud_rate, int *divisor);
+static int  send_cmd_write_baud_rate   (struct edgeport_port *edge_port, int baudRate);
+static void change_port_settings       (struct edgeport_port *edge_port, struct termios *old_termios);
+static int  send_cmd_write_uart_register       (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue);
+static int  write_cmd_usb              (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength);
+static void send_more_port_data                (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port);
+
+static int  sram_write                 (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data);
+static int  rom_read                   (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data);
+static int  rom_write                  (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data);
+static void get_manufacturing_desc     (struct edgeport_serial *edge_serial);
+static void get_boot_desc              (struct edgeport_serial *edge_serial);
+static void load_application_firmware  (struct edgeport_serial *edge_serial);
+
+
+static void unicode_to_ascii           (char *string, short *unicode, int unicode_size);
+
+static int  get_string_desc            (struct usb_device *dev, int Id, struct usb_string_descriptor **pRetDesc);
+
+
+
+
+// ************************************************************************
+// ************************************************************************
+// ************************************************************************
+// ************************************************************************
+
+// These functions should be in firmware.c
+
+/************************************************************************
+ *                                                                     *
+ *     update_edgeport_E2PROM()        Compare current versions of             *
+ *                             Boot ROM and Manufacture                *
+ *                             Descriptors with versions               *
+ *                             embedded in this driver                 *
+ *                                                                     *
+ ************************************************************************/
+void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
+{
+       __u32 BootCurVer;
+       __u32 BootNewVer;
+       __u8 BootMajorVersion;                  
+       __u8 BootMinorVersion;                  
+       __u16 BootBuildNumber;
+       __u8 *BootImage;      
+       __u32 BootSize;
+       PEDGE_FIRMWARE_IMAGE_RECORD record;
+       unsigned char *firmware;
+       int response;
+
+
+       switch (edge_serial->product_info.iDownloadFile) {
+               case EDGE_DOWNLOAD_FILE_I930:
+                       BootMajorVersion        = BootCodeImageVersion_GEN1.MajorVersion;
+                       BootMinorVersion        = BootCodeImageVersion_GEN1.MinorVersion;
+                       BootBuildNumber         = BootCodeImageVersion_GEN1.BuildNumber;
+                       BootImage               = &BootCodeImage_GEN1[0];
+                       BootSize                = sizeof( BootCodeImage_GEN1 );
+                       break;
+
+               case EDGE_DOWNLOAD_FILE_80251:
+                       BootMajorVersion        = BootCodeImageVersion_GEN2.MajorVersion;
+                       BootMinorVersion        = BootCodeImageVersion_GEN2.MinorVersion;
+                       BootBuildNumber         = BootCodeImageVersion_GEN2.BuildNumber;
+                       BootImage               = &BootCodeImage_GEN2[0];
+                       BootSize                = sizeof( BootCodeImage_GEN2 );
+                       break;
+
+               default:
+                       return;
+       }
+
+       // Check Boot Image Version
+       BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) +
+                    (edge_serial->boot_descriptor.MinorVersion << 16) +
+                     edge_serial->boot_descriptor.BuildNumber;
+
+       BootNewVer = (BootMajorVersion << 24) +
+                    (BootMinorVersion << 16) +
+                     BootBuildNumber;
+
+       dbg("Current Boot Image version %d.%d.%d",
+           edge_serial->boot_descriptor.MajorVersion,
+           edge_serial->boot_descriptor.MinorVersion,
+           edge_serial->boot_descriptor.BuildNumber);
+
+
+       if (BootNewVer > BootCurVer) {
+               dbg("**Update Boot Image from %d.%d.%d to %d.%d.%d",
+                   edge_serial->boot_descriptor.MajorVersion,
+                   edge_serial->boot_descriptor.MinorVersion,
+                   edge_serial->boot_descriptor.BuildNumber,
+                   BootMajorVersion,
+                   BootMinorVersion,
+                   BootBuildNumber);
+
+
+               dbg("Downloading new Boot Image");
+
+               firmware = BootImage;
+
+               for (;;) {
+                       record = (PEDGE_FIRMWARE_IMAGE_RECORD)firmware;
+                       response = rom_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]);
+                       if (response < 0) {
+                               err("sram_write failed (%x, %x, %d)", record->ExtAddr, record->Addr, record->Len);
+                               break;
+                       }
+                       firmware += sizeof (EDGE_FIRMWARE_IMAGE_RECORD) + record->Len;
+                       if (firmware >= &BootImage[BootSize]) {
+                               break;
+                       }
+               }
+       } else {
+               dbg("Boot Image -- already up to date");
+       }
+}
+
+
+/************************************************************************
+ *                                                                     *
+ *  Get string descriptor from device                                  *
+ *                                                                     *
+ ************************************************************************/
+static int get_string (struct usb_device *dev, int Id, char *string)
+{
+       struct usb_string_descriptor StringDesc;
+       struct usb_string_descriptor *pStringDesc;
+
+       dbg(__FUNCTION__ " - USB String ID = %d", Id );
+
+       if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
+               return 0;
+       }
+
+       pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL);
+
+       if (!pStringDesc) {
+               return 0;
+       }
+
+       if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) {
+               kfree(pStringDesc);
+               return 0;
+       }
+
+       unicode_to_ascii(string,  pStringDesc->wData,     pStringDesc->bLength/2-1);
+
+       kfree(pStringDesc);
+       return strlen(string);
+}
+
+
+/************************************************************************
+ *
+ *  Get string descriptor from device
+ *
+ ************************************************************************/
+static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_descriptor **pRetDesc)
+{
+       struct usb_string_descriptor StringDesc;
+       struct usb_string_descriptor *pStringDesc;
+
+       dbg(__FUNCTION__ " - USB String ID = %d", Id );
+
+       if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
+               return 0;
+       }
+
+       pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL);
+
+       if (!pStringDesc) {
+               return -1;
+       }
+
+       if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) {
+               kfree(pStringDesc);
+               return -1;
+       }
+
+       *pRetDesc = pStringDesc;
+       return 0;
+}
+
+
+
+
+/************************************************************************
+ *                                                                                                                                             *
+ *                                                                                                                                             *
+ ************************************************************************/
+static void get_product_info(struct edgeport_serial *edge_serial)
+{
+       struct edgeport_product_info *product_info = &edge_serial->product_info;
+
+       memset (product_info, 0, sizeof(struct edgeport_product_info));
+
+       product_info->ProductId         = (__u16)(edge_serial->serial->dev->descriptor.idProduct & ~ION_DEVICE_ID_GENERATION_2);
+       product_info->NumPorts          = edge_serial->manuf_descriptor.NumPorts;
+       product_info->ProdInfoVer       = 0;
+
+       product_info->RomSize           = edge_serial->manuf_descriptor.RomSize;
+       product_info->RamSize           = edge_serial->manuf_descriptor.RamSize;
+       product_info->CpuRev            = edge_serial->manuf_descriptor.CpuRev;
+       product_info->BoardRev          = edge_serial->manuf_descriptor.BoardRev;
+
+       product_info->BootMajorVersion  = edge_serial->boot_descriptor.MajorVersion;
+       product_info->BootMinorVersion  = edge_serial->boot_descriptor.MinorVersion;
+       product_info->BootBuildNumber   = edge_serial->boot_descriptor.BuildNumber;
+
+       memcpy(product_info->ManufactureDescDate, edge_serial->manuf_descriptor.DescDate, sizeof(edge_serial->manuf_descriptor.DescDate));
+
+       // check if this is 2nd generation hardware
+       if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_GENERATION_2) {
+               product_info->FirmwareMajorVersion      = OperationalCodeImageVersion_GEN2.MajorVersion;
+               product_info->FirmwareMinorVersion      = OperationalCodeImageVersion_GEN2.MinorVersion;
+               product_info->FirmwareBuildNumber       = OperationalCodeImageVersion_GEN2.BuildNumber;
+               product_info->iDownloadFile             = EDGE_DOWNLOAD_FILE_80251;
+       } else {
+               product_info->FirmwareMajorVersion      = OperationalCodeImageVersion_GEN1.MajorVersion;
+               product_info->FirmwareMinorVersion      = OperationalCodeImageVersion_GEN1.MinorVersion;
+               product_info->FirmwareBuildNumber       = OperationalCodeImageVersion_GEN1.BuildNumber;
+               product_info->iDownloadFile             = EDGE_DOWNLOAD_FILE_I930;
+       }
+
+       // Determine Product type and set appropriate flags
+       switch (DEVICE_ID_FROM_USB_PRODUCT_ID(product_info->ProductId)) {
+               case ION_DEVICE_ID_EDGEPORT_COMPATIBLE:
+               case ION_DEVICE_ID_EDGEPORT_4T:
+               case ION_DEVICE_ID_EDGEPORT_4:
+               case ION_DEVICE_ID_EDGEPORT_2:
+               case ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU:
+               case ION_DEVICE_ID_EDGEPORT_8:
+               case ION_DEVICE_ID_EDGEPORT_421:
+               case ION_DEVICE_ID_EDGEPORT_21:
+               case ION_DEVICE_ID_EDGEPORT_2_DIN:
+               case ION_DEVICE_ID_EDGEPORT_4_DIN:
+               case ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU:
+                       product_info->IsRS232 = 1;
+                       break;
+
+               case ION_DEVICE_ID_EDGEPORT_2I:                            // Edgeport/2 RS422/RS485
+                       product_info->IsRS422 = 1;
+                       product_info->IsRS485 = 1;
+                       break;
+
+               case ION_DEVICE_ID_EDGEPORT_8I:                            // Edgeport/4 RS422
+               case ION_DEVICE_ID_EDGEPORT_4I:                            // Edgeport/4 RS422
+                       product_info->IsRS422 = 1;
+                       break;
+       }
+
+       // Dump Product Info structure
+       dbg("**Product Information:");
+       dbg("  ProductId             %x", product_info->ProductId );
+       dbg("  NumPorts              %d", product_info->NumPorts );
+       dbg("  ProdInfoVer           %d", product_info->ProdInfoVer );
+       dbg("  IsServer              %d", product_info->IsServer);
+       dbg("  IsRS232               %d", product_info->IsRS232 );
+       dbg("  IsRS422               %d", product_info->IsRS422 );
+       dbg("  IsRS485               %d", product_info->IsRS485 );
+       dbg("  RomSize               %d", product_info->RomSize );
+       dbg("  RamSize               %d", product_info->RamSize );
+       dbg("  CpuRev                %x", product_info->CpuRev  );
+       dbg("  BoardRev              %x", product_info->BoardRev);
+       dbg("  BootMajorVersion      %d.%d.%d", product_info->BootMajorVersion,
+           product_info->BootMinorVersion,
+           product_info->BootBuildNumber);
+       dbg("  FirmwareMajorVersion  %d.%d.%d", product_info->FirmwareMajorVersion,
+           product_info->FirmwareMinorVersion,
+           product_info->FirmwareBuildNumber);
+       dbg("  ManufactureDescDate   %d/%d/%d", product_info->ManufactureDescDate[0],
+           product_info->ManufactureDescDate[1],
+           product_info->ManufactureDescDate[2]+1900);
+       dbg("  iDownloadFile         0x%x",     product_info->iDownloadFile);
+
+}
+
+
+/************************************************************************/
+/************************************************************************/
+/*            U S B  C A L L B A C K   F U N C T I O N S                */
+/*            U S B  C A L L B A C K   F U N C T I O N S                */
+/************************************************************************/
+/************************************************************************/
+
+/*****************************************************************************
+ * edge_interrupt_callback
+ *     this is the callback function for when we have received data on the 
+ *     interrupt endpoint.
+ *****************************************************************************/
+static void edge_interrupt_callback (struct urb *urb)
+{
+       struct edgeport_serial  *edge_serial = (struct edgeport_serial *)urb->context;
+       struct edgeport_port *edge_port;
+       struct usb_serial_port *port;
+       unsigned char *data = urb->transfer_buffer;
+       int length = urb->actual_length;
+       int bytes_avail;
+       int position;
+       int txCredits;
+       int portNumber;
+       int result;
+
+       dbg(__FUNCTION__);
+
+       if (serial_paranoia_check (edge_serial->serial, __FUNCTION__)) {
+               return;
+       }
+
+       if (urb->status) {
+               dbg(__FUNCTION__" - nonzero control read status received: %d", urb->status);
+               return;
+       }
+
+       // process this interrupt-read even if there are no ports open
+       if (length) {
+               usb_serial_debug_data (__FILE__, __FUNCTION__, length, data);
+
+               if (length > 1) {
+                       bytes_avail = data[0] | (data[1] << 8);
+                       if (bytes_avail) {
+                               edge_serial->rxBytesAvail += bytes_avail;
+                               dbg(__FUNCTION__" - bytes_avail = %d, rxBytesAvail %d", bytes_avail, edge_serial->rxBytesAvail);
+
+                               if ((edge_serial->rxBytesAvail > 0) &&
+                                   (edge_serial->read_urb->status != -EINPROGRESS)) {
+                                       dbg(" --- Posting a read");
+
+                                       /* we have pending bytes on the bulk in pipe, send a request */
+                                       edge_serial->read_urb->dev = edge_serial->serial->dev;
+                                       result = usb_submit_urb(edge_serial->read_urb);
+                                       if (result) {
+                                               dbg(__FUNCTION__" - usb_submit_urb(read bulk) failed with result = %d", result);
+                                       }
+                               }
+                       }
+               }
+               /* grab the txcredits for the ports if available */
+               position = 2;
+               portNumber = 0;
+               while ((position < length) && (portNumber < edge_serial->serial->num_ports)) {
+                       txCredits = data[position] | (data[position+1] << 8);
+                       if (txCredits) {
+                               port = &edge_serial->serial->port[portNumber];
+                               if (port_paranoia_check (port, __FUNCTION__) == 0) {
+                                       edge_port = (struct edgeport_port *)port->private;
+                                       if (edge_port->open) {
+                                               edge_port->txCredits += txCredits;
+                                               dbg(__FUNCTION__" - txcredits for port%d = %d", portNumber, edge_port->txCredits);
+
+                                               /* tell the tty driver that something has changed */
+                                               wake_up_interruptible(&edge_port->port->tty->write_wait);
+
+                                               // Since we have more credit, check if more data can be sent
+                                               send_more_port_data(edge_serial, edge_port);
+                                       }
+                               }
+                       }
+                       position += 2;
+                       ++portNumber;
+               }
+       }
+}
+
+
+/*****************************************************************************
+ * edge_bulk_in_callback
+ *     this is the callback function for when we have received data on the 
+ *     bulk in endpoint.
+ *****************************************************************************/
+static void edge_bulk_in_callback (struct urb *urb)
+{
+       struct edgeport_serial  *edge_serial = (struct edgeport_serial *)urb->context;
+       unsigned char           *data = urb->transfer_buffer;
+       int                     status;
+       __u16                   raw_data_length;
+
+       dbg(__FUNCTION__);
+
+       if (serial_paranoia_check (edge_serial->serial, __FUNCTION__)) {
+               return;
+       }
+
+       if (urb->status) {
+               dbg(__FUNCTION__" - nonzero read bulk status received: %d", urb->status);
+               return;
+       }
+
+       if (urb->actual_length) {
+               raw_data_length = urb->actual_length;
+
+               usb_serial_debug_data (__FILE__, __FUNCTION__, raw_data_length, data);
+
+               /* decrement our rxBytes available by the number that we just got */
+               edge_serial->rxBytesAvail -= raw_data_length;
+
+               dbg(__FUNCTION__" - Received = %d, rxBytesAvail %d", raw_data_length, edge_serial->rxBytesAvail);
+
+               process_rcvd_data (edge_serial, data, urb->actual_length);
+
+               /* check to see if there's any more data for us to read */
+               if ((edge_serial->rxBytesAvail > 0) &&
+                   (edge_serial->read_urb->status != -EINPROGRESS)) {
+                       dbg(" --- Posting a read");
+
+                       /* there is, so resubmit our urb */
+                       edge_serial->read_urb->dev = edge_serial->serial->dev;
+                       status = usb_submit_urb(edge_serial->read_urb);
+                       if (status) {
+                               err(__FUNCTION__" - usb_submit_urb(read bulk) failed, status = %d", status);
+                       }
+               }
+       }
+}
+
+
+/*****************************************************************************
+ * edge_bulk_out_data_callback
+ *     this is the callback function for when we have finished sending serial data
+ *     on the bulk out endpoint.
+ *****************************************************************************/
+static void edge_bulk_out_data_callback (struct urb *urb)
+{
+       struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
+       struct tty_struct *tty;
+
+       dbg(__FUNCTION__);
+
+       if (port_paranoia_check (edge_port->port, __FUNCTION__)) {
+               return;
+       }
+
+       if (urb->status) {
+               dbg(__FUNCTION__" - nonzero write bulk status received: %d", urb->status);
+       }
+
+       tty = edge_port->port->tty;
+
+       /* let the tty driver wakeup if it has a special write_wakeup function */
+       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
+               (tty->ldisc.write_wakeup)(tty);
+       }
+
+       /* tell the tty driver that something has changed */
+       wake_up_interruptible(&tty->write_wait);
+
+       // Release the Write URB
+       edge_port->write_in_progress = FALSE;
+
+       // Check if more data needs to be sent
+       send_more_port_data((struct edgeport_serial *)(edge_port->port->serial->private), edge_port);
+}
+
+
+/*****************************************************************************
+ * BulkOutCmdCallback
+ *     this is the callback function for when we have finished sending a command
+ *     on the bulk out endpoint.
+ *****************************************************************************/
+static void edge_bulk_out_cmd_callback (struct urb *urb)
+{
+       struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
+       struct tty_struct *tty;
+       int status = urb->status;
+
+       dbg(__FUNCTION__);
+
+       CmdUrbs--;
+       dbg(__FUNCTION__" - FREE URB %p (outstanding %d)", urb, CmdUrbs);
+
+
+       /* if this urb had a transfer buffer already (old transfer) free it */
+       if (urb->transfer_buffer != NULL) {
+               kfree(urb->transfer_buffer);
+       }
+
+       // Free the command urb
+       usb_unlink_urb (urb);
+       usb_free_urb   (urb);
+
+       if (port_paranoia_check (edge_port->port, __FUNCTION__)) {
+               return;
+       }
+
+       if (status) {
+               dbg(__FUNCTION__" - nonzero write bulk status received: %d", urb->status);
+               return;
+       }
+
+       /* Get pointer to tty */
+       tty = edge_port->port->tty;
+
+       /* tell the tty driver that something has changed */
+       wake_up_interruptible(&tty->write_wait);
+
+
+       /* we have completed the command */
+       edge_port->commandPending = FALSE;
+       wake_up_interruptible(&edge_port->wait_command);
+}
+
+
+/*****************************************************************************
+ * Driver tty interface functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * SerialOpen
+ *     this function is called by the tty driver when a port is opened
+ *     If successful, we return 0
+ *     Otherwise we return a negative error number.
+ *****************************************************************************/
+static int edge_open (struct usb_serial_port *port, struct file * filp)
+{
+       struct edgeport_port *edge_port = (struct edgeport_port *)port->private;
+       struct usb_serial *serial;
+       struct edgeport_serial *edge_serial;
+       int response;
+       int timeout;
+
+       if (port_paranoia_check (port, __FUNCTION__))
+               return -ENODEV;
+       
+       dbg(__FUNCTION__ " - port %d", port->number);
+
+       ++port->open_count;
+       MOD_INC_USE_COUNT;
+       
+       if (!port->active) {
+               port->active = 1;
+
+               /* force low_latency on so that our tty_push actually forces the data through, 
+                  otherwise it is scheduled, and with high data rates (like with OHCI) data
+                  can get lost. */
+               port->tty->low_latency = 1;
+       
+               /* see if we've set up our endpoint info yet (can't set it up in edge_startup
+                  as the structures were not set up at that time.) */
+               serial = port->serial;
+               edge_serial = (struct edgeport_serial *)serial->private;
+               if (edge_serial->interrupt_in_buffer == NULL) {
+                       struct usb_serial_port *port0 = &serial->port[0];
+                       
+                       /* not set up yet, so do it now */
+                       edge_serial->interrupt_in_buffer = port0->interrupt_in_buffer;
+                       edge_serial->interrupt_in_endpoint = port0->interrupt_in_endpointAddress;
+                       edge_serial->interrupt_read_urb = port0->interrupt_in_urb;
+                       edge_serial->bulk_in_buffer = port0->bulk_in_buffer;
+                       edge_serial->bulk_in_endpoint = port0->bulk_in_endpointAddress;
+                       edge_serial->read_urb = port0->read_urb;
+                       edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress;
+               
+                       /* set up our interrupt urb */
+                       /* Like to use FILL_INT_URB, but we don't know wMaxPacketSize or bInterval, something to change for 2.5... */
+                       edge_serial->interrupt_read_urb->complete = edge_interrupt_callback;
+                       edge_serial->interrupt_read_urb->context = edge_serial;
+                       /* FILL_INT_URB(edge_serial->interrupt_read_urb, serial->dev, 
+                                    usb_rcvintpipe (serial->dev, edge_serial->interrupt_in_endpoint),
+                                    edge_serial->interrupt_in_buffer, edge_serial->interrupt_in_endpoint.wMaxPacketSize,
+                                    edge_interrupt_callback, edge_serial, edge_serial->interrupt_in_endpoint.bInterval);
+                       */
+                       
+                       /* set up our bulk in urb */
+                       /* Like to use FILL_BULK_URB, but we don't know wMaxPacketSize or bInterval, something to change for 2.5... */
+                       edge_serial->read_urb->complete = edge_bulk_in_callback;
+                       edge_serial->read_urb->context = edge_serial;
+                       /* FILL_BULK_URB(edge_serial->read_urb, serial->dev, 
+                                     usb_rcvbulkpipe (serial->dev, edge_serial->bulk_in_endpoint),
+                                     edge_serial->bulk_in_buffer, edge_serial->bulk_in_endpoint->wMaxPacketSize,
+                                     edge_bulk_in_callback, edge_serial);
+                       */
+               
+                       /* start interrupt read for this edgeport
+                        * this interrupt will continue as long as the edgeport is connected */
+                       response = usb_submit_urb (edge_serial->interrupt_read_urb);
+                       if (response) {
+                               err(__FUNCTION__" - Error %d submitting control urb", response);
+                       }
+               }
+               
+               /* initialize our wait queues */
+               init_waitqueue_head(&edge_port->wait_open);
+               init_waitqueue_head(&edge_port->wait_chase);
+               init_waitqueue_head(&edge_port->delta_msr_wait);
+               init_waitqueue_head(&edge_port->wait_command);
+
+               /* initialize our icount structure */
+               memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount));
+
+               /* initialize our port settings */
+               edge_port->txCredits            = 0;                    /* Can't send any data yet */
+               edge_port->shadowMCR            = MCR_MASTER_IE;        /* Must always set this bit to enable ints! */
+               edge_port->chaseResponsePending = FALSE;
+
+               /* send a open port command */
+               edge_port->openPending = TRUE;
+               edge_port->open        = FALSE;
+               response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);
+
+               if (response < 0) {
+                       err(__FUNCTION__" - error sending open port command");
+                       edge_port->openPending = FALSE;
+                       port->active = 0;
+                       port->open_count = 0;
+                       MOD_DEC_USE_COUNT;
+                       return -ENODEV;
+               }
+
+               /* now wait for the port to be completly opened */
+               timeout = OPEN_TIMEOUT;
+               while (timeout && edge_port->openPending == TRUE) {
+                       timeout = interruptible_sleep_on_timeout (&edge_port->wait_open, timeout);
+               }
+
+               if (edge_port->open == FALSE) {
+                       /* open timed out */
+                       dbg(__FUNCTION__" - open timedout");
+                       edge_port->openPending = FALSE;
+                       port->active = 0;
+                       port->open_count = 0;
+                       MOD_DEC_USE_COUNT;
+                       return -ENODEV;
+               }
+
+               /* create the txfifo */
+               edge_port->txfifo.head  = 0;
+               edge_port->txfifo.tail  = 0;
+               edge_port->txfifo.count = 0;
+               edge_port->txfifo.size  = edge_port->maxTxCredits;
+               edge_port->txfifo.fifo  = kmalloc (edge_port->maxTxCredits, GFP_KERNEL);
+
+               if (!edge_port->txfifo.fifo) {
+                       dbg(__FUNCTION__" - no memory");
+                       edge_close (port, filp);
+                       return -ENOMEM;
+               }
+
+               /* Allocate a URB for the write */
+               edge_port->write_urb = usb_alloc_urb (0);
+
+               if (!edge_port->write_urb) {
+                       dbg(__FUNCTION__" - no memory");
+                       edge_close (port, filp);
+                       return -ENOMEM;
+               }
+
+               dbg(__FUNCTION__"(%d) - Initialize TX fifo to %d bytes", port->number, edge_port->maxTxCredits);
+       }
+
+       dbg(__FUNCTION__" exited");
+
+       return 0;
+}
+
+
+/************************************************************************
+ *
+ * block_until_chase_response
+ *
+ *     This function will block the close until one of the following:
+ *             1. Response to our Chase comes from Edgeport
+ *             2. A timout of 10 seconds without activity has expired
+ *                (1K of Edgeport data @ 2400 baud ==> 4 sec to empty)
+ *
+ ************************************************************************/
+static void block_until_chase_response(struct edgeport_port *edge_port)
+{
+       __u16 lastCredits;
+       int timeout = 1*HZ;
+       int wait = 10;
+
+       while (1) {
+               // Save Last credits
+               lastCredits = edge_port->txCredits;
+
+               // Did we get our Chase response
+               if (edge_port->chaseResponsePending == FALSE) {
+                       dbg(__FUNCTION__" - Got Chase Response");
+
+                       // did we get all of our credit back?
+                       if (edge_port->txCredits == edge_port->maxTxCredits ) {
+                               dbg(__FUNCTION__" - Got all credits");
+                               return;
+                       }
+               }
+
+               // Block the thread for a while
+               interruptible_sleep_on_timeout (&edge_port->wait_chase, timeout);
+
+               if (lastCredits == edge_port->txCredits) {
+                       // No activity.. count down.
+                       wait--;
+                       if (wait == 0) {
+                               edge_port->chaseResponsePending = FALSE;
+                               dbg(__FUNCTION__" - Chase TIMEOUT");
+                               return;
+                       }
+               } else {
+                       // Reset timout value back to 10 seconds
+                       dbg(__FUNCTION__" - Last %d, Current %d", lastCredits, edge_port->txCredits);
+                       wait = 10;
+               }
+       }
+}
+
+
+/************************************************************************
+ *
+ * block_until_tx_empty
+ *
+ *     This function will block the close until one of the following:
+ *             1. TX count are 0
+ *             2. The edgeport has stopped
+ *             3. A timout of 3 seconds without activity has expired
+ *
+ ************************************************************************/
+static void block_until_tx_empty (struct edgeport_port *edge_port)
+{
+       struct TxFifo *fifo = &edge_port->txfifo;
+       __u32 lastCount;
+       int timeout = HZ/10;
+       int wait = 30;
+
+       while (1) {
+               // Save Last count
+               lastCount = fifo->count;
+
+               // Is the Edgeport Buffer empty?
+               if (lastCount == 0) {
+                       dbg(__FUNCTION__" - TX Buffer Empty");
+                       return;
+               }
+
+               // Block the thread for a while
+               interruptible_sleep_on_timeout (&edge_port->wait_chase, timeout);
+
+               dbg(__FUNCTION__ " wait");
+
+               if (lastCount == fifo->count) {
+                       // No activity.. count down.
+                       wait--;
+                       if (wait == 0) {
+                               dbg(__FUNCTION__" - TIMEOUT");
+                               return;
+                       }
+               } else {
+                       // Reset timout value back to seconds
+                       wait = 30;
+               }
+       }
+}
+
+
+/*****************************************************************************
+ * edge_close
+ *     this function is called by the tty driver when a port is closed
+ *****************************************************************************/
+static void edge_close (struct usb_serial_port *port, struct file * filp)
+{
+       struct usb_serial *serial;
+       struct edgeport_serial *edge_serial;
+       struct edgeport_port *edge_port;
+       int status;
+
+       if (port_paranoia_check (port, __FUNCTION__))
+               return;
+       
+       dbg(__FUNCTION__ " - port %d", port->number);
+                        
+       serial = get_usb_serial (port, __FUNCTION__);
+       if (!serial)
+               return;
+       
+       edge_serial = (struct edgeport_serial *)serial->private;
+       edge_port = (struct edgeport_port *)port->private;
+
+       --port->open_count;
+
+       if (port->open_count <= 0) {
+               // block until tx is empty
+               block_until_tx_empty(edge_port);
+       
+               edge_port->closePending = TRUE;
+       
+               /* flush and chase */
+               edge_port->chaseResponsePending = TRUE;
+       
+               dbg(__FUNCTION__" - Sending IOSP_CMD_CHASE_PORT");
+               status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+               if (status == 0) {
+                       // block until chase finished
+                       block_until_chase_response(edge_port);
+               } else {
+                       edge_port->chaseResponsePending = FALSE;
+               }
+       
+               /* close the port */
+               dbg(__FUNCTION__" - Sending IOSP_CMD_CLOSE_PORT");
+               send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
+       
+               //port->close = TRUE;
+               edge_port->closePending = FALSE;
+               edge_port->open = FALSE;
+               edge_port->openPending = FALSE;
+       
+               if (edge_port->write_urb) {
+                       /* if this urb had a transfer buffer already (old transfer) free it */
+                       if (edge_port->write_urb->transfer_buffer != NULL) {
+                               kfree(edge_port->write_urb->transfer_buffer);
+                       }
+       
+                       usb_unlink_urb (edge_port->write_urb);
+                       usb_free_urb   (edge_port->write_urb);
+               }
+       
+               if (edge_port->txfifo.fifo) {
+                       kfree(edge_port->txfifo.fifo);
+               }
+       }
+
+       MOD_DEC_USE_COUNT;
+       dbg(__FUNCTION__" exited");
+}   
+
+
+
+
+/*****************************************************************************
+ * SerialWrite
+ *     this function is called by the tty driver when data should be written to
+ *     the port.
+ *     If successful, we return the number of bytes written, otherwise we return
+ *     a negative error number.
+ *****************************************************************************/
+static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *data, int count)
+{
+        struct edgeport_port *edge_port = (struct edgeport_port *)port->private;
+       struct TxFifo *fifo;
+       int copySize;
+       int bytesleft;
+       int firsthalf;
+       int secondhalf;
+
+       dbg(__FUNCTION__ " - port %d", port->number);
+
+       // get a pointer to the Tx fifo
+       fifo = &edge_port->txfifo;
+
+       // calculate number of bytes to put in fifo
+       copySize = MIN(count, (edge_port->txCredits - fifo->count));
+
+       dbg(__FUNCTION__"(%d) of %d byte(s) Fifo room  %d -- will copy %d bytes", 
+           port->number, count, edge_port->txCredits - fifo->count, copySize);
+
+       /* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */
+       if (copySize == 0) {
+               dbg (__FUNCTION__" - copySize = Zero");
+               return 0;
+       }
+
+       // queue the data       
+       // since we can never overflow the buffer we do not have to check for full condition
+
+       // the copy is done is two parts -- first fill to the end of the buffer
+       // then copy the reset from the start of the buffer 
+
+       bytesleft = fifo->size - fifo->head;
+       firsthalf = MIN(bytesleft,copySize);
+       dbg (__FUNCTION__" - copy %d bytes of %d into fifo ", firsthalf, bytesleft);
+
+       /* now copy our data */
+       if (from_user) {
+               copy_from_user(&fifo->fifo[fifo->head], data, firsthalf);
+       } else {
+               memcpy(&fifo->fifo[fifo->head], data, firsthalf);
+       }  
+
+       // update the index and size
+       fifo->head  += firsthalf;
+       fifo->count += firsthalf;
+
+       // wrap the index
+       if (fifo->head == fifo->size) {
+               fifo->head = 0;
+       }
+
+       secondhalf = copySize-firsthalf;
+
+       if (secondhalf) {
+               dbg (__FUNCTION__" - copy rest of data %d", secondhalf);
+               if (from_user) {
+                       copy_from_user(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf);
+               } else {
+                       memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf);
+               }
+               // update the index and size
+               fifo->count += secondhalf;
+               fifo->head  += secondhalf;
+               // No need to check for wrap since we can not get to end of fifo in this part
+       }
+
+       if (copySize) {
+               usb_serial_debug_data (__FILE__, __FUNCTION__, copySize, data);
+       }
+
+       send_more_port_data((struct edgeport_serial *)port->serial->private, edge_port);
+
+       dbg(__FUNCTION__" wrote %d byte(s) TxCredits %d, Fifo %d", copySize, edge_port->txCredits, fifo->count);
+
+       return copySize;   
+}
+
+
+/************************************************************************
+ *
+ * send_more_port_data()
+ *
+ *     This routine attempts to write additional UART transmit data
+ *     to a port over the USB bulk pipe. It is called (1) when new
+ *     data has been written to a port's TxBuffer from higher layers
+ *     (2) when the peripheral sends us additional TxCredits indicating
+ *     that it can accept more Tx data for a given port; and (3) when
+ *     a bulk write completes successfully and we want to see if we
+ *     can transmit more.
+ *
+ ************************************************************************/
+static void send_more_port_data(struct edgeport_serial *edge_serial, struct edgeport_port *edge_port)
+{
+       struct TxFifo   *fifo = &edge_port->txfifo;
+       struct urb      *urb;
+       unsigned char   *buffer;
+       int             status;
+       unsigned long   flags;
+       int             count;
+       int             bytesleft;
+       int             firsthalf;
+       int             secondhalf;
+
+       dbg(__FUNCTION__"(%d)", edge_port->port->number);
+
+       /* find our next free urb */    // ICK!!! FIXME!!!
+       save_flags(flags); cli();
+
+       if (edge_port->write_in_progress ||
+           !edge_port->open             ||
+           (fifo->count == 0)) {
+               restore_flags(flags);
+               dbg(__FUNCTION__"(%d) EXIT - fifo %d, PendingWrite = %d", edge_port->port->number, fifo->count, edge_port->write_in_progress);
+               return;
+       }
+
+       // since the amount of data in the fifo will always fit into the
+       // edgeport buffer we do not need to check the write length
+
+       //      Do we have enough credits for this port to make it worthwhile
+       //      to bother queueing a write. If it's too small, say a few bytes,
+       //      it's better to wait for more credits so we can do a larger
+       //      write.
+       if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits)) {
+               restore_flags(flags);
+               dbg(__FUNCTION__"(%d) Not enough credit - fifo %d TxCredit %d", edge_port->port->number, fifo->count, edge_port->txCredits );
+               return;
+       }
+
+       // lock this write
+       edge_port->write_in_progress = TRUE;
+       restore_flags(flags);
+
+       // get a pointer to the write_urb
+       urb = edge_port->write_urb;
+
+       /* if this urb had a transfer buffer already (old transfer) free it */
+       if (urb->transfer_buffer != NULL) {
+               kfree(urb->transfer_buffer);
+               urb->transfer_buffer = NULL;
+       }
+
+       /* build the data header for the buffer and port that we are about to send out */
+       count = fifo->count;
+       buffer = kmalloc (count+2, GFP_KERNEL);
+       if (buffer == NULL) {
+               err(__FUNCTION__" - no more kernel memory...");
+               edge_port->write_in_progress = FALSE;
+               return;
+       }
+       buffer[0] = IOSP_BUILD_DATA_HDR1 (edge_port->port->number, count);
+       buffer[1] = IOSP_BUILD_DATA_HDR2 (edge_port->port->number, count);
+
+       /* now copy our data */
+       bytesleft =  fifo->size - fifo->tail;
+       firsthalf = MIN(bytesleft,count);
+       memcpy(&buffer[2], &fifo->fifo[fifo->tail], firsthalf);
+       fifo->tail  += firsthalf;
+       fifo->count -= firsthalf;
+       if (fifo->tail == fifo->size) {
+               fifo->tail = 0;
+       }
+
+       secondhalf = count-firsthalf;
+       if (secondhalf) {
+               memcpy(&buffer[2+firsthalf], &fifo->fifo[fifo->tail], secondhalf);
+               fifo->tail  += secondhalf;
+               fifo->count -= secondhalf;
+       }
+
+       if (count) {
+               usb_serial_debug_data (__FILE__, __FUNCTION__, count, &buffer[2]);
+       }
+
+       /* fill up the urb with all of our data and submit it */
+       FILL_BULK_URB (urb, edge_serial->serial->dev, 
+                      usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
+                      buffer, count+2, edge_bulk_out_data_callback, edge_port);
+
+       /* set the USB_BULK_QUEUE flag so that we can shove a bunch of urbs at once down the pipe */
+       urb->transfer_flags |= USB_QUEUE_BULK;
+
+       urb->dev = edge_serial->serial->dev;
+       status = usb_submit_urb(urb);
+       if (status) {
+               /* something went wrong */
+               dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed");
+               edge_port->write_in_progress = FALSE;
+       } else {
+               /* decrement the number of credits we have by the number we just sent */
+               edge_port->txCredits -= count;
+               edge_port->icount.tx += count;
+       }
+       dbg(__FUNCTION__" wrote %d byte(s) TxCredit %d, Fifo %d", count, edge_port->txCredits, fifo->count);
+}
+
+
+/*****************************************************************************
+ * edge_write_room
+ *     this function is called by the tty driver when it wants to know how many
+ *     bytes of data we can accept for a specific port.
+ *     If successful, we return the amount of room that we have for this port
+ *     (the txCredits), 
+ *     Otherwise we return a negative error number.
+ *****************************************************************************/
+static int edge_write_room (struct usb_serial_port *port)
+{
+       struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+       int room;
+
+       dbg(__FUNCTION__);
+
+       if (edge_port->closePending == TRUE) {
+               return -ENODEV;
+       }
+
+       dbg(__FUNCTION__" - port %d", port->number);
+
+       if (!edge_port->open) {
+               dbg (__FUNCTION__" - port not opened");
+               return -EINVAL;
+       }
+
+       // total of both buffers is still txCredit
+       room = edge_port->txCredits - edge_port->txfifo.count;
+
+       dbg(__FUNCTION__" - returns %d", room);
+       return room;
+}
+
+
+/*****************************************************************************
+ * edge_chars_in_buffer
+ *     this function is called by the tty driver when it wants to know how many
+ *     bytes of data we currently have outstanding in the port (data that has
+ *     been written, but hasn't made it out the port yet)
+ *     If successful, we return the number of bytes left to be written in the 
+ *     system, 
+ *     Otherwise we return a negative error number.
+ *****************************************************************************/
+static int edge_chars_in_buffer (struct usb_serial_port *port)
+{
+       struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+       int num_chars;
+
+       dbg(__FUNCTION__);
+
+       if (!edge_port->open) {
+               dbg (__FUNCTION__" - port not opened");
+               return -EINVAL;
+       }
+
+       num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count;
+       if (num_chars) {
+               dbg(__FUNCTION__"(port %d) - returns %d", port->number, num_chars);
+       }
+
+       return num_chars;
+}
+
+
+/*****************************************************************************
+ * SerialThrottle
+ *     this function is called by the tty driver when it wants to stop the data
+ *     being read from the port.
+ *****************************************************************************/
+static void edge_throttle (struct usb_serial_port *port)
+{
+       struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+       struct tty_struct *tty;
+       int status;
+
+       dbg(__FUNCTION__" - port %d", port->number);
+
+       if (!edge_port->open) {
+               dbg (__FUNCTION__" - port not opened");
+               return;
+       }
+
+       tty = port->tty;
+
+       /* if we are implementing XON/XOFF, send the stop character */
+       if (I_IXOFF(tty)) {
+               unsigned char stop_char = STOP_CHAR(tty);
+               status = edge_write (port, 0, &stop_char, 1);
+               if (status <= 0) {
+                       return;
+               }
+       }
+
+       /* if we are implementing RTS/CTS, toggle that line */
+       if (tty->termios->c_cflag & CRTSCTS) {
+               edge_port->shadowMCR &= ~MCR_RTS;
+               status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
+               if (status != 0) {
+                       return;
+               }
+       }
+
+       return;
+}
+
+
+/*****************************************************************************
+ * edge_unthrottle
+ *     this function is called by the tty driver when it wants to resume the data
+ *     being read from the port (called after SerialThrottle is called)
+ *****************************************************************************/
+static void edge_unthrottle (struct usb_serial_port *port)
+{
+       struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+       struct tty_struct *tty;
+       int status;
+
+       dbg(__FUNCTION__" - port %d", port->number);
+
+       if (!edge_port->open) {
+               dbg (__FUNCTION__" - port not opened");
+               return;
+       }
+
+       tty = port->tty;
+
+       /* if we are implementing XON/XOFF, send the start character */
+       if (I_IXOFF(tty)) {
+               unsigned char start_char = START_CHAR(tty);
+               status = edge_write (port, 0, &start_char, 1);
+               if (status <= 0) {
+                       return;
+               }
+       }
+
+       /* if we are implementing RTS/CTS, toggle that line */
+       if (tty->termios->c_cflag & CRTSCTS) {
+               edge_port->shadowMCR |= MCR_RTS;
+               status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
+               if (status != 0) {
+                       return;
+               }
+       }
+
+       return;
+}
+
+
+/*****************************************************************************
+ * SerialSetTermios
+ *     this function is called by the tty driver when it wants to change the termios structure
+ *****************************************************************************/
+static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+{
+       struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+       struct tty_struct *tty = port->tty;
+       unsigned int cflag = tty->termios->c_cflag;
+
+       dbg(__FUNCTION__" - clfag %08x %08x iflag %08x %08x", 
+           tty->termios->c_cflag,
+           old_termios->c_cflag,
+           RELEVANT_IFLAG(tty->termios->c_iflag),
+           RELEVANT_IFLAG(old_termios->c_iflag)
+          );
+
+       /* check that they really want us to change something */
+       if (old_termios) {
+               if ((cflag == old_termios->c_cflag) &&
+                   (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
+                       dbg(__FUNCTION__" - nothing to change");
+                       return;
+               }
+       }
+
+       dbg(__FUNCTION__" - port %d", port->number);
+
+       if (!edge_port->open) {
+               dbg (__FUNCTION__" - port not opened");
+               return;
+       }
+
+       /* change the port settings to the new ones specified */
+       change_port_settings (edge_port, old_termios);
+
+       return;
+}
+
+
+/*****************************************************************************
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ *         is emptied.  On bus types like RS485, the transmitter must
+ *         release the bus after transmitting. This must be done when
+ *         the transmit shift register is empty, not be done when the
+ *         transmit holding register is empty.  This functionality
+ *         allows an RS485 driver to be written in user space. 
+ *****************************************************************************/
+static int get_lsr_info(struct edgeport_port *edge_port, unsigned int *value)
+{
+       unsigned int result = 0;
+
+       if (edge_port->maxTxCredits == edge_port->txCredits &&
+           edge_port->txfifo.count == 0) {
+               dbg(__FUNCTION__" -- Empty");
+               result = TIOCSER_TEMT;
+       }
+
+       if (copy_to_user(value, &result, sizeof(int)))
+               return -EFAULT;
+       return 0;
+}
+
+static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int *value)
+{
+       unsigned int result = 0;
+       struct tty_struct *tty = edge_port->port->tty;
+
+       result = tty->read_cnt;
+
+       dbg(__FUNCTION__"(%d) = %d",  edge_port->port->number, result);
+       if (copy_to_user(value, &result, sizeof(int)))
+               return -EFAULT;
+       //return 0;
+       return -ENOIOCTLCMD;
+}
+
+static int set_modem_info(struct edgeport_port *edge_port, unsigned int *value)
+{
+       unsigned int mcr = edge_port->shadowMCR;
+       unsigned int arg;
+
+       if (copy_from_user(&arg, value, sizeof(int)))
+               return -EFAULT;
+
+       // turn off the RTS and DTR
+       mcr &=  ~(MCR_RTS | MCR_DTR);
+
+       mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
+       mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
+
+       edge_port->shadowMCR = mcr;
+
+       send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
+
+       return 0;
+}
+
+static int get_modem_info(struct edgeport_port *edge_port, unsigned int *value)
+{
+       unsigned int result = 0;
+       unsigned int msr = edge_port->shadowMSR;
+       unsigned int mcr = edge_port->shadowMCR;
+
+       result = ((mcr & MCR_DTR)       ? TIOCM_DTR: 0)   /* 0x002 */
+                 | ((mcr & MCR_RTS)    ? TIOCM_RTS: 0)   /* 0x004 */
+                 | ((msr & MSR_CTS)    ? TIOCM_CTS: 0)   /* 0x020 */
+                 | ((msr & MSR_CD)     ? TIOCM_CAR: 0)   /* 0x040 */
+                 | ((msr & MSR_RI)     ? TIOCM_RI:  0)   /* 0x080 */
+                 | ((msr & MSR_DSR)    ? TIOCM_DSR: 0);  /* 0x100 */
+
+
+       dbg(__FUNCTION__" -- %x", result);
+
+       if (copy_to_user(value, &result, sizeof(int)))
+               return -EFAULT;
+       return 0;
+}
+
+
+
+static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct * retinfo)
+{
+       struct serial_struct tmp;
+
+       if (!retinfo)
+               return -EFAULT;
+
+       memset(&tmp, 0, sizeof(tmp));
+
+       tmp.type                = PORT_16550A;
+       tmp.line                = edge_port->port->serial->minor;
+       tmp.port                = edge_port->port->number;
+       tmp.irq                 = 0;
+       tmp.flags               = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+       tmp.xmit_fifo_size      = edge_port->maxTxCredits;
+       tmp.baud_base           = 9600;
+       tmp.close_delay         = 5*HZ;
+       tmp.closing_wait        = 30*HZ;
+//     tmp.custom_divisor      = state->custom_divisor;
+//     tmp.hub6                = state->hub6;
+//     tmp.io_type             = state->io_type;
+
+
+       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+               return -EFAULT;
+       return 0;
+}
+
+
+
+/*****************************************************************************
+ * SerialIoctl
+ *     this function handles any ioctl calls to the driver
+ *****************************************************************************/
+static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+       struct async_icount cnow;
+       struct async_icount cprev;
+       struct serial_icounter_struct icount;
+       unsigned long flags;
+
+
+       dbg(__FUNCTION__" - port %d, cmd = 0x%x", port->number, cmd);
+
+       switch (cmd) {
+               // return number of bytes available
+               case TIOCINQ:
+                       dbg(__FUNCTION__" (%d) TIOCINQ",  port->number);
+                       return get_number_bytes_avail(edge_port, (unsigned int *) arg);
+                       break;
+
+//             case TCGETS:            
+//                     dbg(__FUNCTION__" (%d) TCGETS",  port->number);
+//                     break;
+
+//             case TCSETS:            
+//                     dbg(__FUNCTION__" (%d) TCSETS",  port->number);
+//                     break;
+
+               case TIOCSERGETLSR:
+                       dbg(__FUNCTION__" (%d) TIOCSERGETLSR",  port->number);
+                       return get_lsr_info(edge_port, (unsigned int *) arg);
+                       return 0;
+
+               case TIOCMSET:  
+                       dbg(__FUNCTION__" (%d) TIOCMSET",  port->number);
+                       return set_modem_info(edge_port, (unsigned int *) arg);
+
+               case TIOCMGET:  
+                       dbg(__FUNCTION__" (%d) TIOCMGET",  port->number);
+                       return get_modem_info(edge_port, (unsigned int *) arg);
+
+               case TIOCGSERIAL:
+                       dbg(__FUNCTION__" (%d) TIOCGSERIAL",  port->number);
+                       return get_serial_info(edge_port, (struct serial_struct *) arg);
+
+               case TIOCSSERIAL:
+                       dbg(__FUNCTION__" (%d) TIOCSSERIAL",  port->number);
+                       break;
+
+               case TIOCMIWAIT:
+                       dbg(__FUNCTION__" (%d) TIOCMIWAIT",  port->number);
+                       save_flags(flags); cli();
+                       cprev = edge_port->icount;
+                       restore_flags(flags);
+                       while (1) {
+                               interruptible_sleep_on(&edge_port->delta_msr_wait);
+                               /* see if a signal did it */
+                               if (signal_pending(current))
+                                       return -ERESTARTSYS;
+                               save_flags(flags); cli();
+                               cnow = edge_port->icount; /* atomic copy */
+                               restore_flags(flags);
+                               if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+                                   cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+                                       return -EIO; /* no change => error */
+                               if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+                                   ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+                                   ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
+                                   ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+                                       return 0;
+                               }
+                               cprev = cnow;
+                       }
+                       /* NOTREACHED */
+                       break;
+
+               case TIOCGICOUNT:
+                       save_flags(flags); cli();
+                       cnow = edge_port->icount;
+                       restore_flags(flags);
+                       icount.cts = cnow.cts;
+                       icount.dsr = cnow.dsr;
+                       icount.rng = cnow.rng;
+                       icount.dcd = cnow.dcd;
+                       icount.rx = cnow.rx;
+                       icount.tx = cnow.tx;
+                       icount.frame = cnow.frame;
+                       icount.overrun = cnow.overrun;
+                       icount.parity = cnow.parity;
+                       icount.brk = cnow.brk;
+                       icount.buf_overrun = cnow.buf_overrun;
+
+                       dbg(__FUNCTION__" (%d) TIOCGICOUNT RX=%d, TX=%d",  port->number, icount.rx, icount.tx );
+                       if (copy_to_user((void *)arg, &icount, sizeof(icount)))
+                               return -EFAULT;
+                       return 0;
+       }
+
+       return -ENOIOCTLCMD;
+}
+
+
+/*****************************************************************************
+ * SerialBreak
+ *     this function sends a break to the port
+ *****************************************************************************/
+static void edge_break (struct usb_serial_port *port, int break_state)
+{
+       struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+       int status;
+
+       /* flush and chase */
+       edge_port->chaseResponsePending = TRUE;
+
+       dbg(__FUNCTION__" - Sending IOSP_CMD_CHASE_PORT");
+       status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+       if (status == 0) {
+               // block until chase finished
+               block_until_chase_response(edge_port);
+       } else {
+               edge_port->chaseResponsePending = FALSE;
+       }
+
+       if (break_state == -1) {
+               dbg(__FUNCTION__" - Sending IOSP_CMD_SET_BREAK");
+               status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0);
+       } else {
+               dbg(__FUNCTION__" - Sending IOSP_CMD_CLEAR_BREAK");
+               status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0);
+       }
+       if (status) {
+               dbg(__FUNCTION__" - error sending break set/clear command.");
+       }
+
+       return;
+}
+
+
+/*****************************************************************************
+ * process_rcvd_data
+ *     this function handles the data received on the bulk in pipe.
+ *****************************************************************************/
+static int process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char * buffer, __u16 bufferLength)
+{
+       struct usb_serial_port *port;
+       struct edgeport_port *edge_port;
+       struct tty_struct *tty;
+       __u16 lastBufferLength;
+       __u16 rxLen;
+       int i;
+
+       dbg(__FUNCTION__);
+
+       lastBufferLength = bufferLength + 1;
+
+       while (bufferLength > 0) {
+               /* failsafe incase we get a message that we don't understand */
+               if (lastBufferLength == bufferLength) {
+                       dbg(__FUNCTION__" - stuck in loop, exiting it.");
+                       break;
+               }
+               lastBufferLength = bufferLength;
+
+               switch (edge_serial->rxState) {
+                       case EXPECT_HDR1:
+                               edge_serial->rxHeader1 = *buffer;
+                               ++buffer;
+                               --bufferLength;
+
+                               if (bufferLength == 0) {
+                                       edge_serial->rxState = EXPECT_HDR2;
+                                       break;
+                               }
+                               /* otherwise, drop on through */
+
+                       case EXPECT_HDR2:
+                               edge_serial->rxHeader2 = *buffer;
+                               ++buffer;
+                               --bufferLength;
+
+                               dbg(__FUNCTION__" - Hdr1=%02X Hdr2=%02X", edge_serial->rxHeader1, edge_serial->rxHeader2);
+
+                               // Process depending on whether this header is
+                               // data or status
+
+                               if (IS_CMD_STAT_HDR(edge_serial->rxHeader1)) {
+                                       // Decode this status header and goto EXPECT_HDR1 (if we
+                                       // can process the status with only 2 bytes), or goto
+                                       // EXPECT_HDR3 to get the third byte.
+
+                                       edge_serial->rxPort       = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
+                                       edge_serial->rxStatusCode = IOSP_GET_STATUS_CODE(edge_serial->rxHeader1);
+
+                                       if (!IOSP_STATUS_IS_2BYTE(edge_serial->rxStatusCode)) {
+                                               // This status needs additional bytes. Save what we have
+                                               // and then wait for more data.
+                                               edge_serial->rxStatusParam = edge_serial->rxHeader2;
+
+                                               edge_serial->rxState = EXPECT_HDR3;
+                                               break;
+                                       }
+
+                                       // We have all the header bytes, process the status now
+                                       process_rcvd_status (edge_serial, edge_serial->rxHeader2, 0);
+
+                                       edge_serial->rxState = EXPECT_HDR1;
+                                       break;
+                               } else {
+                                       edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
+                                       edge_serial->rxBytesRemaining = IOSP_GET_HDR_DATA_LEN(edge_serial->rxHeader1, edge_serial->rxHeader2);
+
+                                       dbg(__FUNCTION__" - Data for Port %u Len %u", edge_serial->rxPort, edge_serial->rxBytesRemaining);
+
+                                       //ASSERT( DevExt->RxPort < DevExt->NumPorts );
+                                       //ASSERT( DevExt->RxBytesRemaining < IOSP_MAX_DATA_LENGTH );
+
+                                       if (bufferLength == 0 ) {
+                                               edge_serial->rxState = EXPECT_DATA;
+                                               break;
+                                       }
+                                       // Else, drop through
+                               }
+
+                       case EXPECT_DATA:       // Expect data
+
+                               if (bufferLength < edge_serial->rxBytesRemaining) {
+                                       rxLen = bufferLength;
+                                       edge_serial->rxState = EXPECT_DATA;     // Expect data to start next buffer
+                               } else {
+                                       // BufLen >= RxBytesRemaining
+                                       rxLen = edge_serial->rxBytesRemaining;
+                                       edge_serial->rxState = EXPECT_HDR1;     // Start another header next time
+                               }
+
+                               bufferLength -= rxLen;
+                               edge_serial->rxBytesRemaining -= rxLen;
+
+                               /* spit this data back into the tty driver if this port is open */
+                               if (rxLen) {
+                                       port = &edge_serial->serial->port[edge_serial->rxPort];
+                                       if (port_paranoia_check (port, __FUNCTION__) == 0) {
+                                               edge_port = (struct edgeport_port *)port->private;
+                                               if (edge_port->open) {
+                                                       tty = edge_port->port->tty;
+                                                       if (tty) {
+                                                               dbg (__FUNCTION__" - Sending %d bytes to TTY for port %d", rxLen, edge_serial->rxPort);
+                                                               for (i = 0; i < rxLen ; ++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);
+                                                                       }
+                                                                       /* this doesn't actually push the data through unless tty->low_latency is set */
+                                                                       tty_insert_flip_char(tty, buffer[i], 0);
+                                                               }
+                                                               tty_flip_buffer_push(tty);
+                                                       }
+                                                       edge_port->icount.rx += rxLen;
+                                               }
+                                       }
+                                       buffer += rxLen;
+                               }
+
+                               break;
+
+                       case EXPECT_HDR3:                       // Expect 3rd byte of status header
+                               edge_serial->rxHeader3 = *buffer;
+                               ++buffer;
+                               --bufferLength;
+
+                               // We have all the header bytes, process the status now
+                               process_rcvd_status (edge_serial, edge_serial->rxStatusParam, edge_serial->rxHeader3);
+                               edge_serial->rxState = EXPECT_HDR1;
+                               break;
+
+               }
+       }
+
+       return 0;
+}
+
+
+/*****************************************************************************
+ * process_rcvd_status
+ *     this function handles the any status messages received on the bulk in pipe.
+ *****************************************************************************/
+static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3)
+{
+       struct usb_serial_port *port;
+       struct edgeport_port *edge_port;
+       __u8 code = edge_serial->rxStatusCode;
+
+       /* switch the port pointer to the one being currently talked about */
+       port = &edge_serial->serial->port[edge_serial->rxPort];
+       if (port_paranoia_check (port, __FUNCTION__)) {
+               return;
+       }
+       edge_port = (struct edgeport_port *)port->private;
+       if (edge_port == NULL) {
+               err (__FUNCTION__ " - edge_port == NULL for port %d", edge_serial->rxPort);
+               return;
+       }
+
+       dbg(__FUNCTION__" - port %d", edge_serial->rxPort);
+
+       if (code == IOSP_EXT_STATUS) {
+               switch (byte2) {
+                       case IOSP_EXT_STATUS_CHASE_RSP:
+                               // we want to do EXT status regardless of port open/closed 
+                               dbg(__FUNCTION__" - Port %u EXT CHASE_RSP Data = %02x", edge_serial->rxPort, byte3 );
+                               // Currently, the only EXT_STATUS is Chase, so process here instead of one more call
+                               // to one more subroutine. If/when more EXT_STATUS, there'll be more work to do.
+                               // Also, we currently clear flag and close the port regardless of content of above's Byte3.
+                               // We could choose to do something else when Byte3 says Timeout on Chase from Edgeport,
+                               // like wait longer in block_until_chase_response, but for now we don't. 
+                               edge_port->chaseResponsePending = FALSE;
+                               wake_up_interruptible (&edge_port->wait_chase);
+                               return;
+
+                       case IOSP_EXT_STATUS_RX_CHECK_RSP:
+                               dbg( __FUNCTION__" ========== Port %u CHECK_RSP Sequence = %02x =============\n", edge_serial->rxPort, byte3 );
+                               //Port->RxCheckRsp = TRUE;
+                               return;
+               }
+       }
+
+       if (code == IOSP_STATUS_OPEN_RSP) {
+               edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3);
+               edge_port->maxTxCredits = edge_port->txCredits;
+               dbg (__FUNCTION__" - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", edge_serial->rxPort, byte2, edge_port->txCredits);
+               handle_new_msr (edge_port, byte2);
+
+               /* send the current line settings to the port so we are in sync with any further termios calls */
+               change_port_settings (edge_port, edge_port->port->tty->termios);
+
+               /* we have completed the open */
+               edge_port->openPending = FALSE;
+               edge_port->open = TRUE;
+               wake_up_interruptible(&edge_port->wait_open);
+               return;
+       }
+
+       // If port is closed, silently discard all rcvd status. We can
+       // have cases where buffered status is received AFTER the close
+       // port command is sent to the Edgeport.
+       if ((!edge_port->open ) || (edge_port->closePending)) {
+               return;
+       }
+
+       switch (code) {
+               // Not currently sent by Edgeport
+               case IOSP_STATUS_LSR:
+                       dbg(__FUNCTION__" - Port %u LSR Status = %02x", edge_serial->rxPort, byte2);
+                       handle_new_lsr (edge_port, FALSE, byte2, 0);
+                       break;
+
+               case IOSP_STATUS_LSR_DATA:
+                       dbg(__FUNCTION__" - Port %u LSR Status = %02x, Data = %02x", edge_serial->rxPort, byte2, byte3);
+                       // byte2 is LSR Register
+                       // byte3 is broken data byte
+                       handle_new_lsr (edge_port, TRUE, byte2, byte3);
+                       break;
+                       //
+                       //      case IOSP_EXT_4_STATUS:
+                       //              dbg(__FUNCTION__" - Port %u LSR Status = %02x Data = %02x", edge_serial->rxPort, byte2, byte3);
+                       //              break;
+                       //
+               case IOSP_STATUS_MSR:
+                       dbg(__FUNCTION__" - Port %u MSR Status = %02x", edge_serial->rxPort, byte2);
+
+                       // Process this new modem status and generate appropriate
+                       // events, etc, based on the new status. This routine
+                       // also saves the MSR in Port->ShadowMsr.
+                       handle_new_msr(edge_port, byte2);
+                       break;
+
+               default:
+                       dbg(__FUNCTION__" - Unrecognized IOSP status code %u\n", code);
+                       break;
+       }
+
+       return;
+}
+
+
+/*****************************************************************************
+ * handle_new_msr
+ *     this function handles any change to the msr register for a port.
+ *****************************************************************************/
+static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
+{
+       struct  async_icount *icount;
+
+       dbg(__FUNCTION__" %02x", newMsr);
+
+       if (newMsr & (MSR_DELTA_CTS | MSR_DELTA_DSR | MSR_DELTA_RI | MSR_DELTA_CD)) {
+               icount = &edge_port->icount;
+
+               /* update input line counters */
+               if (newMsr & MSR_DELTA_CTS) {
+                       icount->cts++;
+               }
+               if (newMsr & MSR_DELTA_DSR) {
+                       icount->dsr++;
+               }
+               if (newMsr & MSR_DELTA_CD) {
+                       icount->dcd++;
+               }
+               if (newMsr & MSR_DELTA_RI) {
+                       icount->rng++;
+               }
+               wake_up_interruptible(&edge_port->delta_msr_wait);
+       }
+
+       /* Save the new modem status */
+       edge_port->shadowMSR = newMsr & 0xf0;
+
+       return;
+}
+
+
+/*****************************************************************************
+ * handle_new_lsr
+ *     this function handles any change to the lsr register for a port.
+ *****************************************************************************/
+static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data)
+{
+       __u8    newLsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
+       struct  async_icount *icount;
+
+       dbg(__FUNCTION__" - %02x", newLsr);
+
+       edge_port->shadowLSR = lsr;
+
+       if (newLsr & LSR_BREAK) {
+               //
+               // Parity and Framing errors only count if they
+               // occur exclusive of a break being
+               // received.
+               //
+               newLsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
+       }
+
+       /* Place LSR data byte into Rx buffer */
+       if (lsrData) {
+               tty_insert_flip_char(edge_port->port->tty, data, 0);
+               tty_flip_buffer_push(edge_port->port->tty);
+       }
+
+       /* update input line counters */
+       icount = &edge_port->icount;
+       if (newLsr & LSR_BREAK) {
+               icount->brk++;
+       }
+       if (newLsr & LSR_OVER_ERR) {
+               icount->overrun++;
+       }
+       if (newLsr & LSR_PAR_ERR) {
+               icount->parity++;
+       }
+       if (newLsr & LSR_FRM_ERR) {
+               icount->frame++;
+       }
+
+       return;
+}
+
+
+/****************************************************************************
+ * sram_write
+ *     writes a number of bytes to the Edgeport device's sram starting at the 
+ *     given address.
+ *     If successful returns the number of bytes written, otherwise it returns
+ *     a negative error number of the problem.
+ ****************************************************************************/
+static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data)
+{
+       int result;
+       __u16 current_length;
+       unsigned char *transfer_buffer;
+
+//     dbg (__FUNCTION__" - %x, %x, %d", extAddr, addr, length);
+
+       transfer_buffer =  kmalloc (64, GFP_KERNEL);
+       if (!transfer_buffer) {
+               err(__FUNCTION__" - kmalloc(%d) failed.\n", 64);
+               return -ENOMEM;
+       }
+
+       /* need to split these writes up into 64 byte chunks */
+       result = 0;
+       while (length > 0) {
+               if (length > 64) {
+                       current_length = 64;
+               } else {
+                       current_length = length;
+               }
+//             dbg (__FUNCTION__" - writing %x, %x, %d", extAddr, addr, current_length);
+               memcpy (transfer_buffer, data, current_length);
+               result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_RAM, 
+                                         0x40, addr, extAddr, transfer_buffer, current_length, 300);
+               if (result < 0)
+                       break;
+               length -= current_length;
+               addr += current_length;
+               data += current_length;
+       }       
+
+       kfree (transfer_buffer);
+       return result;
+}
+
+
+/****************************************************************************
+ * rom_write
+ *     writes a number of bytes to the Edgeport device's ROM starting at the
+ *     given address.
+ *     If successful returns the number of bytes written, otherwise it returns
+ *     a negative error number of the problem.
+ ****************************************************************************/
+static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data)
+{
+       int result;
+       __u16 current_length;
+       unsigned char *transfer_buffer;
+
+//     dbg (__FUNCTION__" - %x, %x, %d", extAddr, addr, length);
+
+       transfer_buffer =  kmalloc (64, GFP_KERNEL);
+       if (!transfer_buffer) {
+               err(__FUNCTION__" - kmalloc(%d) failed.\n", 64);
+               return -ENOMEM;
+       }
+
+       /* need to split these writes up into 64 byte chunks */
+       result = 0;
+       while (length > 0) {
+               if (length > 64) {
+                       current_length = 64;
+               } else {
+                       current_length = length;
+               }
+//             dbg (__FUNCTION__" - writing %x, %x, %d", extAddr, addr, current_length);
+               memcpy (transfer_buffer, data, current_length);
+               result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_ROM, 
+                                         0x40, addr, extAddr, transfer_buffer, current_length, 300);
+               if (result < 0)
+                       break;
+               length -= current_length;
+               addr += current_length;
+               data += current_length;
+       }       
+
+       kfree (transfer_buffer);
+       return result;
+}
+
+
+/****************************************************************************
+ * rom_read
+ *     reads a number of bytes from the Edgeport device starting at the given
+ *     address.
+ *     If successful returns the number of bytes read, otherwise it returns
+ *     a negative error number of the problem.
+ ****************************************************************************/
+static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data)
+{
+       int result;
+       __u16 current_length;
+       unsigned char *transfer_buffer;
+
+       dbg (__FUNCTION__" - %x, %x, %d", extAddr, addr, length);
+
+       transfer_buffer =  kmalloc (64, GFP_KERNEL);
+       if (!transfer_buffer) {
+               err(__FUNCTION__" - kmalloc(%d) failed.\n", 64);
+               return -ENOMEM;
+       }
+
+       /* need to split these reads up into 64 byte chunks */
+       result = 0;
+       while (length > 0) {
+               if (length > 64) {
+                       current_length = 64;
+               } else {
+                       current_length = length;
+               }
+//             dbg (__FUNCTION__" - %x, %x, %d", extAddr, addr, current_length);
+               result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQUEST_ION_READ_ROM, 
+                                         0xC0, addr, extAddr, transfer_buffer, current_length, 300);
+               if (result < 0)
+                       break;
+               memcpy (data, transfer_buffer, current_length);
+               length -= current_length;
+               addr += current_length;
+               data += current_length;
+       }       
+
+       kfree (transfer_buffer);
+       return result;
+}
+
+
+/****************************************************************************
+ * send_iosp_ext_cmd
+ *     Is used to send a IOSP message to the Edgeport device
+ ****************************************************************************/
+static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param)
+{
+       unsigned char   *buffer;
+       unsigned char   *currentCommand;
+       int             length = 0;
+       int             status = 0;
+
+       dbg(__FUNCTION__" - %d, %d", command, param);
+
+       buffer =  kmalloc (10, GFP_KERNEL);
+       if (!buffer) {
+               err(__FUNCTION__" - kmalloc(%d) failed.\n", 10);
+               return -ENOMEM;
+       }
+
+       currentCommand = buffer;
+
+       MAKE_CMD_EXT_CMD( &currentCommand, &length, edge_port->port->number, command, param);
+
+       status = write_cmd_usb (edge_port, buffer, length);
+       if (status) {
+               /* something bad happened, let's free up the memory */
+               kfree(buffer);
+       }
+
+       return status;
+}
+
+
+/*****************************************************************************
+ * write_cmd_usb
+ *     this function writes the given buffer out to the bulk write endpoint.
+ *****************************************************************************/
+static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int length)
+{
+       struct edgeport_serial *edge_serial = (struct edgeport_serial *)edge_port->port->serial->private;
+       int status = 0;
+       urb_t *urb;
+       int timeout;
+
+       usb_serial_debug_data (__FILE__, __FUNCTION__, length, buffer);
+
+       /* Allocate our next urb */
+       urb = usb_alloc_urb (0);
+
+       CmdUrbs++;
+
+       dbg(__FUNCTION__" - ALLOCATE URB %p (outstanding %d)", urb, CmdUrbs);
+
+       if (!urb) {
+               return -ENOMEM;
+       }
+
+       FILL_BULK_URB (urb, edge_serial->serial->dev, 
+                      usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
+                      buffer, length, edge_bulk_out_cmd_callback, edge_port);
+
+       /* set the USB_BULK_QUEUE flag so that we can shove a bunch of urbs at once down the pipe */
+       urb->transfer_flags |= USB_QUEUE_BULK;
+
+       edge_port->commandPending = TRUE;
+       urb->dev = edge_serial->serial->dev;
+       status = usb_submit_urb(urb);
+
+       if (status) {
+               /* something went wrong */
+               dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed");
+
+               /* if this urb had a transfer buffer already (old transfer) free it */
+               if (urb->transfer_buffer != NULL) {
+                       kfree(urb->transfer_buffer);
+               }
+               usb_unlink_urb (urb);
+               usb_free_urb   (urb);
+               return status;
+       }
+
+       // wait for command to finish
+       timeout = COMMAND_TIMEOUT;
+#if 0
+       while (timeout && edge_port->commandPending == TRUE) {
+               timeout = interruptible_sleep_on_timeout (&edge_port->wait_command, timeout);
+       }
+
+       if (edge_port->commandPending == TRUE) {
+               /* command timed out */
+               dbg(__FUNCTION__" - command timed out");
+               status = -EINVAL;
+       }
+#endif
+       return status;
+}
+
+
+/*****************************************************************************
+ * send_cmd_write_baud_rate
+ *     this function sends the proper command to change the baud rate of the
+ *     specified port.
+ *****************************************************************************/
+static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate)
+{
+       unsigned char *cmdBuffer;
+       unsigned char *currCmd;
+       int cmdLen = 0;
+       int divisor;
+       int status;
+       unsigned char number = edge_port->port->number;
+
+       dbg(__FUNCTION__" - port = %d, baud = %d", number, baudRate);
+
+       status = calc_baud_rate_divisor (baudRate, &divisor);
+       if (status) {
+               err(__FUNCTION__" - bad baud rate");
+               return status;
+       }
+
+       // Alloc memory for the string of commands.
+       cmdBuffer =  kmalloc (0x100, GFP_KERNEL);
+       if (!cmdBuffer) {
+               err(__FUNCTION__" - kmalloc(%d) failed.\n", 0x100);
+               return -ENOMEM;
+       }
+       currCmd = cmdBuffer;
+
+       // Enable access to divisor latch
+       MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, LCR_DL_ENABLE );
+
+       // Write the divisor itself
+       MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, DLL, LOW8 (divisor) );
+       MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, DLM, HIGH8(divisor) );
+
+       // Restore original value to disable access to divisor latch
+       MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, edge_port->shadowLCR);
+
+       status = write_cmd_usb(edge_port, cmdBuffer, cmdLen );
+
+       return status;
+}
+
+
+/*****************************************************************************
+ * calc_baud_rate_divisor
+ *     this function calculates the proper baud rate divisor for the specified
+ *     baud rate.
+ *****************************************************************************/
+static int calc_baud_rate_divisor (int baudrate, int *divisor)
+{
+       int i;
+       __u16 custom;
+       __u16 round1;
+       __u16 round;
+
+
+       dbg(__FUNCTION__" - %d", baudrate);
+
+       for (i = 0; i < NUM_ENTRIES(DivisorTable); i++) {
+               if ( DivisorTable[i].BaudRate == baudrate ) {
+                       *divisor = DivisorTable[i].Divisor;
+                       return 0;
+               }
+       }
+
+       // We have tried all of the standard baud rates
+       // lets try to calculate the divisor for this baud rate
+       // Make sure the baud rate is reasonable
+       if (baudrate > 75 &&  baudrate < 230400) {
+               // get divisor
+               custom = (__u16)(230400L  / baudrate);
+
+               // Check for round off
+               round1 = (__u16)(2304000L / baudrate);
+               round = (__u16)(round1 - (custom * 10));
+               if (round > 4) {
+                       custom++;
+               }
+               *divisor = custom;
+
+               dbg(__FUNCTION__" - Baud %d = %d\n", baudrate, custom);
+               return 0;
+       }
+
+       return -1;
+}
+
+
+/*****************************************************************************
+ * send_cmd_write_uart_register
+ *     this function builds up a uart register message and sends to to the device.
+ *****************************************************************************/
+static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue)
+{
+       unsigned char *cmdBuffer;
+       unsigned char *currCmd;
+       unsigned long cmdLen = 0;
+       int status;
+
+       dbg (__FUNCTION__" - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", regValue);
+
+       // Alloc memory for the string of commands.
+       cmdBuffer = kmalloc (0x10, GFP_KERNEL);
+       if (cmdBuffer == NULL ) {
+               return -ENOMEM;
+       }
+
+       currCmd = cmdBuffer;
+
+       // Build a cmd in the buffer to write the given register
+       MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, edge_port->port->number, regNum, regValue);
+
+       status = write_cmd_usb(edge_port, cmdBuffer, cmdLen);
+
+       return status;
+}
+
+
+/*****************************************************************************
+ * change_port_settings
+ *     This routine is called to set the UART on the device to match the specified
+ *     new settings.
+ *****************************************************************************/
+static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios)
+{
+       struct tty_struct *tty;
+       int baud;
+       unsigned cflag;
+       __u8 mask = 0xff;
+       __u8 lData;
+       __u8 lParity;
+       __u8 lStop;
+       __u8 rxFlow;
+       __u8 txFlow;
+       int status;
+
+       dbg(__FUNCTION__" - port %d", edge_port->port->number);
+
+       if ((!edge_port->open) &&
+           (!edge_port->openPending)) {
+               dbg(__FUNCTION__" - port not opened");
+               return;
+       }
+
+       tty = edge_port->port->tty;
+       if ((!tty) ||
+           (!tty->termios)) {
+               dbg(__FUNCTION__" - no tty structures");
+               return;
+       }
+
+       cflag = tty->termios->c_cflag;
+
+       switch (cflag & CSIZE) {
+               case CS5:   lData = LCR_BITS_5; mask = 0x1f;    dbg(__FUNCTION__" - data bits = 5");   break;
+               case CS6:   lData = LCR_BITS_6; mask = 0x3f;    dbg(__FUNCTION__" - data bits = 6");   break;
+               case CS7:   lData = LCR_BITS_7; mask = 0x7f;    dbg(__FUNCTION__" - data bits = 7");   break;
+               default:
+               case CS8:   lData = LCR_BITS_8;                 dbg(__FUNCTION__" - data bits = 8");   break;
+       }
+
+       lParity = LCR_PAR_NONE;
+       if (cflag & PARENB) {
+               if (cflag & PARODD) {
+                       lParity = LCR_PAR_ODD;
+                       dbg(__FUNCTION__" - parity = odd");
+               } else {
+                       lParity = LCR_PAR_EVEN;
+                       dbg(__FUNCTION__" - parity = even");
+               }
+       } else {
+               dbg(__FUNCTION__" - parity = none");
+       }
+
+       if (cflag & CSTOPB) {
+               lStop = LCR_STOP_2;
+               dbg(__FUNCTION__" - stop bits = 2");
+       } else {
+               lStop = LCR_STOP_1;
+               dbg(__FUNCTION__" - stop bits = 1");
+       }
+
+       /* figure out the flow control settings */
+       rxFlow = txFlow = 0x00;
+       if (cflag & CRTSCTS) {
+               rxFlow |= IOSP_RX_FLOW_RTS;
+               txFlow |= IOSP_TX_FLOW_CTS;
+               dbg(__FUNCTION__" - RTS/CTS is enabled");
+       } else {
+               dbg(__FUNCTION__" - RTS/CTS is disabled");
+       }
+
+       /* if we are implementing XON/XOFF, set the start and stop character in the device */
+       if (I_IXOFF(tty) || I_IXON(tty)) {
+               unsigned char stop_char  = STOP_CHAR(tty);
+               unsigned char start_char = START_CHAR(tty);
+
+               {
+                       send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XON_CHAR, start_char);
+                       send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char);
+               }
+
+               /* if we are implementing INBOUND XON/XOFF */
+               if (I_IXOFF(tty)) {
+                       rxFlow |= IOSP_RX_FLOW_XON_XOFF;
+                       dbg(__FUNCTION__" - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", start_char, stop_char);
+               } else {
+                       dbg(__FUNCTION__" - INBOUND XON/XOFF is disabled");
+               }
+
+               /* if we are implementing OUTBOUND XON/XOFF */
+               if (I_IXON(tty)) {
+                       txFlow |= IOSP_TX_FLOW_XON_XOFF;
+                       dbg(__FUNCTION__" - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", start_char, stop_char);
+               } else {
+                       dbg(__FUNCTION__" - OUTBOUND XON/XOFF is disabled");
+               }
+       }
+
+       /* Set flow control to the configured value */
+       send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_RX_FLOW, rxFlow);
+       send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_TX_FLOW, txFlow);
+
+
+       edge_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
+       edge_port->shadowLCR |= (lData | lParity | lStop);
+
+       edge_port->validDataMask = mask;
+
+       /* Send the updated LCR value to the EdgePort */
+       status = send_cmd_write_uart_register(edge_port, LCR, edge_port->shadowLCR);
+       if (status != 0) {
+               return;
+       }
+
+       /* set up the MCR register and send it to the EdgePort */
+       edge_port->shadowMCR = MCR_MASTER_IE;
+       if (cflag & CBAUD) {
+               edge_port->shadowMCR |= (MCR_DTR | MCR_RTS);
+       }
+       status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
+       if (status != 0) {
+               return;
+       }
+
+       /* Determine divisor based on baud rate */
+       baud = tty_get_baud_rate(tty);
+       if (!baud) {
+               /* pick a default, any default... */
+               baud = 9600;
+       }
+
+       dbg(__FUNCTION__ " - baud rate = %d", baud);
+       status = send_cmd_write_baud_rate (edge_port, baud);
+
+       return;
+}
+
+
+/****************************************************************************
+ * unicode_to_ascii
+ *     Turns a string from Unicode into ASCII.
+ *     Doesn't do a good job with any characters that are outside the normal
+ *     ASCII range, but it's only for debugging...
+ ****************************************************************************/
+static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
+{
+       int i;
+       for (i = 0; i < unicode_size; ++i) {
+               string[i] = (char)(unicode[i]);
+       }
+       string[unicode_size] = 0x00;
+}
+
+
+/****************************************************************************
+ * get_manufacturing_desc
+ *     reads in the manufacturing descriptor and stores it into the serial 
+ *     structure.
+ ****************************************************************************/
+static void get_manufacturing_desc (struct edgeport_serial *edge_serial)
+{
+       int response;
+
+       dbg("getting manufacturer descriptor");
+
+       response = rom_read (edge_serial->serial, (EDGE_MANUF_DESC_ADDR & 0xffff0000) >> 16, 
+                           (__u16)(EDGE_MANUF_DESC_ADDR & 0x0000ffff), EDGE_MANUF_DESC_LEN,
+                           (__u8 *)(&edge_serial->manuf_descriptor));
+
+       if (response < 1) {
+               err("error in getting manufacturer descriptor");
+       } else {
+               char string[30];
+               dbg("**Manufacturer Descriptor");
+               dbg("  RomSize:        %dK", edge_serial->manuf_descriptor.RomSize);
+               dbg("  RamSize:        %dK", edge_serial->manuf_descriptor.RamSize);
+               dbg("  CpuRev:         %d", edge_serial->manuf_descriptor.CpuRev);
+               dbg("  BoardRev:       %d", edge_serial->manuf_descriptor.BoardRev);
+               dbg("  NumPorts:       %d", edge_serial->manuf_descriptor.NumPorts);
+               dbg("  DescDate:       %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900);
+               unicode_to_ascii (string, edge_serial->manuf_descriptor.SerialNumber, edge_serial->manuf_descriptor.SerNumLength/2-1);
+               dbg("  SerialNumber: %s", string);
+               unicode_to_ascii (string, edge_serial->manuf_descriptor.AssemblyNumber, edge_serial->manuf_descriptor.AssemblyNumLength/2-1);
+               dbg("  AssemblyNumber: %s", string);
+               unicode_to_ascii (string, edge_serial->manuf_descriptor.OemAssyNumber, edge_serial->manuf_descriptor.OemAssyNumLength/2-1);
+               dbg("  OemAssyNumber:  %s", string);
+               dbg("  UartType:       %d", edge_serial->manuf_descriptor.UartType);
+               dbg("  IonPid:         %d", edge_serial->manuf_descriptor.IonPid);
+               dbg("  IonConfig:      %d", edge_serial->manuf_descriptor.IonConfig);
+       }
+}
+
+
+/****************************************************************************
+ * get_boot_desc
+ *     reads in the bootloader descriptor and stores it into the serial 
+ *     structure.
+ ****************************************************************************/
+static void get_boot_desc (struct edgeport_serial *edge_serial)
+{
+       int response;
+
+       dbg("getting boot descriptor");
+
+       response = rom_read (edge_serial->serial, (EDGE_BOOT_DESC_ADDR & 0xffff0000) >> 16, 
+                           (__u16)(EDGE_BOOT_DESC_ADDR & 0x0000ffff), EDGE_BOOT_DESC_LEN,
+                           (__u8 *)(&edge_serial->boot_descriptor));
+
+       if (response < 1) {
+               err("error in getting boot descriptor");
+       } else {
+               dbg("**Boot Descriptor:");
+               dbg("  BootCodeLength: %d", edge_serial->boot_descriptor.BootCodeLength);
+               dbg("  MajorVersion:   %d", edge_serial->boot_descriptor.MajorVersion);
+               dbg("  MinorVersion:   %d", edge_serial->boot_descriptor.MinorVersion);
+               dbg("  BuildNumber:    %d", edge_serial->boot_descriptor.BuildNumber);
+               dbg("  Capabilities:   0x%x", edge_serial->boot_descriptor.Capabilities);
+               dbg("  UConfig0:       %d", edge_serial->boot_descriptor.UConfig0);
+               dbg("  UConfig1:       %d", edge_serial->boot_descriptor.UConfig1);
+       }
+}
+
+
+/****************************************************************************
+ * load_application_firmware
+ *     This is called to load the application firmware to the device
+ ****************************************************************************/
+static void load_application_firmware (struct edgeport_serial *edge_serial)
+{
+       PEDGE_FIRMWARE_IMAGE_RECORD record;
+       unsigned char *firmware;
+       unsigned char *FirmwareImage;
+       int ImageSize;
+       int response;
+
+
+       switch (edge_serial->product_info.iDownloadFile) {
+               case EDGE_DOWNLOAD_FILE_I930:
+                       dbg("downloading firmware version (930) %d.%d.%d", 
+                           OperationalCodeImageVersion_GEN1.MajorVersion, 
+                           OperationalCodeImageVersion_GEN1.MinorVersion, 
+                           OperationalCodeImageVersion_GEN1.BuildNumber);
+                       firmware = &OperationalCodeImage_GEN1[0];
+                       FirmwareImage = &OperationalCodeImage_GEN1[0];
+                       ImageSize = sizeof(OperationalCodeImage_GEN1);
+                       break;
+
+               case EDGE_DOWNLOAD_FILE_80251:
+                       dbg("downloading firmware version (80251) %d.%d.%d", 
+                           OperationalCodeImageVersion_GEN2.MajorVersion, 
+                           OperationalCodeImageVersion_GEN2.MinorVersion, 
+                           OperationalCodeImageVersion_GEN2.BuildNumber);
+                       firmware = &OperationalCodeImage_GEN2[0];
+                       FirmwareImage = &OperationalCodeImage_GEN2[0];
+                       ImageSize = sizeof(OperationalCodeImage_GEN2);
+                       break;
+
+               case EDGE_DOWNLOAD_FILE_NONE:
+                       dbg     ("No download file specified, skipping download\n");
+                       return;
+
+               default:
+                       return;
+       }
+
+
+       for (;;) {
+               record = (PEDGE_FIRMWARE_IMAGE_RECORD)firmware;
+               response = sram_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]);
+               if (response < 0) {
+                       err("sram_write failed (%x, %x, %d)", record->ExtAddr, record->Addr, record->Len);
+                       break;
+               }
+               firmware += sizeof (EDGE_FIRMWARE_IMAGE_RECORD) + record->Len;
+               if (firmware >= &FirmwareImage[ImageSize]) {
+                       break;
+               }
+       }
+
+       dbg("sending exec_dl_code");
+       response = usb_control_msg (edge_serial->serial->dev, 
+                                   usb_sndctrlpipe(edge_serial->serial->dev, 0), 
+                                   USB_REQUEST_ION_EXEC_DL_CODE, 
+                                   0x40, 0x4000, 0x0001, NULL, 0, 3000);
+
+       return;
+}
+
+
+
+
+/****************************************************************************
+ * edge_startup
+ ****************************************************************************/
+static int edge_startup (struct usb_serial *serial)
+{
+       struct edgeport_serial *edge_serial;
+       struct edgeport_port *edge_port;
+       struct usb_device *dev;
+       int i;
+
+       dev = serial->dev;
+
+       /* create our private serial structure */
+       edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL);
+       if (edge_serial == NULL) {
+               err(__FUNCTION__" - Out of memory");
+               return -ENOMEM;
+       }
+       memset (edge_serial, 0, sizeof(struct edgeport_serial));
+       edge_serial->serial = serial;
+       serial->private = edge_serial;
+
+       /* get the name for the device from the device */
+       if ( (i = get_string(dev, dev->descriptor.iManufacturer, &edge_serial->name[0])) != 0) {
+               edge_serial->name[i-1] = ' ';
+       }
+
+       get_string(dev, dev->descriptor.iProduct, &edge_serial->name[i]);
+
+       info("%s detected", edge_serial->name);
+
+       /* get the manufacturing descriptor for this device */
+       get_manufacturing_desc (edge_serial);
+
+       /* get the boot descriptor */
+       get_boot_desc (edge_serial);
+
+       get_product_info(edge_serial);
+
+       /* set the number of ports from the manufacturing description */
+       // FIXME  should we override this???
+       //serial->num_ports = serial->product_info.NumPorts;
+       if (edge_serial->product_info.NumPorts != serial->num_ports) {
+               warn(__FUNCTION__ " - Device Reported %d serial ports vs core thinking we have %d ports, email greg@kroah.com this info.", edge_serial->product_info.NumPorts, serial->num_ports);
+       }
+
+       dbg(__FUNCTION__ " - time 1 %ld", jiffies);
+
+       /* now load the application firmware into this device */
+       load_application_firmware (edge_serial);
+
+       dbg(__FUNCTION__ " - time 2 %ld", jiffies);
+
+       /* Check current Edgeport EEPROM and update if necessary */
+       update_edgeport_E2PROM (edge_serial);
+       
+       dbg(__FUNCTION__ " - time 3 %ld", jiffies);
+
+       /* set the configuration to use #1 */
+//     dbg("set_configuration 1");
+//     usb_set_configuration (dev, 1);
+
+       /* we set up the pointers to the endpoints in the edge_open function, 
+        * as the structures aren't created yet. */
+
+       /* set up our port private structures */
+       for (i = 0; i < serial->num_ports; ++i) {
+               edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
+               if (edge_port == NULL) {
+                       err(__FUNCTION__" - Out of memory");
+                       return -ENOMEM;
+               }
+               memset (edge_port, 0, sizeof(struct edgeport_port));
+               edge_port->port = &serial->port[i];
+               serial->port[i].private = edge_port;
+       }
+       
+       return 0;
+}
+
+
+
+/****************************************************************************
+ * usb_edgeport_disconnect
+ *     This function is called whenever the device is removed from the usb bus.
+ ****************************************************************************/
+//static void usb_edgeport_disconnect (struct usb_device *dev, void *ptr)
+static void edge_shutdown (struct usb_serial *serial)
+{
+       int i;
+
+       dbg (__FUNCTION__);
+
+       /* stop reads and writes on all ports */
+       for (i=0; i < serial->num_ports; ++i) {
+               while (serial->port[i].open_count > 0) {
+                       edge_close (&serial->port[i], NULL);
+               }
+       }
+
+       /* free up any memory that we allocated */
+       // FIXME
+       
+}
+
+
+/****************************************************************************
+ * edgeport_init
+ *     This is called by the module subsystem, or on startup to initialize us
+ ****************************************************************************/
+int __init edgeport_init(void)
+{
+       usb_serial_register (&edgeport_4_device);
+       usb_serial_register (&rapidport_4_device);
+       usb_serial_register (&edgeport_4t_device);
+       usb_serial_register (&edgeport_2_device);
+       usb_serial_register (&edgeport_4i_device);
+       usb_serial_register (&edgeport_2i_device);
+       usb_serial_register (&edgeport_prl_device);
+       usb_serial_register (&edgeport_421_device);
+       usb_serial_register (&edgeport_21_device);
+       usb_serial_register (&edgeport_8dual_device);
+       usb_serial_register (&edgeport_8_device);
+       usb_serial_register (&edgeport_2din_device);
+       usb_serial_register (&edgeport_4din_device);
+       usb_serial_register (&edgeport_16dual_device);
+       usb_serial_register (&edgeport_compat_id_device);
+       usb_serial_register (&edgeport_8i_device);
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
+       return 0;
+}
+
+
+
+/****************************************************************************
+ * edgeport_exit
+ *     Called when the driver is about to be unloaded.
+ ****************************************************************************/
+void __exit edgeport_exit (void)
+{
+       usb_serial_deregister (&edgeport_4_device);
+       usb_serial_deregister (&rapidport_4_device);
+       usb_serial_deregister (&edgeport_4t_device);
+       usb_serial_deregister (&edgeport_2_device);
+       usb_serial_deregister (&edgeport_4i_device);
+       usb_serial_deregister (&edgeport_2i_device);
+       usb_serial_deregister (&edgeport_prl_device);
+       usb_serial_deregister (&edgeport_421_device);
+       usb_serial_deregister (&edgeport_21_device);
+       usb_serial_deregister (&edgeport_8dual_device);
+       usb_serial_deregister (&edgeport_8_device);
+       usb_serial_deregister (&edgeport_2din_device);
+       usb_serial_deregister (&edgeport_4din_device);
+       usb_serial_deregister (&edgeport_16dual_device);
+       usb_serial_deregister (&edgeport_compat_id_device);
+       usb_serial_deregister (&edgeport_8i_device);
+}
+
+module_init(edgeport_init);
+module_exit(edgeport_exit);
+
+/* Module information */
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
diff --git a/drivers/usb/serial/io_edgeport.h b/drivers/usb/serial/io_edgeport.h
new file mode 100644 (file)
index 0000000..03f0328
--- /dev/null
@@ -0,0 +1,152 @@
+/************************************************************************
+ *
+ *     io_edgeport.h   Edgeport Linux Interface definitions
+ *
+ *     Copyright (c) 2000 Inside Out Networks, Inc.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *
+ ************************************************************************/
+
+#if !defined(_IO_EDGEPORT_H_)
+#define        _IO_EDGEPORT_H_
+
+
+#define MAX_RS232_PORTS                8       /* Max # of RS-232 ports per device */
+
+/* typedefs that the insideout headers need */
+#ifndef TRUE
+       #define TRUE            (1)
+#endif
+#ifndef FALSE
+       #define FALSE           (0)
+#endif
+#ifndef MIN
+       #define MIN(a,b)        (((a)<(b))?(a):(b))
+#endif
+#ifndef MAX
+       #define MAX(a,b)        (((a)>(b))?(a):(b))
+#endif
+#ifndef max
+       #define max             MAX
+#endif
+
+#ifndef LOW8
+       #define LOW8(a)         ((unsigned char)(a & 0xff))
+#endif
+#ifndef HIGH8
+       #define HIGH8(a)        ((unsigned char)((a & 0xff00) >> 8))
+#endif
+#ifndef NUM_ENTRIES
+       #define NUM_ENTRIES(x)  (sizeof(x)/sizeof((x)[0]))
+#endif
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+
+#include "io_usbvend.h"
+
+
+
+/* The following table is used to map the USBx port number to 
+ * the device serial number (or physical USB path), */
+#define MAX_EDGEPORTS  64
+
+struct comMapper {
+       char    SerialNumber[MAX_SERIALNUMBER_LEN+1];   /* Serial number/usb path */
+       int     numPorts;                               /* Number of ports */
+       int     Original[MAX_RS232_PORTS];              /* Port numbers set by IOCTL */
+       int     Port[MAX_RS232_PORTS];                  /* Actual used port numbers */
+};
+
+
+#define EDGEPORT_CONFIG_DEVICE "/proc/edgeport"
+
+/* /proc/edgeport Interface
+ * This interface uses read/write/lseek interface to talk to the edgeport driver
+ * the following read functions are supported: */
+#define PROC_GET_MAPPING_TO_PATH       1
+#define PROC_GET_COM_ENTRY             2
+#define PROC_GET_EDGE_MANUF_DESCRIPTOR 3
+#define PROC_GET_BOOT_DESCRIPTOR       4
+#define PROC_GET_PRODUCT_INFO          5
+#define PROC_GET_STRINGS               6
+#define PROC_GET_CURRENT_COM_MAPPING   7
+
+/* The parameters to the lseek() for the read is: */
+#define PROC_READ_SETUP(Command, Argument)     ((Command) + ((Argument)<<8))
+
+
+/* the following write functions are supported: */
+#define PROC_SET_COM_MAPPING           1
+#define PROC_SET_COM_ENTRY             2
+
+
+/* The following sturcture is passed to the write */
+struct procWrite {
+       int     Command;
+       union {
+               struct comMapper        Entry;
+               int                     ComMappingBasedOnUSBPort;       /* Boolean value */
+       } u;
+};
+
+/*
+ *     Product information read from the Edgeport
+ */
+struct edgeport_product_info {
+       __u16   ProductId;                      /* Product Identifier */
+       __u8    NumPorts;                       /* Number of ports on edgeport */
+       __u8    ProdInfoVer;                    /* What version of structure is this? */
+
+       __u32   IsServer        :1;             /* Set if Server */
+       __u32   IsRS232         :1;             /* Set if RS-232 ports exist */
+       __u32   IsRS422         :1;             /* Set if RS-422 ports exist */
+       __u32   IsRS485         :1;             /* Set if RS-485 ports exist */
+       __u32   IsReserved      :28;            /* Reserved for later expansion */
+
+       __u8    RomSize;                        /* Size of ROM/E2PROM in K */
+       __u8    RamSize;                        /* Size of external RAM in K */
+       __u8    CpuRev;                         /* CPU revision level (chg only if s/w visible) */
+       __u8    BoardRev;                       /* PCB revision level (chg only if s/w visible) */
+
+       __u8    BootMajorVersion;               /* Boot Firmware version: xx. */
+       __u8    BootMinorVersion;               /*                        yy. */
+       __u16   BootBuildNumber;                /*                        zzzz (LE format) */
+
+       __u8    FirmwareMajorVersion;           /* Operational Firmware version:xx. */
+       __u8    FirmwareMinorVersion;           /*                              yy. */
+       __u16   FirmwareBuildNumber;            /*                              zzzz (LE format) */
+
+       __u8    ManufactureDescDate[3];         /* MM/DD/YY when descriptor template was compiled */
+       __u8    Unused1[1];                     /* Available */
+
+       __u8    iDownloadFile;                  /* What to download to EPiC device */
+       __u8    Unused2[2];                     /* Available */
+};
+
+/*
+ *     Edgeport Stringblock String locations
+ */
+#define EDGESTRING_MANUFNAME           1       /* Manufacture Name */
+#define EDGESTRING_PRODNAME            2       /* Product Name */
+#define EDGESTRING_SERIALNUM           3       /* Serial Number */
+#define EDGESTRING_ASSEMNUM            4       /* Assembly Number */
+#define EDGESTRING_OEMASSEMNUM         5       /* OEM Assembly Number */
+#define EDGESTRING_MANUFDATE           6       /* Manufacture Date */
+#define EDGESTRING_ORIGSERIALNUM       7       /* Serial Number */
+
+struct string_block {
+       __u16   NumStrings;                     /* Number of strings in block */
+       __u16   Strings[1];                     /* Start of string block */
+};
+
+typedef struct string_block STRING_BLOCK, *PSTRING_BLOCK;
+
+
+#endif
diff --git a/drivers/usb/serial/io_fw_boot.h b/drivers/usb/serial/io_fw_boot.h
new file mode 100644 (file)
index 0000000..844f1c3
--- /dev/null
@@ -0,0 +1,558 @@
+//**************************************************************
+//* Edgeport/4 Binary Image
+//* Generated by HEX2C v1.06
+//* Copyright(c) 1998 Inside Out Networks, All rights reserved.
+//*    This program is free software; you can redistribute it and/or modify
+//*    it under the terms of the GNU General Public License as published by
+//*    the Free Software Foundation; either version 2 of the License, or
+//*    (at your option) any later version.
+//**************************************************************
+
+
+//Image structure definition
+#if !defined(DEFINED_EDGE_FIRMWARE_IMAGE_RECORD)
+#define DEFINED_EDGE_FIRMWARE_IMAGE_RECORD
+       typedef struct _EDGE_FIRMWARE_IMAGE_RECORD
+       {
+               unsigned short ExtAddr;
+               unsigned short Addr;
+               unsigned short Len;
+               unsigned char  Data[0];
+       } EDGE_FIRMWARE_IMAGE_RECORD, *PEDGE_FIRMWARE_IMAGE_RECORD;
+
+       typedef struct _EDGE_FIRMWARE_VERSION_INFO
+       {
+               unsigned char    MajorVersion;
+               unsigned char  MinorVersion;
+               unsigned short BuildNumber;
+       } EDGE_FIRMWARE_VERSION_INFO, *PEDGE_FIRMWARE_VERSION_INFO;
+
+#endif
+
+#if !defined(IMAGE_ARRAY_NAME)
+#define IMAGE_ARRAY_NAME               FirmwareImage
+#define IMAGE_VERSION_NAME     FirmwareImageVersion
+#endif
+
+static unsigned char IMAGE_ARRAY_NAME[] = {
+
+// Segment #1, Start Address 00ff0000, Length 6
+0xff,0x00,0x00,0x00,0x06,0x00,
+    0x02, 0x00, 0x80, 0x02, 0x00, 0x03, 
+
+// Segment #2, Start Address 00ff000b, Length 3
+0xff,0x00,0x0b,0x00,0x03,0x00,
+    0x02, 0x00, 0x0b, 
+
+// Segment #3, Start Address 00ff0013, Length 3
+0xff,0x00,0x13,0x00,0x03,0x00,
+    0x02, 0x01, 0xb8, 
+
+// Segment #4, Start Address 00ff001b, Length 3
+0xff,0x00,0x1b,0x00,0x03,0x00,
+    0x02, 0x00, 0x1b, 
+
+// Segment #5, Start Address 00ff0023, Length 3
+0xff,0x00,0x23,0x00,0x03,0x00,
+    0x02, 0x00, 0x23, 
+
+// Segment #6, Start Address 00ff002b, Length 3
+0xff,0x00,0x2b,0x00,0x03,0x00,
+    0x02, 0x00, 0x2b, 
+
+// Segment #7, Start Address 00ff0033, Length 3
+0xff,0x00,0x33,0x00,0x03,0x00,
+    0x02, 0x00, 0x33, 
+
+// Segment #8, Start Address 00ff003b, Length 3
+0xff,0x00,0x3b,0x00,0x03,0x00,
+    0x02, 0x00, 0x3b, 
+
+// Segment #9, Start Address 00ff0043, Length 3
+0xff,0x00,0x43,0x00,0x03,0x00,
+    0x02, 0x01, 0xbd, 
+
+// Segment #10, Start Address 00ff004b, Length 3
+0xff,0x00,0x4b,0x00,0x03,0x00,
+    0x02, 0x01, 0xd0, 
+
+// Segment #11, Start Address 00ff0053, Length 3
+0xff,0x00,0x53,0x00,0x03,0x00,
+    0x02, 0x01, 0x21, 
+
+// Segment #12, Start Address 00ff007b, Length 3
+0xff,0x00,0x7b,0x00,0x03,0x00,
+    0x02, 0x00, 0x7b, 
+
+// Segment #13, Start Address 00ff0080, Length 358
+0xff,0x00,0x80,0x00,0x66,0x01,
+    0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x3f, 0xf2, 0x7e, 0xf8, 0x00, 0x23, 0x7e, 0x00, 0x01, 0x7e, 0x10, 
+    0x00, 0x12, 0x07, 0x5f, 0x69, 0x20, 0x00, 0x0a, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x05, 0x75, 0x90, 
+    0x0d, 0x80, 0x03, 0x75, 0x90, 0x1d, 0xd2, 0xb5, 0x7e, 0x00, 0x00, 0xa5, 0xd8, 0xfd, 0x75, 0xa8, 
+    0x00, 0x75, 0xb1, 0x00, 0xa9, 0xd5, 0x87, 0xca, 0x29, 0x12, 0x09, 0xcc, 0x12, 0x09, 0xa0, 0xf5, 
+    0x09, 0x7a, 0xa1, 0x20, 0x12, 0x01, 0xe6, 0xda, 0x29, 0xa9, 0xd0, 0xc7, 0x7e, 0x00, 0x05, 0x7a, 
+    0x01, 0xf1, 0x75, 0xe1, 0x10, 0xa9, 0xd7, 0xf4, 0xa9, 0xd7, 0xe4, 0xa5, 0xd8, 0xf1, 0x75, 0xf1, 
+    0x00, 0x75, 0xe1, 0x3f, 0x75, 0xa2, 0x03, 0x75, 0xa3, 0x00, 0x75, 0xc0, 0x00, 0x75, 0xc1, 0x00, 
+    0xa9, 0xd1, 0xb1, 0xa9, 0xd0, 0xb1, 0xa9, 0xd5, 0xd3, 0xd2, 0xaf, 0xe4, 0x7e, 0x04, 0x28, 0x00, 
+    0x8d, 0xef, 0x1b, 0x04, 0x78, 0xfa, 0x04, 0xa9, 0x34, 0xd3, 0x03, 0x30, 0xe0, 0xee, 0xbe, 0x24, 
+    0x00, 0x00, 0x78, 0x05, 0x63, 0x90, 0x30, 0x80, 0xe3, 0xb2, 0x95, 0x80, 0xdf, 0xbe, 0xb0, 0x02, 
+    0x22, 0xc0, 0xd0, 0xa9, 0x20, 0xdf, 0x0f, 0xa9, 0x31, 0xdf, 0x03, 0x02, 0x01, 0xb5, 0x75, 0x08, 
+    0x01, 0x12, 0x08, 0x33, 0x80, 0xfe, 0x75, 0x08, 0xfe, 0x12, 0x08, 0x33, 0x75, 0xa8, 0x00, 0x7e, 
+    0xb3, 0x3f, 0xf2, 0x30, 0xe0, 0x4b, 0x30, 0x01, 0x46, 0xc2, 0x92, 0x7e, 0x24, 0x80, 0x00, 0x7e, 
+    0x11, 0x09, 0x74, 0x08, 0x19, 0xb2, 0x00, 0x10, 0x74, 0x0e, 0x19, 0xb2, 0x00, 0x04, 0x2e, 0x24, 
+    0x01, 0x00, 0xa5, 0xd9, 0xed, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 0xe4, 0xd5, 0xe0, 0xfd, 
+    0x09, 0xb2, 0x00, 0x08, 0x20, 0xe0, 0x0a, 0x09, 0xb2, 0x00, 0x00, 0x09, 0xb2, 0x00, 0x18, 0x80, 
+    0xeb, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xe4, 0x43, 0x90, 0x30, 0xd2, 0xaa, 0x80, 0x05, 0xd2, 
+    0xaa, 0x43, 0x90, 0x34, 0xd2, 0xaf, 0xa9, 0xd1, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x11, 
+    0xdf, 0x03, 0xa9, 0xd2, 0xdf, 0x75, 0x08, 0xff, 0x12, 0x08, 0x33, 0xc0, 0xd1, 0xca, 0x02, 0xff, 
+    0xca, 0x06, 0x83, 0x00, 0x32, 0xd0, 0xd0, 0x32, 0xc2, 0x8b, 0xc2, 0xaa, 0x32, 0x75, 0x08, 0x08, 
+    0x12, 0x08, 0x33, 0xa9, 0xc0, 0xb1, 0xa9, 0xc5, 0xd3, 0xa9, 0xc6, 0xd3, 0xa9, 0xd2, 0xb1, 0x32, 
+    0xca, 0xb8, 0x75, 0x08, 0x02, 0x12, 0x08, 0x33, 0xe5, 0xc0, 0x54, 0x03, 0x68, 0x05, 0x12, 0x01, 
+    0xee, 0x80, 0xf5, 0xda, 0xb8, 0x32, 
+
+// Segment #14, Start Address 00ff1bca, Length 1
+0xff,0x00,0xca,0x1b,0x01,0x00,
+    0x00, 
+
+// Segment #15, Start Address 00ff01e6, Length 1613
+0xff,0x00,0xe6,0x01,0x4d,0x06,
+    0xe4, 0x7a, 0xb3, 0x3f, 0xf1, 0x02, 0x02, 0x63, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xca, 0x3b, 
+    0xca, 0x4b, 0xca, 0x5b, 0xca, 0x6b, 0xca, 0x7b, 0xca, 0xeb, 0xc0, 0xf1, 0x7e, 0xb3, 0x01, 0x2b, 
+    0xb4, 0x00, 0x02, 0x80, 0x19, 0xb4, 0x01, 0x16, 0x30, 0xc0, 0x08, 0x75, 0xf1, 0x00, 0x12, 0x02, 
+    0x4d, 0x80, 0x1f, 0x30, 0xc1, 0x1c, 0x75, 0xf1, 0x00, 0x12, 0x02, 0xde, 0x80, 0x14, 0x30, 0xc1, 
+    0x08, 0x75, 0xf1, 0x00, 0x12, 0x02, 0xde, 0x80, 0x09, 0x30, 0xc0, 0x06, 0x75, 0xf1, 0x00, 0x12, 
+    0x02, 0x4d, 0xd0, 0xf1, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 0xda, 0x5b, 0xda, 0x4b, 0xda, 0x3b, 
+    0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0xc2, 0xc0, 0x7e, 0xb3, 0x01, 0x2b, 0xb4, 0x02, 0x07, 
+    0x12, 0x02, 0x6f, 0x02, 0x02, 0x63, 0x22, 0xb4, 0x01, 0xfc, 0x02, 0x02, 0xa9, 0x7e, 0x00, 0x00, 
+    0x7a, 0x03, 0x01, 0x2b, 0x7a, 0x03, 0x01, 0x2c, 0x22, 0x7e, 0xb3, 0x01, 0x23, 0x54, 0x60, 0x60, 
+    0x05, 0xb4, 0x40, 0x15, 0x80, 0x13, 0x7e, 0xb3, 0x01, 0x24, 0xb4, 0x05, 0x0c, 0x75, 0x08, 0x71, 
+    0x12, 0x08, 0x33, 0x7e, 0xb3, 0x01, 0x26, 0xf5, 0x8f, 0x22, 0x75, 0xf6, 0x00, 0x22, 0xbe, 0x57, 
+    0x01, 0x29, 0x28, 0x04, 0x7e, 0x57, 0x01, 0x29, 0x7a, 0x0f, 0x01, 0x2e, 0x7a, 0x57, 0x01, 0x32, 
+    0x02, 0x02, 0xa9, 0x7e, 0xef, 0x01, 0x2e, 0x7e, 0xf7, 0x01, 0x32, 0x7e, 0x07, 0x01, 0x32, 0x4d, 
+    0x00, 0x68, 0x21, 0x7e, 0x00, 0x00, 0x7e, 0xeb, 0xb0, 0xf5, 0xf3, 0xa3, 0xa5, 0x08, 0x1b, 0xf4, 
+    0x68, 0x04, 0xa5, 0xb8, 0x08, 0xf0, 0x7a, 0xef, 0x01, 0x2e, 0x7a, 0xf7, 0x01, 0x32, 0x75, 0x08, 
+    0x06, 0x12, 0x08, 0x33, 0x7a, 0x01, 0xf6, 0x22, 0xc2, 0xc1, 0x75, 0x08, 0x03, 0x12, 0x08, 0x33, 
+    0xa9, 0x36, 0xe2, 0x16, 0xe5, 0xf5, 0x54, 0xc0, 0x68, 0x07, 0xa9, 0xd7, 0xf4, 0xa9, 0x27, 0xf4, 
+    0xfc, 0x53, 0xe1, 0x3f, 0x43, 0xf2, 0x88, 0x02, 0x03, 0x55, 0x7e, 0xb3, 0x01, 0x2c, 0xb4, 0x02, 
+    0x0f, 0xa9, 0xd4, 0xe4, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x01, 0x2c, 0x7a, 0xb3, 0x01, 0x2b, 0x22, 
+    0xb4, 0x01, 0x39, 0x7e, 0x21, 0xe6, 0x7c, 0x32, 0x7e, 0x13, 0x01, 0x2d, 0x2c, 0x21, 0x7a, 0x23, 
+    0x01, 0x2d, 0x7e, 0x00, 0x00, 0x2e, 0x04, 0x01, 0x34, 0xe5, 0xe3, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 
+    0xa5, 0xdb, 0xf6, 0xa9, 0xd4, 0xe4, 0x75, 0x08, 0x70, 0x12, 0x08, 0x33, 0x7e, 0xb3, 0x01, 0x2d, 
+    0x7e, 0xa3, 0x01, 0x2a, 0xbc, 0xab, 0x78, 0x03, 0x12, 0x03, 0xec, 0x22, 0x02, 0x07, 0x55, 0xe5, 
+    0xe6, 0xb4, 0x08, 0x65, 0xa9, 0xc4, 0xe2, 0x7e, 0x01, 0xe3, 0x7e, 0x11, 0xe3, 0x7e, 0x31, 0xe3, 
+    0x7e, 0x21, 0xe3, 0x7e, 0x51, 0xe3, 0x7e, 0x41, 0xe3, 0x7e, 0x71, 0xe3, 0x7e, 0x61, 0xe3, 0x7a, 
+    0x0f, 0x01, 0x23, 0x7a, 0x1f, 0x01, 0x27, 0x75, 0x08, 0x04, 0x12, 0x08, 0x33, 0x7a, 0x01, 0x08, 
+    0x12, 0x08, 0x33, 0x7a, 0x11, 0x08, 0x12, 0x08, 0x33, 0x7a, 0x21, 0x08, 0x12, 0x08, 0x33, 0x7a, 
+    0x31, 0x08, 0x12, 0x08, 0x33, 0x7a, 0x41, 0x08, 0x12, 0x08, 0x33, 0x7a, 0x51, 0x08, 0x12, 0x08, 
+    0x33, 0x7a, 0x61, 0x08, 0x12, 0x08, 0x33, 0x7a, 0x71, 0x08, 0x12, 0x08, 0x33, 0xa9, 0xd4, 0xe4, 
+    0xa9, 0xd7, 0xf4, 0xa9, 0xc6, 0xe2, 0x12, 0x03, 0xc0, 0x22, 0x6d, 0x00, 0x7e, 0x14, 0x01, 0x02, 
+    0x7a, 0x07, 0x01, 0x32, 0x7a, 0x03, 0x01, 0x2d, 0x7e, 0xb3, 0x01, 0x23, 0x20, 0xe7, 0x0f, 0x7a, 
+    0x23, 0x01, 0x2c, 0x7a, 0x33, 0x01, 0x2b, 0xbe, 0x07, 0x01, 0x29, 0x68, 0x09, 0x22, 0x7a, 0x33, 
+    0x01, 0x2c, 0x7a, 0x23, 0x01, 0x2b, 0x7e, 0xb3, 0x01, 0x23, 0x54, 0xe3, 0x23, 0x23, 0x30, 0xe0, 
+    0x02, 0xd2, 0xe5, 0x30, 0xe7, 0x02, 0xd2, 0xe4, 0x30, 0xe5, 0x06, 0x30, 0xe4, 0x03, 0x02, 0x07, 
+    0x55, 0x54, 0x3e, 0xf5, 0xf0, 0x03, 0x54, 0x1f, 0xc3, 0x25, 0xf0, 0x90, 0x04, 0x18, 0x75, 0x84, 
+    0xff, 0x73, 0x02, 0x05, 0x6c, 0x02, 0x04, 0x60, 0x02, 0x06, 0x09, 0x02, 0x06, 0x24, 0x02, 0x05, 
+    0x05, 0x02, 0x04, 0xc6, 0x02, 0x06, 0x3d, 0x02, 0x06, 0x3d, 0x02, 0x06, 0x40, 0x02, 0x06, 0x40, 
+    0x02, 0x06, 0x40, 0x02, 0x06, 0x40, 0x02, 0x06, 0x40, 0x02, 0x06, 0x40, 0x02, 0x06, 0x40, 0x02, 
+    0x06, 0x40, 0x02, 0x06, 0x46, 0x02, 0x06, 0xfa, 0x02, 0x06, 0x43, 0x02, 0x06, 0x43, 0x02, 0x06, 
+    0x43, 0x02, 0x06, 0x43, 0x02, 0x06, 0x43, 0x02, 0x06, 0x43, 0x7e, 0xb3, 0x01, 0x24, 0xb4, 0x06, 
+    0x2a, 0x7e, 0xb3, 0x01, 0x25, 0x60, 0x56, 0x7c, 0x0b, 0x7e, 0x13, 0x01, 0x26, 0x7e, 0x17, 0x01, 
+    0x27, 0x75, 0x08, 0x72, 0x12, 0x08, 0x33, 0x7a, 0x01, 0x08, 0x12, 0x08, 0x33, 0x7a, 0x11, 0x08, 
+    0x12, 0x08, 0x33, 0x12, 0x07, 0x5f, 0x40, 0x35, 0x02, 0x02, 0x94, 0xb4, 0x08, 0x10, 0x75, 0x08, 
+    0x74, 0x12, 0x08, 0x33, 0x7e, 0xb3, 0x3f, 0xf1, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 0x22, 0xb4, 0x00, 
+    0x1c, 0x75, 0x08, 0x75, 0x12, 0x08, 0x33, 0x7e, 0xb3, 0x3f, 0xf2, 0x30, 0xe0, 0x05, 0x75, 0xf3, 
+    0x02, 0x80, 0x03, 0x75, 0xf3, 0x00, 0x75, 0xf3, 0x00, 0x75, 0xf6, 0x02, 0x22, 0x02, 0x07, 0x55, 
+    0x7e, 0xb3, 0x01, 0x24, 0xb4, 0x00, 0x35, 0x75, 0x08, 0x76, 0x12, 0x08, 0x33, 0x7e, 0xb3, 0x01, 
+    0x28, 0x54, 0x0f, 0xf5, 0xf1, 0x7e, 0xb3, 0x01, 0x28, 0x20, 0xe7, 0x09, 0xe5, 0xe1, 0x30, 0xe7, 
+    0x0d, 0x74, 0x01, 0x80, 0x0b, 0xe5, 0xe1, 0x30, 0xe6, 0x04, 0x74, 0x01, 0x80, 0x02, 0x74, 0x00, 
+    0x53, 0xf1, 0x80, 0xf5, 0xf3, 0x75, 0xf3, 0x00, 0x75, 0xf6, 0x02, 0x22, 0x02, 0x07, 0x55, 0xc0, 
+    0xf1, 0x7e, 0xb3, 0x01, 0x28, 0x54, 0x0f, 0x42, 0xf1, 0x7e, 0xb3, 0x01, 0x26, 0xb4, 0x00, 0x45, 
+    0x7e, 0xb3, 0x01, 0x24, 0xb4, 0x01, 0x24, 0x75, 0x08, 0x77, 0x12, 0x08, 0x33, 0x7e, 0xb3, 0x01, 
+    0x28, 0x54, 0x0f, 0x78, 0x05, 0x53, 0xe1, 0x3f, 0x80, 0x37, 0x7e, 0xb3, 0x01, 0x28, 0x20, 0xe7, 
+    0x05, 0x53, 0xe1, 0x7f, 0x80, 0x2b, 0x53, 0xe1, 0xbf, 0x80, 0x26, 0xb4, 0x03, 0x17, 0x75, 0x08, 
+    0x78, 0x12, 0x08, 0x33, 0x7e, 0xb3, 0x01, 0x28, 0x20, 0xe7, 0x05, 0x43, 0xe1, 0x80, 0x80, 0x11, 
+    0x43, 0xe1, 0x40, 0x80, 0x0c, 0x43, 0xe1, 0xc0, 0xd0, 0xf1, 0x75, 0x08, 0x07, 0x12, 0x08, 0x33, 
+    0x22, 0xd0, 0xf1, 0x02, 0x02, 0x90, 0x7e, 0xb3, 0x01, 0x24, 0xb4, 0x09, 0x23, 0x75, 0x08, 0x79, 
+    0x12, 0x08, 0x33, 0x7e, 0xb3, 0x01, 0x26, 0xbe, 0xb3, 0x3f, 0xf1, 0x68, 0x11, 0xca, 0xb8, 0xc0, 
+    0xf1, 0x12, 0x01, 0x1d, 0xd0, 0xf1, 0xda, 0xb8, 0x50, 0x76, 0x7a, 0xb3, 0x3f, 0xf1, 0x80, 0x6d, 
+    0xb4, 0x05, 0x08, 0x75, 0x08, 0x7a, 0x12, 0x08, 0x33, 0x80, 0x62, 0xb4, 0x03, 0x19, 0x75, 0x08, 
+    0x7b, 0x12, 0x08, 0x33, 0x7e, 0xb3, 0x01, 0x26, 0xb4, 0x01, 0x55, 0x7e, 0xb3, 0x3f, 0xf2, 0x44, 
+    0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x46, 0xb4, 0x01, 0x19, 0x75, 0x08, 0x7c, 0x12, 0x08, 0x33, 
+    0x7e, 0xb3, 0x01, 0x26, 0xb4, 0x01, 0x39, 0x7e, 0xb3, 0x3f, 0xf2, 0x54, 0xfe, 0x7a, 0xb3, 0x3f, 
+    0xf2, 0x80, 0x2a, 0xb4, 0x07, 0x2a, 0x7e, 0xb3, 0x01, 0x25, 0x60, 0x24, 0x7c, 0x0b, 0x7e, 0x13, 
+    0x01, 0x26, 0x7e, 0x17, 0x01, 0x27, 0x75, 0x08, 0x73, 0x12, 0x08, 0x33, 0x7a, 0x01, 0x08, 0x12, 
+    0x08, 0x33, 0x7a, 0x11, 0x08, 0x12, 0x08, 0x33, 0x12, 0x07, 0x8b, 0x40, 0x03, 0x02, 0x02, 0x90, 
+    0x02, 0x07, 0x55, 0x7e, 0xb3, 0x01, 0x24, 0xb4, 0x0b, 0xf6, 0x75, 0x08, 0x7d, 0x12, 0x08, 0x33, 
+    0x7e, 0xb3, 0x01, 0x26, 0x7e, 0xa3, 0x01, 0x28, 0x4c, 0xab, 0x78, 0xe4, 0x80, 0xdf, 0x7e, 0xb3, 
+    0x01, 0x24, 0xb4, 0x0a, 0xdb, 0x75, 0x08, 0x7e, 0x12, 0x08, 0x33, 0x7e, 0xb3, 0x01, 0x26, 0x70, 
+    0xcf, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 0x22, 0x02, 0x07, 0x55, 0x02, 0x07, 0x55, 0x02, 0x07, 0x55, 
+    0x7e, 0xb3, 0x01, 0x24, 0xb4, 0x04, 0x20, 0x75, 0x08, 0xc3, 0x12, 0x08, 0x33, 0x7e, 0x04, 0x00, 
+    0x01, 0x7e, 0x17, 0x01, 0x25, 0x7e, 0x18, 0x01, 0x34, 0x7a, 0x1c, 0x00, 0x00, 0x7e, 0x47, 0x01, 
+    0x29, 0x12, 0x08, 0x3f, 0x02, 0x06, 0xf4, 0xb4, 0x06, 0x3a, 0x75, 0x08, 0xc1, 0x12, 0x08, 0x33, 
+    0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7d, 0xca, 0x7e, 0xd7, 0x01, 0x25, 0x7e, 0x78, 
+    0x01, 0x34, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x01, 0x29, 0x75, 0x08, 0xc1, 0x12, 0x08, 0x33, 
+    0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x08, 0xd6, 0xd0, 0x87, 0xd0, 0xa8, 
+    0x40, 0x4f, 0x80, 0x4a, 0xb4, 0x00, 0x1c, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x02, 0x90, 0xe4, 
+    0x8d, 0xef, 0x8d, 0xef, 0x8d, 0xef, 0xd5, 0xe0, 0xf7, 0xc0, 0xd1, 0xca, 0x02, 0xff, 0xca, 0x06, 
+    0x00, 0x00, 0x32, 0xb4, 0x09, 0x12, 0x7e, 0x57, 0x01, 0x25, 0x4d, 0x55, 0x68, 0x05, 0xa9, 0xd2, 
+    0xb1, 0x80, 0x03, 0xa9, 0xc2, 0xb1, 0x80, 0x16, 0xb4, 0x07, 0x16, 0xc2, 0xaf, 0x7e, 0x07, 0x01, 
+    0x27, 0x7e, 0x17, 0x01, 0x25, 0xc0, 0xd1, 0xca, 0x18, 0xca, 0x38, 0xca, 0x28, 0x32, 0x02, 0x02, 
+    0x90, 0x02, 0x07, 0x55, 0x7e, 0xb3, 0x01, 0x24, 0xb4, 0x03, 0x15, 0x75, 0x08, 0xc2, 0x12, 0x08, 
+    0x33, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x01, 0x25, 0x7e, 0x57, 0x01, 0x29, 0x02, 0x02, 0x94, 
+    0xb4, 0x05, 0x39, 0x75, 0x08, 0xc0, 0x12, 0x08, 0x33, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 
+    0xd5, 0x87, 0x7e, 0x08, 0x01, 0x34, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x37, 
+    0x01, 0x25, 0x7e, 0x47, 0x01, 0x29, 0x12, 0x08, 0x3f, 0xd0, 0x87, 0xd0, 0xa8, 0x7e, 0x08, 0x01, 
+    0x34, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x57, 0x01, 0x29, 0x02, 0x02, 0x94, 0x02, 0x07, 0x55, 0x75, 
+    0x08, 0x07, 0x12, 0x08, 0x33, 0x43, 0xe1, 0xc0, 0x22, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 
+    0xd5, 0x87, 0x12, 0x07, 0xca, 0x40, 0x19, 0x7e, 0x08, 0x01, 0x34, 0x7a, 0x0c, 0x00, 0x00, 0xca, 
+    0x0b, 0xca, 0x49, 0x12, 0x08, 0x3f, 0xda, 0x59, 0xda, 0x0b, 0xd0, 0x87, 0xd0, 0xa8, 0xc3, 0x22, 
+    0xd0, 0x87, 0xd0, 0xa8, 0x22, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x07, 
+    0xca, 0x40, 0x2b, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7f, 0x61, 0x7e, 0x78, 0x01, 
+    0x34, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x01, 0x29, 0xbd, 0x74, 0x78, 0x11, 0x75, 0x08, 0xc1, 
+    0x12, 0x08, 0x33, 0x12, 0x08, 0xd6, 0x40, 0x06, 0xd0, 0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 
+    0xd0, 0xa8, 0xd3, 0x22, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x34, 0x7f, 0xca, 0x0b, 0x1a, 0x50, 0xc5, 
+    0xf0, 0x7d, 0x62, 0x7d, 0x75, 0x7d, 0x87, 0x7e, 0x34, 0x7f, 0x03, 0x7e, 0x1b, 0xb0, 0xbc, 0x0b, 
+    0x50, 0x49, 0x3e, 0x00, 0x3e, 0x00, 0x0a, 0x50, 0x2d, 0x75, 0x0b, 0x3a, 0x30, 0x69, 0x53, 0x00, 
+    0x02, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbc, 0x1b, 0x50, 0x30, 0x3e, 0x10, 0x3e, 0x10, 0x0a, 
+    0x51, 0x2d, 0x35, 0x69, 0x41, 0x00, 0x02, 0x0b, 0x1a, 0x30, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 
+    0xbe, 0x44, 0xff, 0xff, 0x78, 0x05, 0x7e, 0x1b, 0x90, 0x0a, 0x49, 0x4d, 0x44, 0x68, 0x0c, 0xbe, 
+    0x44, 0x00, 0xff, 0x28, 0x04, 0x7e, 0x44, 0x00, 0xff, 0xc3, 0x22, 0xd3, 0x22, 
+
+// Segment #16, EXCLUDED Start Address 00ff7c00, Length 199
+
+
+// Segment #17, EXCLUDED Start Address 00ff7f00, Length 192
+
+
+// Segment #17, Start Address 00ff7fc0, Length 64
+0xff,0x00,0xc0,0x7f,0x40,0x00,
+    0x40, 0x01, 0x02, 0x00, 0xca, 0x1b, 0x01, 0x0c, 0x02, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x01, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+
+// Segment #18, Start Address 00ff0833, Length 5015
+0xff,0x00,0x33,0x08,0x97,0x13,
+    0xca, 0x08, 0x7e, 0x01, 0x08, 0x7a, 0x03, 0x3f, 0xf0, 0xda, 0x08, 0x22, 0x80, 0x50, 0x0b, 0x1a, 
+    0x60, 0x0b, 0x35, 0x0b, 0x1a, 0x70, 0x0b, 0x35, 0x0b, 0x1a, 0x80, 0x0b, 0x35, 0x0b, 0x1a, 0x90, 
+    0x0b, 0x35, 0x0b, 0x1a, 0xa0, 0x0b, 0x35, 0x0b, 0x1a, 0xb0, 0x0b, 0x35, 0x0b, 0x1a, 0xc0, 0x0b, 
+    0x35, 0x0b, 0x1a, 0xd0, 0x0b, 0x35, 0x1b, 0x0a, 0x60, 0x0b, 0x15, 0x1b, 0x0a, 0x70, 0x0b, 0x15, 
+    0x1b, 0x0a, 0x80, 0x0b, 0x15, 0x1b, 0x0a, 0x90, 0x0b, 0x15, 0x1b, 0x0a, 0xa0, 0x0b, 0x15, 0x1b, 
+    0x0a, 0xb0, 0x0b, 0x15, 0x1b, 0x0a, 0xc0, 0x0b, 0x15, 0x1b, 0x0a, 0xd0, 0x0b, 0x15, 0x9e, 0x44, 
+    0x00, 0x10, 0x50, 0xaa, 0x2e, 0x44, 0x00, 0x10, 0x68, 0x0e, 0x7e, 0x1b, 0xc0, 0x7a, 0x0b, 0xc0, 
+    0x0b, 0x14, 0x0b, 0x34, 0x1b, 0x44, 0x78, 0xf2, 0x22, 0x7f, 0x6f, 0x7f, 0xf0, 0x1b, 0xfc, 0x7c, 
+    0x54, 0x7d, 0x32, 0x80, 0x08, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0x9e, 0x44, 0x00, 
+    0x10, 0x50, 0xf2, 0x2e, 0x44, 0x00, 0x10, 0x68, 0x06, 0xca, 0x48, 0x1b, 0x44, 0x78, 0xfa, 0x7f, 
+    0xf6, 0x89, 0xe4, 0xca, 0x6b, 0x5e, 0xd4, 0x00, 0x3f, 0x68, 0x20, 0x7e, 0x84, 0x00, 0x40, 0x9d, 
+    0x8d, 0xda, 0x6b, 0xbd, 0x87, 0x38, 0x16, 0xca, 0x79, 0x7d, 0x78, 0x12, 0x09, 0x00, 0xda, 0x79, 
+    0x40, 0x08, 0x9d, 0x78, 0x68, 0x02, 0x80, 0x05, 0xc2, 0xd7, 0x22, 0xda, 0x6b, 0x43, 0x90, 0x30, 
+    0x74, 0xaa, 0x39, 0xb5, 0x55, 0x55, 0x74, 0x55, 0x39, 0xb5, 0x2a, 0xaa, 0x74, 0xa0, 0x39, 0xb5, 
+    0x55, 0x55, 0x7e, 0x04, 0x00, 0x40, 0x9d, 0x70, 0x50, 0x06, 0x2d, 0x70, 0x7d, 0x07, 0x6d, 0x77, 
+    0x7c, 0x31, 0x7e, 0x7b, 0x00, 0x7a, 0x6b, 0x00, 0x0b, 0x7c, 0x0b, 0x6c, 0xa5, 0xd9, 0xf3, 0x7f, 
+    0x16, 0x1b, 0x1c, 0x7e, 0x54, 0x27, 0x10, 0x7e, 0x1b, 0x10, 0xbc, 0x10, 0x68, 0x06, 0x1b, 0x54, 
+    0x78, 0xf5, 0x80, 0x2c, 0x6d, 0x00, 0x7c, 0x20, 0x7f, 0x16, 0x9f, 0x10, 0x7f, 0x27, 0x9f, 0x20, 
+    0x7e, 0x2b, 0x00, 0x7e, 0x1b, 0x10, 0xbc, 0x01, 0x78, 0x16, 0x0b, 0x2c, 0x0b, 0x1c, 0xa5, 0xdb, 
+    0xef, 0x7c, 0xb6, 0x20, 0xe0, 0x03, 0x63, 0x90, 0x30, 0x4d, 0x77, 0x78, 0x93, 0xc2, 0xd7, 0x22, 
+    0xd2, 0xd7, 0x22, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x06, 0x04, 0x02, 0x04, 0x00, 0x02, 0x01, 
+    0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 
+    0x04, 0x00, 0x08, 0x10, 0x02, 0x10, 0x04, 0x02, 0x08, 0x00, 0x01, 0x01, 0x08, 0x7e, 0x18, 0x7f, 
+    0xbd, 0x7a, 0x1c, 0x00, 0xff, 0x0b, 0x1a, 0x00, 0xbe, 0x10, 0x14, 0x38, 0x1a, 0x0a, 0x51, 0x23, 
+    0x7e, 0x18, 0x09, 0x76, 0x7a, 0x1c, 0x00, 0xff, 0x2d, 0x35, 0x0b, 0x1a, 0x50, 0x60, 0x08, 0xa5, 
+    0xb8, 0x02, 0x03, 0x4e, 0xa0, 0x08, 0x22, 0x80, 0xfe, 0x7e, 0xe8, 0x7f, 0xbf, 0x7a, 0xec, 0x00, 
+    0xff, 0xe0, 0xf5, 0x22, 0x54, 0xc0, 0x68, 0x16, 0x7e, 0xe8, 0x7f, 0xbe, 0x7a, 0xec, 0x00, 0xff, 
+    0xe0, 0x60, 0x0c, 0x12, 0x09, 0xa0, 0xf5, 0x09, 0x7a, 0xa1, 0x20, 0x02, 0x0f, 0x0a, 0x22, 0xc2, 
+    0x95, 0xd2, 0x94, 0x12, 0x19, 0xfb, 0x53, 0x90, 0xcf, 0x12, 0x19, 0xfb, 0x80, 0xf1, 0x0d, 0x0a, 
+    0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0d, 
+    0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 
+    0x45, 0x64, 0x67, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x34, 0x20, 0x2d, 0x20, 0x48, 0x61, 0x72, 
+    0x64, 0x77, 0x61, 0x72, 0x65, 0x20, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 
+    0x73, 0x2c, 0x20, 0x52, 0x65, 0x76, 0x20, 0x31, 0x2e, 0x30, 0x30, 0x3b, 0x20, 0x43, 0x6f, 0x70, 
+    0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, 0x39, 0x39, 0x38, 0x20, 0x49, 0x6e, 0x73, 0x69, 
+    0x64, 0x65, 0x20, 0x4f, 0x75, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x0d, 
+    0x0a, 0x00, 0x50, 0x61, 0x73, 0x73, 0x00, 0x46, 0x41, 0x49, 0x4c, 0x20, 0x21, 0x21, 0x00, 0x50, 
+    0x61, 0x73, 0x73, 0x20, 0x20, 0x20, 0x20, 0x00, 0x46, 0x41, 0x49, 0x4c, 0x20, 0x21, 0x21, 0x20, 
+    0x00, 0x0d, 0x0a, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x20, 0x52, 0x61, 0x6d, 0x3a, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x00, 0x0d, 0x0a, 0x52, 0x61, 0x6d, 0x20, 0x54, 0x65, 0x73, 0x74, 0x3a, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x00, 0x0d, 0x0a, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x62, 
+    0x69, 0x74, 0x20, 0x30, 0x2d, 0x31, 0x34, 0x20, 0x74, 0x65, 0x73, 0x74, 0x3a, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x0d, 0x0a, 0x57, 0x72, 0x6f, 0x74, 0x65, 0x20, 0x41, 
+    0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x30, 0x30, 0x3a, 0x00, 0x20, 0x20, 0x77, 0x69, 
+    0x74, 0x68, 0x20, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x20, 0x00, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 
+    0x72, 0x65, 0x61, 0x64, 0x3a, 0x20, 0x00, 0x0d, 0x0a, 0x4f, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 
+    0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 
+    0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x62, 0x69, 
+    0x74, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x68, 
+    0x6f, 0x72, 0x74, 0x65, 0x64, 0x0d, 0x0a, 0x74, 0x6f, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68, 
+    0x69, 0x6e, 0x67, 0x3a, 0x20, 0x00, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x00, 0x0d, 0x0a, 0x44, 0x65, 
+    0x74, 0x65, 0x63, 0x74, 0x20, 0x55, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x0d, 0x0a, 
+    0x53, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x20, 0x50, 0x61, 0x64, 0x2c, 0x46, 0x69, 0x46, 0x6f, 
+    0x20, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x26, 0x20, 0x52, 0x53, 0x54, 0x3a, 0x20, 0x00, 
+    0x0d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x55, 0x61, 0x72, 0x74, 0x20, 0x54, 0x65, 0x73, 0x74, 0x73, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x50, 0x6f, 0x72, 0x74, 0x31, 0x20, 0x20, 0x20, 0x50, 0x6f, 0x72, 0x74, 
+    0x32, 0x20, 0x20, 0x20, 0x50, 0x6f, 0x72, 0x74, 0x33, 0x20, 0x20, 0x20, 0x50, 0x6f, 0x72, 0x74, 
+    0x34, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
+    0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 
+    0x2d, 0x00, 0x0d, 0x0a, 0x50, 0x6f, 0x72, 0x74, 0x20, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x72, 
+    0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x0d, 0x0a, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 
+    0x4c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x0d, 0x0a, 0x41, 0x6e, 0x61, 0x6c, 
+    0x6f, 0x67, 0x20, 0x4c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x0d, 0x0a, 
+    0x52, 0x58, 0x44, 0x2c, 0x54, 0x58, 0x44, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x54, 0x53, 0x2c, 0x43, 
+    0x54, 0x53, 0x2c, 0x52, 0x49, 0x20, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x3a, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x00, 0x0d, 0x0a, 0x52, 0x58, 0x44, 0x2c, 0x54, 0x58, 0x44, 0x20, 0x74, 0x6f, 0x20, 0x44, 
+    0x54, 0x52, 0x2c, 0x44, 0x53, 0x52, 0x2c, 0x43, 0x44, 0x20, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x3a, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x0d, 0x0a, 0x52, 0x54, 0x53, 0x5b, 0x43, 0x54, 0x53, 0x2c, 
+    0x52, 0x49, 0x5d, 0x20, 0x74, 0x6f, 0x20, 0x44, 0x54, 0x52, 0x2c, 0x44, 0x53, 0x52, 0x2c, 0x43, 
+    0x44, 0x20, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x3a, 0x20, 0x00, 0x0d, 0x0a, 0x52, 0x54, 0x53, 0x5b, 
+    0x43, 0x54, 0x53, 0x2c, 0x43, 0x44, 0x5d, 0x20, 0x74, 0x6f, 0x20, 0x44, 0x53, 0x52, 0x2c, 0x52, 
+    0x49, 0x20, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x0d, 0x0a, 
+    0x44, 0x54, 0x52, 0x5b, 0x44, 0x53, 0x52, 0x2c, 0x43, 0x44, 0x5d, 0x20, 0x74, 0x6f, 0x20, 0x52, 
+    0x54, 0x53, 0x2c, 0x43, 0x54, 0x53, 0x2c, 0x52, 0x49, 0x20, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x3a, 
+    0x20, 0x00, 0x0d, 0x0a, 0x44, 0x54, 0x52, 0x20, 0x74, 0x6f, 0x20, 0x43, 0x54, 0x53, 0x2c, 0x43, 
+    0x44, 0x20, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x0d, 0x0a, 0x52, 0x54, 0x53, 0x20, 0x74, 0x6f, 0x20, 0x43, 
+    0x54, 0x53, 0x2c, 0x52, 0x49, 0x20, 0x4c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x0d, 0x0a, 0x52, 0x54, 0x53, 0x20, 
+    0x74, 0x6f, 0x20, 0x43, 0x54, 0x53, 0x2c, 0x43, 0x44, 0x20, 0x4c, 0x6f, 0x6f, 0x70, 0x62, 0x61, 
+    0x63, 0x6b, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x0d, 0x0a, 
+    0x44, 0x54, 0x52, 0x20, 0x74, 0x6f, 0x20, 0x44, 0x53, 0x52, 0x2c, 0x43, 0x44, 0x20, 0x4c, 0x6f, 
+    0x6f, 0x70, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x00, 0x0d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x45, 0x20, 0x52, 0x20, 0x52, 0x20, 0x4f, 0x20, 
+    0x52, 0x20, 0x21, 0x21, 0x21, 0x2c, 0x20, 0x45, 0x20, 0x52, 0x20, 0x52, 0x20, 0x4f, 0x20, 0x52, 
+    0x20, 0x21, 0x21, 0x21, 0x20, 0x2c, 0x20, 0x45, 0x20, 0x52, 0x20, 0x52, 0x20, 0x4f, 0x20, 0x52, 
+    0x20, 0x21, 0x21, 0x21, 0x0d, 0x0a, 0x0a, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 
+    0x63, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x65, 0x6e, 0x74, 0x65, 
+    0x72, 0x20, 0x61, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x20, 0x6c, 0x6f, 0x6f, 0x70, 0x20, 0x6f, 
+    0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x64, 0x65, 0x74, 0x65, 
+    0x63, 0x74, 0x65, 0x64, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x00, 0x0d, 0x0a, 0x0a, 0x4e, 
+    0x6f, 0x20, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 
+    0x73, 0x20, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x2e, 0x0d, 0x0a, 0x00, 0x43, 0x6f, 
+    0x70, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 
+    0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x6c, 0x61, 0x76, 0x65, 0x27, 
+    0x73, 0x20, 0x45, 0x45, 0x70, 0x72, 0x6f, 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x00, 0x44, 0x6f, 0x6e, 
+    0x65, 0x0d, 0x0a, 0x0a, 0x2d, 0x3e, 0x20, 0x54, 0x75, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x69, 0x74, 
+    0x20, 0x6f, 0x66, 0x66, 0x2c, 0x20, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 
+    0x20, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x73, 
+    0x74, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x20, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 
+    0x73, 0x74, 0x69, 0x63, 0x73, 0x2e, 0x00, 0xc2, 0xaf, 0xc2, 0x09, 0xc2, 0x0a, 0x75, 0x90, 0x0d, 
+    0x20, 0x17, 0x02, 0xd2, 0xb5, 0x43, 0x90, 0x30, 0x6c, 0x00, 0x7e, 0x10, 0x03, 0x12, 0x0f, 0x38, 
+    0x7e, 0x68, 0x0a, 0x01, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x0b, 0x00, 0x30, 0xb4, 0x02, 
+    0x80, 0x24, 0x02, 0x1b, 0x3c, 0x20, 0x09, 0x1d, 0xc2, 0x94, 0xd2, 0x95, 0x12, 0x19, 0xfb, 0x53, 
+    0x90, 0xcf, 0x12, 0x19, 0xfb, 0xc2, 0x95, 0xd2, 0x94, 0x12, 0x19, 0xfb, 0xa5, 0xd9, 0xe6, 0x43, 
+    0x90, 0x30, 0x12, 0x19, 0xfb, 0x22, 0x7e, 0x68, 0x0a, 0x94, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 
+    0x93, 0x7e, 0xe4, 0x10, 0x00, 0x7e, 0x40, 0x55, 0x7a, 0xe9, 0x40, 0x0b, 0xe4, 0x7e, 0x50, 0xaa, 
+    0x7a, 0xe9, 0x50, 0x1b, 0xe4, 0xbe, 0xe9, 0x40, 0x68, 0x19, 0x7e, 0x68, 0x0a, 0x7a, 0x7a, 0x6c, 
+    0x00, 0xff, 0x12, 0x1a, 0x93, 0x12, 0x1a, 0x08, 0x30, 0x09, 0x13, 0x7a, 0xe9, 0x40, 0x7e, 0xe9, 
+    0x10, 0x80, 0xf8, 0x7e, 0x68, 0x0a, 0x75, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x0b, 0x00, 
+    0x7e, 0x68, 0x0a, 0xd8, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7e, 0x78, 0x00, 0x00, 0x7e, 
+    0x70, 0x0e, 0x7e, 0xa4, 0xff, 0xff, 0x7e, 0xb4, 0xbf, 0xff, 0x7d, 0xcb, 0x0e, 0xc4, 0x7d, 0xdc, 
+    0x5d, 0xdb, 0x6c, 0xbb, 0x7d, 0xfa, 0x5e, 0xf4, 0x7f, 0xff, 0x7a, 0x7b, 0xb0, 0x0b, 0xb0, 0x7d, 
+    0xfb, 0x5e, 0xf4, 0x7f, 0xff, 0x7a, 0x7b, 0xb0, 0x0b, 0xb0, 0x7d, 0xfc, 0x5e, 0xf4, 0x7f, 0xff, 
+    0x7a, 0x7b, 0xb0, 0x0b, 0xb0, 0x7d, 0xfd, 0x5e, 0xf4, 0x7f, 0xff, 0x7a, 0x7b, 0xb0, 0x6c, 0xbb, 
+    0x7d, 0xfa, 0x5e, 0xf4, 0x7f, 0xff, 0xbe, 0x7b, 0xb0, 0x78, 0x41, 0x0b, 0xb0, 0x7d, 0xfb, 0x5e, 
+    0xf4, 0x7f, 0xff, 0xbe, 0x7b, 0xb0, 0x78, 0x34, 0x0b, 0xb0, 0x7d, 0xfc, 0x5e, 0xf4, 0x7f, 0xff, 
+    0xbe, 0x7b, 0xb0, 0x78, 0x27, 0x0b, 0xb0, 0x7d, 0xfd, 0x5e, 0xf4, 0x7f, 0xff, 0xbe, 0x7b, 0xb0, 
+    0x78, 0x1a, 0x0b, 0xb0, 0xbe, 0xc4, 0xff, 0xfe, 0x78, 0x92, 0x0e, 0xb4, 0xa5, 0xdf, 0x8b, 0x7e, 
+    0x68, 0x0a, 0x82, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x80, 0x77, 0xca, 0x5b, 0xca, 0x6b, 
+    0x7e, 0x68, 0x0a, 0x8b, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7e, 0x68, 0x0b, 0x2a, 0x7a, 
+    0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x0a, 0x47, 0x12, 0x1a, 0xc9, 0x7e, 0x68, 0x0b, 0x79, 0x7a, 
+    0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x6c, 0x77, 0xda, 0x6b, 0xca, 0x6b, 0x0b, 0x70, 0x0e, 0xc4, 
+    0xbe, 0xc4, 0xff, 0xff, 0x78, 0xf6, 0x1b, 0x70, 0x0a, 0x47, 0x12, 0x1a, 0xc9, 0x12, 0x1a, 0x08, 
+    0x30, 0x09, 0x30, 0xda, 0x6b, 0xda, 0x5b, 0x6c, 0xbb, 0x7e, 0x78, 0x00, 0x00, 0x7d, 0xfa, 0x5e, 
+    0xf4, 0x7f, 0xff, 0x7a, 0x7b, 0xb0, 0x7d, 0xfb, 0x5e, 0xf4, 0x7f, 0xff, 0x7a, 0x7b, 0xb0, 0x7d, 
+    0xfc, 0x5e, 0xf4, 0x7f, 0xff, 0x7a, 0x7b, 0xb0, 0x7d, 0xfd, 0x5e, 0xf4, 0x7f, 0xff, 0x7a, 0x7b, 
+    0xb0, 0x80, 0xd4, 0x7e, 0x68, 0x0a, 0xb6, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x30, 0x17, 
+    0x0e, 0x7e, 0x78, 0x04, 0x20, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x44, 0x7b, 0xe0, 0x80, 0x0c, 0x7e, 
+    0x78, 0x00, 0x00, 0x7a, 0x7c, 0x00, 0x01, 0x7e, 0x44, 0x80, 0x00, 0x0b, 0x00, 0x7e, 0x40, 0x3a, 
+    0x7c, 0x54, 0x7f, 0x57, 0x7d, 0x84, 0x6c, 0x66, 0x7a, 0x5b, 0x50, 0x0b, 0x5c, 0x0b, 0x50, 0xa5, 
+    0xde, 0x02, 0x0b, 0x50, 0x1b, 0x84, 0x78, 0xf0, 0x7c, 0x54, 0x7f, 0x57, 0x7d, 0x84, 0x6c, 0x66, 
+    0xbe, 0x5b, 0x50, 0x78, 0x1a, 0x0b, 0x5c, 0x0b, 0x50, 0xa5, 0xde, 0x02, 0x0b, 0x50, 0x1b, 0x84, 
+    0x78, 0xee, 0x7e, 0x68, 0x0a, 0x75, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x80, 0x4b, 0x7f, 
+    0x45, 0x7e, 0x68, 0x0a, 0x7a, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7e, 0x68, 0x0a, 0xfa, 
+    0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7d, 0x4b, 0x12, 0x1a, 0xc9, 0x7e, 0x68, 0x0b, 0x0f, 
+    0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x6c, 0x88, 0x7c, 0x95, 0x12, 0x1a, 0xc9, 0x7e, 0x68, 
+    0x0b, 0x1d, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7e, 0x4b, 0x90, 0x12, 0x1a, 0xc9, 0x12, 
+    0x1a, 0x08, 0x30, 0x09, 0x05, 0x7e, 0x4b, 0x90, 0x80, 0xfb, 0x7e, 0x68, 0x0b, 0x7f, 0x7a, 0x6c, 
+    0x00, 0xff, 0x12, 0x1a, 0x93, 0x0b, 0x00, 0xd2, 0x92, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 0x00, 
+    0x08, 0xbe, 0xb0, 0x01, 0x78, 0x0b, 0x09, 0xb2, 0x00, 0x14, 0xbe, 0xb0, 0x60, 0x78, 0x02, 0x80, 
+    0x17, 0x7e, 0x68, 0x0a, 0x7a, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x12, 0x1a, 0x08, 0x30, 
+    0x09, 0x11, 0x09, 0xb2, 0x00, 0x08, 0x80, 0xfa, 0x7e, 0x68, 0x0a, 0x75, 0x7a, 0x6c, 0x00, 0xff, 
+    0x12, 0x1a, 0x93, 0x7e, 0x68, 0x0b, 0xa1, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x0b, 0x00, 
+    0xc2, 0x92, 0x12, 0x19, 0xee, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0xa0, 0x55, 0x19, 0xa2, 0x00, 0x1c, 
+    0x7e, 0xb0, 0x01, 0x19, 0xb2, 0x00, 0x08, 0x09, 0xb2, 0x00, 0x1c, 0xbc, 0xab, 0x78, 0x37, 0x09, 
+    0xb2, 0x00, 0x08, 0x5e, 0xb0, 0xc0, 0xbe, 0xb0, 0xc0, 0x78, 0x2b, 0x7e, 0xa0, 0xaa, 0x19, 0xa2, 
+    0x00, 0x1c, 0x6c, 0xbb, 0x19, 0xb2, 0x00, 0x08, 0x09, 0xb2, 0x00, 0x1c, 0xbc, 0xab, 0x78, 0x16, 
+    0x09, 0xb2, 0x00, 0x08, 0x5e, 0xb0, 0xc0, 0x78, 0x0d, 0x7e, 0x68, 0x0a, 0x75, 0x7a, 0x6c, 0x00, 
+    0xff, 0x12, 0x1a, 0x93, 0x80, 0x1b, 0x7e, 0x68, 0x0a, 0x7a, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 
+    0x93, 0x12, 0x1a, 0x08, 0x30, 0x09, 0x0a, 0x19, 0xa2, 0x00, 0x1c, 0x09, 0xb2, 0x00, 0x1c, 0x80, 
+    0xf6, 0x7e, 0x68, 0x0b, 0xc3, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7e, 0x68, 0x0c, 0x45, 
+    0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 0x7e, 0xb0, 
+    0x01, 0x19, 0xb2, 0x00, 0x1c, 0x2e, 0x24, 0x01, 0x00, 0x0b, 0xb0, 0xa5, 0xd9, 0xf3, 0x7e, 0x24, 
+    0x80, 0x00, 0x7e, 0x11, 0x09, 0x7e, 0xb0, 0x01, 0x0b, 0x00, 0x09, 0xa2, 0x00, 0x1c, 0xbc, 0xab, 
+    0x78, 0x16, 0x7e, 0x68, 0x0a, 0x82, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x2e, 0x24, 0x01, 
+    0x00, 0x0b, 0xb0, 0xa5, 0xd9, 0xe2, 0x80, 0x25, 0x7e, 0x68, 0x0a, 0x8b, 0x7a, 0x6c, 0x00, 0xff, 
+    0x12, 0x1a, 0x93, 0x12, 0x1a, 0x08, 0x30, 0x09, 0xe4, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 
+    0x09, 0xa2, 0x00, 0x1c, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xf5, 0x80, 0xec, 0x7e, 0x68, 0x0c, 
+    0x69, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x12, 0x13, 0x8a, 0x7e, 0x24, 0x80, 0x00, 0x7e, 
+    0x11, 0x09, 0x0b, 0x00, 0x74, 0x10, 0x19, 0xb2, 0x00, 0x10, 0x12, 0x13, 0x03, 0x2e, 0x24, 0x01, 
+    0x00, 0xa5, 0xd9, 0xee, 0x7e, 0x68, 0x0c, 0x8d, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7e, 
+    0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 0x0b, 0x00, 0xe4, 0x19, 0xb2, 0x00, 0x10, 0x12, 0x13, 0x03, 
+    0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xef, 0x30, 0x00, 0x03, 0x02, 0x18, 0xb7, 0x02, 0x13, 0xbb, 
+    0x74, 0x07, 0x19, 0xb2, 0x00, 0x08, 0x12, 0x19, 0xfb, 0x09, 0xb2, 0x00, 0x00, 0x09, 0xb2, 0x00, 
+    0x14, 0x09, 0xb2, 0x00, 0x00, 0x09, 0xb2, 0x00, 0x14, 0x09, 0xb2, 0x00, 0x00, 0x09, 0xb2, 0x00, 
+    0x14, 0x09, 0xb2, 0x00, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xc2, 0x0b, 0x7e, 0xb0, 0x55, 0x12, 0x13, 
+    0x64, 0x7e, 0xb0, 0xaa, 0x12, 0x13, 0x64, 0x7e, 0xb0, 0x00, 0x12, 0x13, 0x64, 0x7e, 0xb0, 0xff, 
+    0x12, 0x13, 0x64, 0x30, 0x0b, 0x0f, 0x7e, 0x68, 0x0a, 0x8b, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 
+    0x93, 0x12, 0x1a, 0x08, 0x22, 0x7e, 0x68, 0x0a, 0x82, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 
+    0x22, 0x19, 0xb2, 0x00, 0x00, 0x12, 0x19, 0xee, 0x09, 0xa2, 0x00, 0x00, 0xbc, 0xab, 0x78, 0x01, 
+    0x22, 0x20, 0x09, 0x03, 0xd2, 0x0b, 0x22, 0x12, 0x1a, 0x08, 0x19, 0xb2, 0x00, 0x00, 0x12, 0x19, 
+    0xee, 0x09, 0xa2, 0x00, 0x00, 0x80, 0xf3, 0xd2, 0x92, 0x12, 0x19, 0xee, 0xc2, 0x92, 0x12, 0x19, 
+    0xee, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 0x74, 0x80, 0x19, 0xb2, 0x00, 0x0c, 0x7e, 0x54, 
+    0x00, 0x02, 0x19, 0xa2, 0x00, 0x04, 0x19, 0xb2, 0x00, 0x00, 0x74, 0x03, 0x19, 0xb2, 0x00, 0x0c, 
+    0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xe1, 0x22, 0x7e, 0x68, 0x0c, 0xb1, 0x7a, 0x6c, 0x00, 0xff, 
+    0x12, 0x1a, 0x93, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 0x0b, 0x00, 0x12, 0x19, 0xee, 0x09, 
+    0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x55, 0x19, 0xa2, 0x00, 0x00, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 
+    0x18, 0x5e, 0xb0, 0x05, 0x78, 0x0d, 0x7e, 0x68, 0x0a, 0x82, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 
+    0x93, 0x80, 0x1a, 0x7e, 0x68, 0x0a, 0x8b, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x12, 0x1a, 
+    0x08, 0x30, 0x09, 0x09, 0x19, 0xa2, 0x00, 0x00, 0x12, 0x19, 0xee, 0x80, 0xf7, 0x2e, 0x24, 0x01, 
+    0x00, 0xa5, 0xd9, 0xb6, 0x7e, 0x68, 0x0c, 0xd5, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7e, 
+    0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 0x0b, 0x00, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x7e, 
+    0xa0, 0x55, 0x19, 0xa2, 0x00, 0x00, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x0a, 
+    0x78, 0x0d, 0x7e, 0x68, 0x0a, 0x82, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x80, 0x1a, 0x7e, 
+    0x68, 0x0a, 0x8b, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x12, 0x1a, 0x08, 0x30, 0x09, 0x09, 
+    0x19, 0xa2, 0x00, 0x00, 0x12, 0x19, 0xee, 0x80, 0xf7, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xb6, 
+    0x30, 0x04, 0x03, 0x02, 0x16, 0x8c, 0x7e, 0x68, 0x0c, 0xf9, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 
+    0x93, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 0x0b, 0x00, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 
+    0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 
+    0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x0a, 0x78, 0x3c, 
+    0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 
+    0x03, 0x19, 0xa2, 0x00, 0x10, 0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 
+    0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x0a, 0x78, 0x14, 0x7e, 0x68, 0x0a, 0x82, 0x7a, 0x6c, 0x00, 0xff, 
+    0x12, 0x1a, 0x93, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0x9e, 0x80, 0x20, 0x7e, 0x68, 0x0a, 0x8b, 
+    0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x12, 0x1a, 0x08, 0x30, 0x09, 0xe6, 0x7e, 0xa0, 0x02, 
+    0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x80, 0xf1, 0x7e, 0x68, 0x0d, 0x41, 
+    0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 0x0b, 0x00, 
+    0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x01, 
+    0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 
+    0x18, 0x5e, 0xb0, 0x05, 0x78, 0x3c, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 
+    0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x03, 0x19, 0xa2, 0x00, 0x10, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 
+    0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x05, 0x78, 0x14, 0x7e, 0x68, 
+    0x0a, 0x82, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0x9e, 
+    0x80, 0x20, 0x7e, 0x68, 0x0a, 0x8b, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x12, 0x1a, 0x08, 
+    0x30, 0x09, 0xe6, 0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 
+    0x80, 0xf1, 0x7e, 0x68, 0x0d, 0x89, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7e, 0x24, 0x80, 
+    0x00, 0x7e, 0x11, 0x09, 0x0b, 0x00, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 
+    0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x50, 0xbe, 0xb0, 0x50, 0x78, 0x1f, 0x6c, 0xaa, 0x19, 0xa2, 
+    0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x50, 0x78, 0x0d, 0x7e, 0x68, 
+    0x0a, 0x82, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x80, 0x20, 0x7e, 0x68, 0x0a, 0x8b, 0x7a, 
+    0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x12, 0x1a, 0x08, 0x30, 0x09, 0x0f, 0x7e, 0xa0, 0x02, 0x19, 
+    0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x80, 0xf1, 0x2e, 0x24, 0x01, 0x00, 0xa5, 
+    0xd9, 0xa2, 0x7e, 0x68, 0x0d, 0xd1, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7e, 0x24, 0x80, 
+    0x00, 0x7e, 0x11, 0x09, 0x0b, 0x00, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 
+    0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0xa0, 0xbe, 0xb0, 0xa0, 0x78, 0x1f, 
+    0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0xa0, 
+    0x78, 0x0d, 0x7e, 0x68, 0x0a, 0x82, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x80, 0x20, 0x7e, 
+    0x68, 0x0a, 0x8b, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x12, 0x1a, 0x08, 0x30, 0x09, 0x0f, 
+    0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x80, 0xf1, 0x2e, 
+    0x24, 0x01, 0x00, 0xa5, 0xd9, 0x9e, 0x02, 0x18, 0x2b, 0x7e, 0x68, 0x0d, 0x1d, 0x7a, 0x6c, 0x00, 
+    0xff, 0x12, 0x1a, 0x93, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 0x0b, 0x00, 0x6c, 0xaa, 0x19, 
+    0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 
+    0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 
+    0x06, 0x78, 0x3c, 0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 
+    0x18, 0x7e, 0xa0, 0x03, 0x19, 0xa2, 0x00, 0x10, 0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x12, 
+    0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x06, 0x78, 0x14, 0x7e, 0x68, 0x0a, 0x82, 0x7a, 
+    0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0x9e, 0x80, 0x20, 0x7e, 
+    0x68, 0x0a, 0x8b, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x12, 0x1a, 0x08, 0x30, 0x09, 0xe6, 
+    0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x80, 0xf1, 0x7e, 
+    0x68, 0x0d, 0x65, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 
+    0x09, 0x0b, 0x00, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 
+    0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 
+    0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x09, 0x78, 0x3c, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 
+    0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x03, 0x19, 0xa2, 0x00, 0x10, 0x7e, 0xa0, 
+    0x02, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x09, 0x78, 
+    0x14, 0x7e, 0x68, 0x0a, 0x82, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x2e, 0x24, 0x01, 0x00, 
+    0xa5, 0xd9, 0x9e, 0x80, 0x20, 0x7e, 0x68, 0x0a, 0x8b, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 
+    0x12, 0x1a, 0x08, 0x30, 0x09, 0xe6, 0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 
+    0xa2, 0x00, 0x10, 0x80, 0xf1, 0x7e, 0x68, 0x0d, 0xad, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 
+    0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 0x0b, 0x00, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 
+    0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x90, 0xbe, 0xb0, 0x90, 0x78, 0x1f, 0x6c, 
+    0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x90, 0x78, 
+    0x0d, 0x7e, 0x68, 0x0a, 0x82, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x80, 0x20, 0x7e, 0x68, 
+    0x0a, 0x8b, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x12, 0x1a, 0x08, 0x30, 0x09, 0x0f, 0x7e, 
+    0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x80, 0xf1, 0x2e, 0x24, 
+    0x01, 0x00, 0xa5, 0xd9, 0xa2, 0x02, 0x18, 0xb7, 0x30, 0x17, 0x03, 0x02, 0x19, 0x3b, 0xc2, 0x8a, 
+    0x12, 0x19, 0x22, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x04, 
+    0x12, 0x19, 0xee, 0x0b, 0x00, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x20, 
+    0x8b, 0x3e, 0x20, 0x89, 0x3b, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, 0x04, 0x09, 0xa2, 0x00, 0x10, 
+    0x4e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x30, 0x8b, 0x23, 0x30, 0x89, 0x20, 
+    0x09, 0xa2, 0x00, 0x10, 0x5e, 0xa0, 0xfd, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 0x7e, 0xa0, 
+    0x00, 0x19, 0xa2, 0x00, 0x04, 0x12, 0x19, 0xee, 0x20, 0x8b, 0x05, 0x20, 0x89, 0x02, 0x80, 0x1a, 
+    0x12, 0x1a, 0x08, 0x30, 0x09, 0x14, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x00, 0x00, 0x5e, 
+    0xa0, 0xfd, 0x19, 0xa2, 0x00, 0x10, 0x00, 0x00, 0x80, 0xec, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 
+    0x89, 0x02, 0x19, 0x3b, 0x20, 0x17, 0xfa, 0x12, 0x13, 0x8a, 0x12, 0x19, 0x22, 0x7e, 0x24, 0x80, 
+    0x00, 0x7e, 0x11, 0x09, 0x0b, 0x00, 0x20, 0x89, 0x26, 0x7e, 0xa0, 0xff, 0x19, 0xa2, 0x00, 0x04, 
+    0x12, 0x19, 0xee, 0x7e, 0xb0, 0x55, 0x19, 0xb2, 0x00, 0x00, 0x12, 0x19, 0xee, 0x30, 0x89, 0x0f, 
+    0x7e, 0xa0, 0x00, 0x19, 0xa2, 0x00, 0x04, 0x12, 0x19, 0xee, 0x20, 0x89, 0x02, 0x80, 0x26, 0x12, 
+    0x1a, 0x08, 0x30, 0x09, 0x20, 0x7e, 0xa0, 0xff, 0x19, 0xa2, 0x00, 0x04, 0x12, 0x19, 0xee, 0x7e, 
+    0xb0, 0x55, 0x19, 0xb2, 0x00, 0x00, 0x12, 0x19, 0xee, 0x7e, 0xa0, 0x00, 0x19, 0xa2, 0x00, 0x04, 
+    0x12, 0x19, 0xee, 0x80, 0xe0, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xa8, 0x02, 0x19, 0x3b, 0x7e, 
+    0x24, 0x80, 0x00, 0x7e, 0x11, 0x09, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x19, 0xee, 
+    0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xef, 0x22, 0x30, 0x0a, 0x19, 0x7e, 0x68, 0x0d, 0xf5, 0x7a, 
+    0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0xd2, 0x09, 0x12, 0x19, 0xee, 0x12, 0x19, 0xee, 0x12, 0x19, 
+    0xee, 0x02, 0x0f, 0x10, 0x30, 0x17, 0x1c, 0x7e, 0x68, 0x0e, 0x6f, 0x7a, 0x6c, 0x00, 0xff, 0x12, 
+    0x1a, 0x93, 0x7e, 0x68, 0x0e, 0x91, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x1a, 0x93, 0x12, 0x1b, 0x3c, 
+    0x02, 0x19, 0xe6, 0x0b, 0x00, 0x7e, 0x78, 0x19, 0xa0, 0x7a, 0x7c, 0x00, 0xff, 0x7f, 0x67, 0x7a, 
+    0x6c, 0x00, 0x00, 0x7e, 0x70, 0x3e, 0x7e, 0x7b, 0xb0, 0x7a, 0x6b, 0xb0, 0x0b, 0x7c, 0x0b, 0x6c, 
+    0xa5, 0xdf, 0xf3, 0x7e, 0x78, 0x19, 0xa0, 0x7a, 0x7c, 0x00, 0x00, 0x89, 0x78, 0x7e, 0x78, 0x00, 
+    0x00, 0x7a, 0x7c, 0x00, 0xfe, 0x7e, 0x68, 0x7f, 0xbf, 0x7a, 0x6c, 0x00, 0xfe, 0x74, 0xaa, 0x39, 
+    0xb7, 0x55, 0x55, 0x74, 0x55, 0x39, 0xb7, 0x2a, 0xaa, 0x74, 0xa0, 0x39, 0xb7, 0x55, 0x55, 0x6c, 
+    0x99, 0x7a, 0x6b, 0x90, 0x7e, 0x54, 0x27, 0x10, 0x7e, 0x6b, 0x80, 0xbc, 0x89, 0x68, 0x08, 0x1b, 
+    0x54, 0x78, 0xf5, 0x8a, 0xff, 0x19, 0xde, 0x8a, 0xff, 0x19, 0xe6, 0x12, 0x1a, 0x08, 0x7e, 0x6b, 
+    0x80, 0x80, 0xfb, 0x7e, 0x10, 0xff, 0x12, 0x1a, 0x85, 0x80, 0xf8, 0xca, 0xf9, 0x7e, 0xf4, 0x00, 
+    0xff, 0x1b, 0xf4, 0x78, 0xfc, 0xda, 0xf9, 0x22, 0xca, 0xf9, 0x7e, 0xf4, 0x00, 0x00, 0x1b, 0xf4, 
+    0x78, 0xfc, 0xda, 0xf9, 0x22, 0x20, 0x09, 0x19, 0xd2, 0x0a, 0x12, 0x19, 0xfb, 0xc2, 0x95, 0xd2, 
+    0x94, 0x12, 0x19, 0xfb, 0x12, 0x19, 0xfb, 0x12, 0x19, 0xfb, 0x12, 0x19, 0xfb, 0x43, 0x90, 0x30, 
+    0x22, 0xca, 0x0b, 0x7e, 0x10, 0x03, 0x7c, 0x30, 0x6c, 0x22, 0x0b, 0x20, 0x9e, 0x30, 0x0a, 0x50, 
+    0xf9, 0x2e, 0x30, 0x0b, 0x1b, 0x20, 0x68, 0x18, 0x12, 0x19, 0xfb, 0x12, 0x19, 0xfb, 0x53, 0x90, 
+    0xcf, 0x12, 0x19, 0xfb, 0x12, 0x19, 0xfb, 0x12, 0x19, 0xfb, 0x43, 0x90, 0x30, 0xa5, 0xda, 0xe8, 
+    0x12, 0x19, 0xfb, 0x12, 0x19, 0xfb, 0x1b, 0x30, 0x68, 0x19, 0x12, 0x19, 0xfb, 0x12, 0x19, 0xfb, 
+    0xc2, 0x95, 0xd2, 0x94, 0x12, 0x19, 0xfb, 0x12, 0x19, 0xfb, 0x12, 0x19, 0xfb, 0x43, 0x90, 0x30, 
+    0xa5, 0xdb, 0xe7, 0x7e, 0x20, 0x0a, 0x12, 0x19, 0xfb, 0xa5, 0xda, 0xfa, 0xa5, 0xd9, 0xa7, 0xda, 
+    0x0b, 0x22, 0x20, 0x09, 0x0a, 0x12, 0x19, 0xfb, 0xb2, 0x94, 0x12, 0x19, 0xfb, 0xb2, 0x94, 0x22, 
+    0x30, 0x17, 0x32, 0x20, 0x09, 0x2f, 0xca, 0x2b, 0xca, 0x7b, 0x7e, 0x78, 0x80, 0x00, 0x7a, 0x7c, 
+    0x00, 0xfe, 0x12, 0x1b, 0x1c, 0x7e, 0x6b, 0xa0, 0x5c, 0xaa, 0x68, 0x10, 0x29, 0xb7, 0x00, 0x14, 
+    0x54, 0x60, 0x68, 0xf8, 0x39, 0xa7, 0x00, 0x00, 0x0b, 0x6c, 0x80, 0xe9, 0x12, 0x19, 0xee, 0xd2, 
+    0xb5, 0xda, 0x7b, 0xda, 0x2b, 0x22, 0x12, 0x1a, 0xd4, 0x7e, 0x68, 0x00, 0x0b, 0x12, 0x1a, 0x93, 
+    0x22, 0xca, 0x59, 0xca, 0x5b, 0x7e, 0xb4, 0x00, 0x0b, 0x7c, 0xb8, 0xc4, 0x12, 0x1b, 0x04, 0x7c, 
+    0xb8, 0x12, 0x1b, 0x04, 0x7c, 0xb9, 0xc4, 0x12, 0x1b, 0x04, 0x7c, 0xb9, 0x12, 0x1b, 0x04, 0x7e, 
+    0xb0, 0x68, 0x7a, 0xb9, 0xb0, 0x0b, 0xb4, 0x6c, 0xbb, 0x7a, 0xb9, 0xb0, 0xda, 0x59, 0xda, 0x5b, 
+    0x22, 0x5e, 0xb0, 0x0f, 0x7c, 0xab, 0x9e, 0xa0, 0x0a, 0x40, 0x05, 0x2e, 0xb0, 0x37, 0x80, 0x03, 
+    0x2e, 0xb0, 0x30, 0x7a, 0xb9, 0xb0, 0x0b, 0xb4, 0x22, 0xc2, 0xb5, 0xc2, 0x92, 0x12, 0x19, 0xee, 
+    0x74, 0x80, 0x39, 0xb7, 0x00, 0x0c, 0x7e, 0x54, 0x00, 0x06, 0x39, 0xa7, 0x00, 0x04, 0x39, 0xb7, 
+    0x00, 0x00, 0x74, 0x03, 0x39, 0xb7, 0x00, 0x0c, 0x22, 0x7e, 0x78, 0x00, 0x00, 0x7a, 0x7c, 0x00, 
+    0xff, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0x01, 0x7f, 0x65, 0x7e, 0x74, 0x20, 0x00, 0x12, 
+    0x08, 0xd6, 0x40, 0x54, 0x7e, 0x78, 0x7c, 0x00, 0x7a, 0x7c, 0x00, 0xff, 0x7e, 0x58, 0x00, 0x00, 
+    0x7a, 0x5c, 0x00, 0x01, 0x7e, 0x68, 0x7c, 0x00, 0x7a, 0x6c, 0x00, 0x01, 0x7e, 0x74, 0x04, 0x00, 
+    0x12, 0x08, 0xd6, 0x40, 0x33, 0x74, 0x80, 0x12, 0x1b, 0xb1, 0x40, 0x2c, 0x53, 0x90, 0xcf, 0xd2, 
+    0x08, 0x7e, 0x04, 0x00, 0x08, 0x7e, 0x14, 0x00, 0x00, 0x84, 0xa5, 0xdb, 0xfc, 0xa5, 0xda, 0xf9, 
+    0xa5, 0xd9, 0xf6, 0x74, 0x40, 0x12, 0x1b, 0xb1, 0x40, 0x0e, 0x7e, 0x68, 0x0e, 0xc0, 0x7a, 0x6c, 
+    0x00, 0xff, 0x12, 0x1a, 0x93, 0x02, 0x19, 0xe6, 0xc2, 0x95, 0xd2, 0x94, 0x80, 0xfe, 0xf5, 0x0a, 
+    0x7e, 0x78, 0x00, 0x0a, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x68, 0x7f, 0xbf, 0x7a, 0x6c, 0x00, 0x01, 
+    0x7e, 0x74, 0x00, 0x01, 0x02, 0x08, 0xd6, 
+};
+
+static EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME = {
+       1, 12, 2 };             // Major, Minor, Build
+
+#undef IMAGE_VERSION_NAME
+
+#undef IMAGE_ARRAY_NAME
+
diff --git a/drivers/usb/serial/io_fw_boot2.h b/drivers/usb/serial/io_fw_boot2.h
new file mode 100644 (file)
index 0000000..06d82f2
--- /dev/null
@@ -0,0 +1,548 @@
+//**************************************************************
+//* Edgeport/4 Binary Image
+//* Generated by HEX2C v1.06
+//* Copyright(c) 1998 Inside Out Networks, All rights reserved.
+//*    This program is free software; you can redistribute it and/or modify
+//*    it under the terms of the GNU General Public License as published by
+//*    the Free Software Foundation; either version 2 of the License, or
+//*    (at your option) any later version.
+//**************************************************************
+
+
+//Image structure definition
+#if !defined(DEFINED_EDGE_FIRMWARE_IMAGE_RECORD)
+#define DEFINED_EDGE_FIRMWARE_IMAGE_RECORD
+       typedef struct _EDGE_FIRMWARE_IMAGE_RECORD
+       {
+               unsigned short ExtAddr;
+               unsigned short Addr;
+               unsigned short Len;
+               unsigned char  Data[0];
+       } EDGE_FIRMWARE_IMAGE_RECORD, *PEDGE_FIRMWARE_IMAGE_RECORD;
+
+       typedef struct _EDGE_FIRMWARE_VERSION_INFO
+       {
+               unsigned char    MajorVersion;
+               unsigned char  MinorVersion;
+               unsigned short BuildNumber;
+       } EDGE_FIRMWARE_VERSION_INFO, *PEDGE_FIRMWARE_VERSION_INFO;
+
+#endif
+
+#if !defined(IMAGE_ARRAY_NAME)
+#define IMAGE_ARRAY_NAME               FirmwareImage
+#define IMAGE_VERSION_NAME     FirmwareImageVersion
+#endif
+
+static unsigned char IMAGE_ARRAY_NAME[] = {
+
+// Segment #1, Start Address 00ff0000, Length 6
+0xff,0x00,0x00,0x00,0x06,0x00,
+    0x02, 0x00, 0x80, 0x02, 0x00, 0x03, 
+
+// Segment #2, Start Address 00ff000b, Length 3
+0xff,0x00,0x0b,0x00,0x03,0x00,
+    0x02, 0x00, 0x0b, 
+
+// Segment #3, Start Address 00ff0013, Length 3
+0xff,0x00,0x13,0x00,0x03,0x00,
+    0x02, 0x02, 0x56, 
+
+// Segment #4, Start Address 00ff001b, Length 3
+0xff,0x00,0x1b,0x00,0x03,0x00,
+    0x02, 0x00, 0x1b, 
+
+// Segment #5, Start Address 00ff0023, Length 3
+0xff,0x00,0x23,0x00,0x03,0x00,
+    0x02, 0x00, 0x23, 
+
+// Segment #6, Start Address 00ff002b, Length 3
+0xff,0x00,0x2b,0x00,0x03,0x00,
+    0x02, 0x00, 0x2b, 
+
+// Segment #7, Start Address 00ff0033, Length 3
+0xff,0x00,0x33,0x00,0x03,0x00,
+    0x02, 0x00, 0x33, 
+
+// Segment #8, Start Address 00ff003b, Length 3
+0xff,0x00,0x3b,0x00,0x03,0x00,
+    0x02, 0x00, 0x3b, 
+
+// Segment #9, Start Address 00ff0043, Length 3
+0xff,0x00,0x43,0x00,0x03,0x00,
+    0x02, 0x00, 0x43, 
+
+// Segment #10, Start Address 00ff004b, Length 3
+0xff,0x00,0x4b,0x00,0x03,0x00,
+    0x02, 0x00, 0x4b, 
+
+// Segment #11, Start Address 00ff0053, Length 3
+0xff,0x00,0x53,0x00,0x03,0x00,
+    0x02, 0x01, 0xf5, 
+
+// Segment #12, Start Address 00ff007b, Length 3
+0xff,0x00,0x7b,0x00,0x03,0x00,
+    0x02, 0x00, 0x7b, 
+
+// Segment #13, Start Address 00ff0080, Length 534
+0xff,0x00,0x80,0x00,0x16,0x02,
+    0x7e, 0xb3, 0x91, 0x01, 0x20, 0xe3, 0x0c, 0x7e, 0xb3, 0x3f, 0xf2, 0x54, 0xfe, 0x7a, 0xb3, 0x3f, 
+    0xf2, 0x80, 0x0a, 0x7e, 0xb3, 0x3f, 0xf2, 0x44, 0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x74, 0x00, 0x7a, 
+    0xb3, 0x91, 0x00, 0x74, 0x01, 0x7a, 0xb3, 0x91, 0x12, 0x7e, 0xf8, 0x00, 0x24, 0x7e, 0x00, 0x01, 
+    0x7e, 0x10, 0x00, 0x12, 0x09, 0xd0, 0x69, 0x20, 0x00, 0x0a, 0x5e, 0x40, 0x1f, 0xbe, 0x24, 0x00, 
+    0x00, 0x78, 0x09, 0x7e, 0x00, 0x03, 0x7a, 0x03, 0x90, 0x00, 0x80, 0x07, 0x7e, 0x00, 0x02, 0x7a, 
+    0x03, 0x90, 0x00, 0x75, 0xb0, 0xdf, 0x7e, 0x00, 0x01, 0x7a, 0x03, 0x94, 0x00, 0x7a, 0x03, 0x01, 
+    0x24, 0x7e, 0x00, 0x01, 0x7a, 0x03, 0x93, 0x00, 0x7e, 0x00, 0x00, 0xa5, 0xd8, 0xfd, 0x75, 0xa8, 
+    0x00, 0x75, 0xb1, 0x00, 0xca, 0x29, 0x12, 0x0c, 0x66, 0x12, 0x0c, 0x37, 0xf5, 0x21, 0x7a, 0xa1, 
+    0x20, 0x20, 0x09, 0x08, 0x20, 0x0a, 0x0a, 0x7e, 0xb0, 0x0c, 0x80, 0x08, 0x7e, 0xb0, 0x00, 0x80, 
+    0x03, 0x7e, 0xb0, 0x08, 0x7a, 0xb3, 0x92, 0x00, 0x12, 0x02, 0x96, 0xda, 0x29, 0x74, 0x10, 0x7a, 
+    0xb3, 0x91, 0x01, 0x7e, 0x20, 0x04, 0x7c, 0xb2, 0xc2, 0xd7, 0x13, 0x13, 0x13, 0x13, 0x7a, 0xb3, 
+    0x91, 0x00, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x10, 0x74, 0x60, 0x7a, 0xb3, 0x91, 0x1c, 0x74, 0x02, 
+    0x7a, 0xb3, 0x91, 0x12, 0xa5, 0xda, 0xdf, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 
+    0xb3, 0x91, 0x1c, 0x74, 0x10, 0x7a, 0xb3, 0x91, 0x06, 0x74, 0x10, 0x7a, 0xb3, 0x91, 0x07, 0x74, 
+    0x34, 0x7a, 0xb3, 0x91, 0x13, 0x74, 0x3f, 0x7a, 0xb3, 0x91, 0x14, 0x74, 0x02, 0x7a, 0xb3, 0x91, 
+    0x06, 0x74, 0x01, 0x7a, 0xb3, 0x91, 0x07, 0x74, 0x03, 0x7a, 0xb3, 0x91, 0x06, 0x74, 0x44, 0x7a, 
+    0xb3, 0x91, 0x07, 0x74, 0xef, 0x7a, 0xb3, 0x91, 0x04, 0x74, 0x07, 0x7a, 0xb3, 0x91, 0x06, 0x7e, 
+    0xb3, 0x91, 0x07, 0x7a, 0xb1, 0x0a, 0x75, 0x09, 0x01, 0xd2, 0xaa, 0xd2, 0xaf, 0xe4, 0x7e, 0x60, 
+    0x02, 0x4d, 0x22, 0x78, 0x03, 0x7e, 0x60, 0x03, 0x7c, 0x76, 0x7e, 0x04, 0x28, 0x00, 0x8d, 0xef, 
+    0x1b, 0x04, 0x78, 0xfa, 0x04, 0x7e, 0x20, 0x07, 0x7a, 0x23, 0x91, 0x06, 0x7e, 0x23, 0x91, 0x07, 
+    0x7e, 0x31, 0x0a, 0xbc, 0x32, 0x68, 0x22, 0x7a, 0x21, 0x0a, 0x7e, 0x21, 0x09, 0x68, 0x17, 0xca, 
+    0xb8, 0x74, 0x03, 0x7a, 0xb3, 0x91, 0x06, 0x7e, 0xb3, 0x91, 0x07, 0x44, 0x02, 0x7a, 0xb3, 0x91, 
+    0x07, 0xda, 0xb8, 0x75, 0x09, 0x00, 0x30, 0xe0, 0xc1, 0x6c, 0x67, 0x7a, 0x63, 0x90, 0x00, 0x80, 
+    0xb9, 0xbe, 0xb0, 0x02, 0x22, 0xc0, 0xd0, 0x75, 0x08, 0xfe, 0x12, 0x0a, 0xc0, 0x74, 0x02, 0x7a, 
+    0xb3, 0x91, 0x06, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x07, 0x74, 0x03, 0x7a, 0xb3, 0x91, 0x06, 0x74, 
+    0x00, 0x7a, 0xb3, 0x91, 0x07, 0x74, 0x02, 0x7a, 0xb3, 0x91, 0x04, 0x7e, 0xb3, 0x3f, 0xf2, 0x30, 
+    0xe0, 0x08, 0x74, 0x18, 0x7a, 0xb3, 0x91, 0x01, 0x80, 0x06, 0x74, 0x10, 0x7a, 0xb3, 0x91, 0x01, 
+    0x74, 0x10, 0x7a, 0xb3, 0x91, 0x04, 0x02, 0x02, 0x36, 0x75, 0x08, 0xff, 0x12, 0x0a, 0xc0, 0x74, 
+    0x01, 0x7a, 0xb3, 0x91, 0x04, 0x74, 0x03, 0x7a, 0xb3, 0x91, 0x06, 0x7e, 0xb3, 0x91, 0x07, 0x54, 
+    0xfc, 0x7a, 0xb3, 0x91, 0x07, 0x32, 0xca, 0xb8, 0x75, 0x08, 0x02, 0x12, 0x0a, 0xc0, 0x7e, 0xb3, 
+    0x91, 0x03, 0x20, 0xe5, 0x08, 0x30, 0xe0, 0x2b, 0x12, 0x02, 0x9e, 0x80, 0xf1, 0x7e, 0xb3, 0x91, 
+    0x04, 0x30, 0xe0, 0x05, 0xda, 0xb8, 0x02, 0x02, 0x39, 0x30, 0xe1, 0x05, 0xda, 0xb8, 0x02, 0x01, 
+    0xf5, 0x30, 0xe6, 0x05, 0x12, 0x04, 0x03, 0x80, 0xd5, 0x30, 0xe2, 0x05, 0xda, 0xb8, 0x02, 0x00, 
+    0x80, 0x80, 0xcb, 0xda, 0xb8, 0x32, 
+
+// Segment #14, EXCLUDED Start Address 00ff31d7, Length 1
+
+
+// Segment #15, Start Address 00ff0296, Length 2090
+0xff,0x00,0x96,0x02,0x2a,0x08,
+    0xe4, 0x7a, 0xb3, 0x3f, 0xf1, 0x02, 0x03, 0x41, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xca, 0x3b, 
+    0xca, 0x4b, 0xca, 0x5b, 0xca, 0x6b, 0xca, 0x7b, 0xca, 0xeb, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 
+    0x7e, 0xb3, 0x01, 0x2e, 0xb4, 0x00, 0x02, 0x80, 0x1c, 0xb4, 0x01, 0x19, 0x7e, 0xb3, 0x91, 0x14, 
+    0x54, 0x14, 0x68, 0x05, 0x12, 0x03, 0x05, 0x80, 0x23, 0x7e, 0xb3, 0x91, 0x14, 0x30, 0xe5, 0x1c, 
+    0x12, 0x04, 0x43, 0x80, 0x17, 0x7e, 0xb3, 0x91, 0x14, 0x30, 0xe5, 0x05, 0x12, 0x04, 0x43, 0x80, 
+    0x0b, 0x7e, 0xb3, 0x91, 0x14, 0x54, 0x14, 0x68, 0x03, 0x12, 0x03, 0x05, 0xda, 0xeb, 0xda, 0x7b, 
+    0xda, 0x6b, 0xda, 0x5b, 0xda, 0x4b, 0xda, 0x3b, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x20, 
+    0xe4, 0x19, 0x75, 0x08, 0x0a, 0x12, 0x0a, 0xc0, 0x7e, 0xb3, 0x01, 0x2d, 0x70, 0x0a, 0x7e, 0xb3, 
+    0x01, 0x2e, 0xb4, 0x01, 0x1f, 0x02, 0x03, 0x9d, 0x02, 0x09, 0x8b, 0x75, 0x08, 0x0b, 0x12, 0x0a, 
+    0xc0, 0x74, 0x14, 0x7a, 0xb3, 0x91, 0x14, 0x7e, 0xb3, 0x01, 0x2e, 0xb4, 0x02, 0x0c, 0x12, 0x03, 
+    0x4d, 0x02, 0x03, 0x41, 0x74, 0x04, 0x7a, 0xb3, 0x91, 0x14, 0x22, 0x7e, 0x00, 0x00, 0x7a, 0x03, 
+    0x01, 0x2e, 0x7a, 0x03, 0x01, 0x2f, 0x22, 0x7e, 0xb3, 0x01, 0x25, 0x54, 0x60, 0x60, 0x05, 0xb4, 
+    0x40, 0x1e, 0x80, 0x1c, 0x7e, 0xb3, 0x01, 0x26, 0xb4, 0x05, 0x15, 0x75, 0x08, 0x71, 0x12, 0x0a, 
+    0xc0, 0x7e, 0xb3, 0x01, 0x28, 0x7e, 0xa0, 0x01, 0x7a, 0xa3, 0x91, 0x06, 0x7a, 0xb3, 0x91, 0x07, 
+    0x22, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x10, 0x7a, 0xb3, 0x91, 0x12, 0x22, 0xbe, 0x57, 
+    0x01, 0x2b, 0x28, 0x04, 0x7e, 0x57, 0x01, 0x2b, 0x7a, 0x0f, 0x01, 0x31, 0x7a, 0x57, 0x01, 0x35, 
+    0x74, 0x10, 0x7a, 0xb3, 0x91, 0x12, 0x22, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x7e, 0xb3, 0x91, 
+    0x1a, 0x70, 0x53, 0x7e, 0xb3, 0x91, 0x14, 0x20, 0xe4, 0x4c, 0x7e, 0xef, 0x01, 0x31, 0x7e, 0xf7, 
+    0x01, 0x35, 0x7e, 0x07, 0x01, 0x35, 0x4d, 0x00, 0x68, 0x21, 0x7e, 0x00, 0x00, 0xe0, 0x7a, 0xb3, 
+    0x91, 0x17, 0xa3, 0xa5, 0x08, 0x1b, 0xf4, 0x68, 0x06, 0xa5, 0xb8, 0x10, 0xf0, 0x80, 0x19, 0x7e, 
+    0xb0, 0x00, 0x7a, 0xb3, 0x01, 0x2e, 0xbe, 0x00, 0x10, 0x68, 0x0d, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 
+    0x01, 0x2e, 0x74, 0x80, 0x7a, 0xb3, 0x91, 0x1e, 0x7a, 0xef, 0x01, 0x31, 0x7a, 0xf7, 0x01, 0x35, 
+    0x75, 0x08, 0x06, 0x12, 0x0a, 0xc0, 0x74, 0x04, 0x7a, 0xb3, 0x91, 0x14, 0x22, 0xca, 0x0b, 0xca, 
+    0x1b, 0xca, 0x2b, 0xca, 0x3b, 0xca, 0x4b, 0xca, 0x5b, 0xca, 0x6b, 0xca, 0x7b, 0xca, 0xeb, 0x75, 
+    0x08, 0x03, 0x12, 0x0a, 0xc0, 0x74, 0x00, 0x7a, 0xb3, 0x01, 0x2d, 0x74, 0x00, 0x7a, 0xb3, 0x91, 
+    0x00, 0x74, 0x01, 0x7a, 0xb3, 0x91, 0x12, 0x12, 0x04, 0xb2, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 
+    0xda, 0x5b, 0xda, 0x4b, 0xda, 0x3b, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x75, 0x08, 0x03, 
+    0x12, 0x0a, 0xc0, 0x7e, 0xb3, 0x01, 0x2f, 0xb4, 0x02, 0x11, 0x74, 0x00, 0x7a, 0xb3, 0x01, 0x2f, 
+    0x7a, 0xb3, 0x01, 0x2e, 0x74, 0x20, 0x7a, 0xb3, 0x91, 0x14, 0x22, 0xb4, 0x01, 0x46, 0x7e, 0xb3, 
+    0x91, 0x04, 0x20, 0xe6, 0x42, 0x7e, 0x23, 0x91, 0x1a, 0x7c, 0x32, 0x7e, 0x13, 0x01, 0x30, 0x2c, 
+    0x21, 0x7a, 0x23, 0x01, 0x30, 0x7e, 0x00, 0x00, 0x2e, 0x04, 0x01, 0x37, 0x7e, 0xb3, 0x91, 0x16, 
+    0x7a, 0x09, 0xb0, 0x0b, 0x04, 0xa5, 0xdb, 0xf4, 0x74, 0x20, 0x7a, 0xb3, 0x91, 0x14, 0x75, 0x08, 
+    0x70, 0x12, 0x0a, 0xc0, 0x7e, 0xb3, 0x01, 0x30, 0x7e, 0xa3, 0x01, 0x2c, 0xbc, 0xab, 0x78, 0x03, 
+    0x12, 0x05, 0x52, 0x22, 0x02, 0x09, 0x8b, 0xda, 0x59, 0x02, 0x04, 0x15, 0x74, 0xe0, 0x7a, 0xb3, 
+    0x91, 0x00, 0x7e, 0x03, 0x91, 0x10, 0x7e, 0x13, 0x91, 0x11, 0x7e, 0x33, 0x91, 0x12, 0x7e, 0x23, 
+    0x91, 0x13, 0x7e, 0x53, 0x91, 0x14, 0x7e, 0x43, 0x91, 0x15, 0x7e, 0x73, 0x91, 0x16, 0x7e, 0x63, 
+    0x91, 0x17, 0x7a, 0x0f, 0x01, 0x25, 0x7a, 0x1f, 0x01, 0x29, 0x75, 0x08, 0x04, 0x12, 0x0a, 0xc0, 
+    0x7a, 0x01, 0x08, 0x12, 0x0a, 0xc0, 0x7a, 0x11, 0x08, 0x12, 0x0a, 0xc0, 0x7a, 0x21, 0x08, 0x12, 
+    0x0a, 0xc0, 0x7a, 0x31, 0x08, 0x12, 0x0a, 0xc0, 0x7a, 0x41, 0x08, 0x12, 0x0a, 0xc0, 0x7a, 0x51, 
+    0x08, 0x12, 0x0a, 0xc0, 0x7a, 0x61, 0x08, 0x12, 0x0a, 0xc0, 0x7a, 0x71, 0x08, 0x12, 0x0a, 0xc0, 
+    0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x40, 0x7a, 0xb3, 0x91, 0x04, 0x12, 0x05, 0x26, 0x22, 
+    0x6d, 0x00, 0x7e, 0x14, 0x01, 0x02, 0x7a, 0x07, 0x01, 0x35, 0x7a, 0x03, 0x01, 0x30, 0x7e, 0xb3, 
+    0x01, 0x25, 0x20, 0xe7, 0x0f, 0x7a, 0x23, 0x01, 0x2f, 0x7a, 0x33, 0x01, 0x2e, 0xbe, 0x07, 0x01, 
+    0x2b, 0x68, 0x09, 0x22, 0x7a, 0x33, 0x01, 0x2f, 0x7a, 0x23, 0x01, 0x2e, 0x7e, 0xb3, 0x01, 0x25, 
+    0x54, 0xe3, 0x23, 0x23, 0x30, 0xe0, 0x02, 0xd2, 0xe5, 0x30, 0xe7, 0x02, 0xd2, 0xe4, 0x30, 0xe5, 
+    0x06, 0x30, 0xe4, 0x03, 0x02, 0x09, 0x8b, 0x54, 0x3e, 0xf5, 0xf0, 0x03, 0x54, 0x1f, 0xc3, 0x25, 
+    0xf0, 0x90, 0x05, 0x7e, 0x75, 0x84, 0xff, 0x73, 0x02, 0x07, 0x39, 0x02, 0x05, 0xc6, 0x02, 0x07, 
+    0xd2, 0x02, 0x07, 0xed, 0x02, 0x06, 0xd0, 0x02, 0x06, 0x5b, 0x02, 0x08, 0x1e, 0x02, 0x08, 0x1e, 
+    0x02, 0x08, 0x21, 0x02, 0x08, 0x21, 0x02, 0x08, 0x21, 0x02, 0x08, 0x21, 0x02, 0x08, 0x21, 0x02, 
+    0x08, 0x21, 0x02, 0x08, 0x21, 0x02, 0x08, 0x21, 0x02, 0x08, 0x27, 0x02, 0x08, 0xf9, 0x02, 0x08, 
+    0x24, 0x02, 0x08, 0x24, 0x02, 0x08, 0x24, 0x02, 0x08, 0x24, 0x02, 0x08, 0x24, 0x02, 0x08, 0x24, 
+    0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 0xb3, 0x91, 0x1c, 0x7e, 0xb3, 0x01, 0x26, 
+    0xb4, 0x06, 0x2a, 0x7e, 0xb3, 0x01, 0x27, 0x60, 0x79, 0x7c, 0x0b, 0x7e, 0x13, 0x01, 0x28, 0x7e, 
+    0x17, 0x01, 0x29, 0x75, 0x08, 0x72, 0x12, 0x0a, 0xc0, 0x7a, 0x01, 0x08, 0x12, 0x0a, 0xc0, 0x7a, 
+    0x11, 0x08, 0x12, 0x0a, 0xc0, 0x12, 0x09, 0xd0, 0x40, 0x58, 0x02, 0x03, 0x84, 0xb4, 0x08, 0x1c, 
+    0x75, 0x08, 0x74, 0x12, 0x0a, 0xc0, 0x7e, 0xb3, 0x3f, 0xf1, 0x7e, 0x08, 0x01, 0x37, 0x7a, 0x0c, 
+    0x00, 0x00, 0x7a, 0x0b, 0xb0, 0x7e, 0x54, 0x00, 0x01, 0x02, 0x03, 0x84, 0xb4, 0x00, 0x33, 0x75, 
+    0x08, 0x75, 0x12, 0x0a, 0xc0, 0x7e, 0x08, 0x01, 0x37, 0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0x7e, 
+    0xb3, 0x3f, 0xf2, 0x30, 0xe0, 0x07, 0x74, 0x02, 0x7a, 0x0b, 0xb0, 0x80, 0x05, 0x74, 0x00, 0x7a, 
+    0x0b, 0xb0, 0x0b, 0x14, 0x74, 0x00, 0x7a, 0x0b, 0xb0, 0x7e, 0x54, 0x00, 0x02, 0xda, 0x0b, 0x02, 
+    0x03, 0x84, 0x02, 0x09, 0x8b, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 0xb3, 0x91, 
+    0x1c, 0x7e, 0xb3, 0x01, 0x26, 0xb4, 0x00, 0x5f, 0x75, 0x08, 0x76, 0x12, 0x0a, 0xc0, 0x7e, 0xb3, 
+    0x01, 0x2a, 0x54, 0x0f, 0xb4, 0x02, 0x05, 0x7e, 0xb0, 0x60, 0x80, 0x17, 0xb4, 0x00, 0x05, 0x7e, 
+    0xb0, 0x00, 0x80, 0x0f, 0x7e, 0xb3, 0x01, 0x2a, 0x20, 0xe7, 0x05, 0x7e, 0xb0, 0x40, 0x80, 0x03, 
+    0x7e, 0xb0, 0x20, 0x7a, 0xb3, 0x91, 0x00, 0x7e, 0xb3, 0x91, 0x11, 0x30, 0xe0, 0x04, 0x74, 0x01, 
+    0x80, 0x02, 0x74, 0x00, 0x7e, 0x08, 0x01, 0x37, 0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0x7a, 0x0b, 
+    0xb0, 0x0b, 0x14, 0x74, 0x00, 0x7a, 0x0b, 0xb0, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x7e, 0x54, 
+    0x00, 0x02, 0xda, 0x0b, 0x02, 0x03, 0x84, 0x02, 0x09, 0x8b, 0x7e, 0xb3, 0x01, 0x2a, 0x54, 0x0f, 
+    0xb4, 0x02, 0x05, 0x7e, 0xb0, 0x60, 0x80, 0x17, 0xb4, 0x00, 0x05, 0x7e, 0xb0, 0x00, 0x80, 0x0f, 
+    0x7e, 0xb3, 0x01, 0x2a, 0x20, 0xe7, 0x05, 0x7e, 0xb0, 0x40, 0x80, 0x03, 0x7e, 0xb0, 0x20, 0x7a, 
+    0xb3, 0x91, 0x00, 0x7e, 0xb3, 0x01, 0x28, 0xb4, 0x00, 0x26, 0x7e, 0xb3, 0x01, 0x26, 0xb4, 0x01, 
+    0x0e, 0x75, 0x08, 0x77, 0x12, 0x0a, 0xc0, 0x74, 0x01, 0x7a, 0xb3, 0x91, 0x12, 0x80, 0x1b, 0xb4, 
+    0x03, 0x0e, 0x75, 0x08, 0x78, 0x12, 0x0a, 0xc0, 0x74, 0x01, 0x7a, 0xb3, 0x91, 0x11, 0x80, 0x0a, 
+    0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x12, 0x09, 0x8b, 0x22, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 
+    0x02, 0x03, 0x77, 0x7e, 0xb3, 0x01, 0x26, 0xb4, 0x09, 0x1f, 0x75, 0x08, 0x79, 0x12, 0x0a, 0xc0, 
+    0x7e, 0xb3, 0x01, 0x28, 0xbe, 0xb3, 0x3f, 0xf1, 0x68, 0x0d, 0xca, 0xb8, 0x12, 0x01, 0xf1, 0xda, 
+    0xb8, 0x50, 0x76, 0x7a, 0xb3, 0x3f, 0xf1, 0x80, 0x6d, 0xb4, 0x05, 0x08, 0x75, 0x08, 0x7a, 0x12, 
+    0x0a, 0xc0, 0x80, 0x62, 0xb4, 0x03, 0x19, 0x75, 0x08, 0x7b, 0x12, 0x0a, 0xc0, 0x7e, 0xb3, 0x01, 
+    0x28, 0xb4, 0x01, 0x55, 0x7e, 0xb3, 0x3f, 0xf2, 0x44, 0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x46, 
+    0xb4, 0x01, 0x19, 0x75, 0x08, 0x7c, 0x12, 0x0a, 0xc0, 0x7e, 0xb3, 0x01, 0x28, 0xb4, 0x01, 0x39, 
+    0x7e, 0xb3, 0x3f, 0xf2, 0x54, 0xfe, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x2a, 0xb4, 0x07, 0x2a, 0x7e, 
+    0xb3, 0x01, 0x27, 0x60, 0x24, 0x7c, 0x0b, 0x7e, 0x13, 0x01, 0x28, 0x7e, 0x17, 0x01, 0x29, 0x75, 
+    0x08, 0x73, 0x12, 0x0a, 0xc0, 0x7a, 0x01, 0x08, 0x12, 0x0a, 0xc0, 0x7a, 0x11, 0x08, 0x12, 0x0a, 
+    0xc0, 0x12, 0x0a, 0x0a, 0x40, 0x03, 0x02, 0x03, 0x77, 0x02, 0x09, 0x8b, 0x7e, 0xb3, 0x01, 0x26, 
+    0xb4, 0x0b, 0xf6, 0x75, 0x08, 0x7d, 0x12, 0x0a, 0xc0, 0x7e, 0xb3, 0x01, 0x28, 0x7e, 0xa3, 0x01, 
+    0x2a, 0x4c, 0xab, 0x78, 0xe4, 0x80, 0xdf, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 
+    0xb3, 0x91, 0x1c, 0x7e, 0xb3, 0x01, 0x26, 0xb4, 0x0a, 0xcf, 0x75, 0x08, 0x7e, 0x12, 0x0a, 0xc0, 
+    0x7e, 0xb3, 0x01, 0x28, 0x70, 0xc3, 0x7e, 0x08, 0x01, 0x37, 0x7a, 0x0c, 0x00, 0x00, 0x7a, 0x0b, 
+    0xb0, 0x7e, 0x54, 0x00, 0x01, 0x02, 0x03, 0x84, 0x02, 0x09, 0x8b, 0x02, 0x09, 0x8b, 0x02, 0x09, 
+    0x8b, 0x7e, 0xb3, 0x01, 0x26, 0xb4, 0x04, 0x20, 0x75, 0x08, 0xc3, 0x12, 0x0a, 0xc0, 0x7e, 0x04, 
+    0x00, 0x01, 0x7e, 0x17, 0x01, 0x27, 0x7e, 0x18, 0x01, 0x37, 0x7a, 0x1c, 0x00, 0x00, 0x7e, 0x47, 
+    0x01, 0x2b, 0x12, 0x0a, 0xcc, 0x02, 0x08, 0xf3, 0xb4, 0x06, 0x42, 0x75, 0x08, 0xc1, 0x12, 0x0a, 
+    0xc0, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7d, 0xca, 0x7e, 0xd7, 0x01, 0x27, 0x7e, 
+    0x78, 0x01, 0x37, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x01, 0x2b, 0x75, 0x08, 0xc1, 0x12, 0x0a, 
+    0xc0, 0xc0, 0xa8, 0xc2, 0xaf, 0x7e, 0x40, 0x01, 0x7a, 0x43, 0x94, 0x00, 0x12, 0x0b, 0x63, 0x7e, 
+    0x43, 0x01, 0x24, 0x7a, 0x43, 0x94, 0x00, 0xd0, 0xa8, 0x40, 0x65, 0x80, 0x60, 0xb4, 0x00, 0x24, 
+    0xc2, 0xaf, 0x7e, 0xb0, 0x01, 0x7a, 0xb3, 0x94, 0x00, 0x7a, 0xb3, 0x01, 0x24, 0x12, 0x03, 0x77, 
+    0xe4, 0x8d, 0xef, 0x8d, 0xef, 0x8d, 0xef, 0xd5, 0xe0, 0xf7, 0xc0, 0xd1, 0xca, 0x02, 0xff, 0xca, 
+    0x06, 0x00, 0x00, 0x32, 0xb4, 0x09, 0x20, 0x74, 0x03, 0x7a, 0xb3, 0x91, 0x06, 0x7e, 0x23, 0x91, 
+    0x07, 0x7e, 0x57, 0x01, 0x27, 0x4d, 0x55, 0x68, 0x05, 0x4e, 0x20, 0x02, 0x80, 0x03, 0x5e, 0x20, 
+    0xfd, 0x7a, 0x23, 0x91, 0x07, 0x80, 0x16, 0xb4, 0x07, 0x16, 0xc2, 0xaf, 0x7e, 0x07, 0x01, 0x29, 
+    0x7e, 0x17, 0x01, 0x27, 0xc0, 0xd1, 0xca, 0x18, 0xca, 0x38, 0xca, 0x28, 0x32, 0x02, 0x03, 0x77, 
+    0x02, 0x09, 0x8b, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 0xb3, 0x91, 0x1c, 0x7e, 
+    0xb3, 0x01, 0x26, 0xb4, 0x03, 0x15, 0x75, 0x08, 0xc2, 0x12, 0x0a, 0xc0, 0x7e, 0x04, 0x00, 0x01, 
+    0x7e, 0x17, 0x01, 0x27, 0x7e, 0x57, 0x01, 0x2b, 0x02, 0x03, 0x84, 0xb4, 0x05, 0x41, 0x75, 0x08, 
+    0xc0, 0x12, 0x0a, 0xc0, 0xc0, 0xa8, 0xc2, 0xaf, 0x7e, 0x40, 0x01, 0x7a, 0x43, 0x94, 0x00, 0x7e, 
+    0x08, 0x01, 0x37, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x37, 0x01, 0x27, 0x7e, 
+    0x47, 0x01, 0x2b, 0x12, 0x0a, 0xcc, 0x7e, 0x43, 0x01, 0x24, 0x7a, 0x43, 0x94, 0x00, 0xd0, 0xa8, 
+    0x7e, 0x08, 0x01, 0x37, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x57, 0x01, 0x2b, 0x02, 0x03, 0x84, 0xb4, 
+    0x01, 0x20, 0x7e, 0x00, 0x00, 0x7e, 0x10, 0x01, 0x75, 0x08, 0x72, 0x12, 0x0a, 0xc0, 0x7a, 0x01, 
+    0x08, 0x12, 0x0a, 0xc0, 0x7a, 0x11, 0x08, 0x12, 0x0a, 0xc0, 0x12, 0x09, 0xd0, 0x40, 0x03, 0x02, 
+    0x03, 0x84, 0x02, 0x09, 0x8b, 0x75, 0x08, 0x07, 0x12, 0x0a, 0xc0, 0x7e, 0xb0, 0x02, 0x7a, 0xb3, 
+    0x90, 0x00, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x40, 0x7a, 0xb3, 0x91, 0x15, 0x74, 0x01, 
+    0x7a, 0xb3, 0x91, 0x11, 0x7e, 0xb3, 0x91, 0x15, 0x54, 0x60, 0xbe, 0xb0, 0x40, 0x68, 0x08, 0x74, 
+    0x20, 0x7a, 0xb3, 0x91, 0x15, 0x80, 0xed, 0x74, 0x01, 0x7a, 0xb3, 0x91, 0x12, 0x74, 0x04, 0x7a, 
+    0xb3, 0x91, 0x14, 0x74, 0xff, 0x7a, 0xb3, 0x01, 0x2d, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0x7e, 0x40, 
+    0x01, 0x7a, 0x43, 0x94, 0x00, 0x12, 0x0a, 0x57, 0x40, 0x1f, 0x7e, 0x08, 0x01, 0x37, 0x7a, 0x0c, 
+    0x00, 0x00, 0xca, 0x0b, 0xca, 0x49, 0x12, 0x0a, 0xcc, 0xda, 0x59, 0xda, 0x0b, 0x7e, 0x43, 0x01, 
+    0x24, 0x7a, 0x43, 0x94, 0x00, 0xd0, 0xa8, 0xc3, 0x22, 0x7e, 0x43, 0x01, 0x24, 0x7a, 0x43, 0x94, 
+    0x00, 0xd0, 0xa8, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0x7e, 0x40, 0x01, 0x7a, 0x43, 0x94, 0x00, 0x12, 
+    0x0a, 0x57, 0x40, 0x31, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7f, 0x61, 0x7e, 0x78, 
+    0x01, 0x37, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x01, 0x2b, 0xbd, 0x74, 0x78, 0x17, 0x75, 0x08, 
+    0xc1, 0x12, 0x0a, 0xc0, 0x12, 0x0b, 0x63, 0x40, 0x0c, 0x7e, 0x43, 0x01, 0x24, 0x7a, 0x43, 0x94, 
+    0x00, 0xd0, 0xa8, 0xc3, 0x22, 0x7e, 0x43, 0x01, 0x24, 0x7a, 0x43, 0x94, 0x00, 0xd0, 0xa8, 0xd3, 
+    0x22, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x34, 0x7f, 0xca, 0x0b, 0x1a, 0x50, 0xc5, 0xf0, 0x7d, 0x62, 
+    0x7d, 0x75, 0x7d, 0x87, 0x7e, 0x34, 0x7f, 0x03, 0x7e, 0x1b, 0xb0, 0xbc, 0x0b, 0x50, 0x49, 0x3e, 
+    0x00, 0x3e, 0x00, 0x0a, 0x50, 0x2d, 0x75, 0x0b, 0x3a, 0x30, 0x69, 0x53, 0x00, 0x02, 0xbd, 0x38, 
+    0x50, 0x02, 0x2d, 0x38, 0xbc, 0x1b, 0x50, 0x30, 0x3e, 0x10, 0x3e, 0x10, 0x0a, 0x51, 0x2d, 0x35, 
+    0x69, 0x41, 0x00, 0x02, 0x0b, 0x1a, 0x30, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbe, 0x44, 0xff, 
+    0xff, 0x78, 0x05, 0x7e, 0x1b, 0x90, 0x0a, 0x49, 0x4d, 0x44, 0x68, 0x0c, 0xbe, 0x44, 0x00, 0xff, 
+    0x28, 0x04, 0x7e, 0x44, 0x00, 0xff, 0xc3, 0x22, 0xd3, 0x22, 
+
+// Segment #16, EXCLUDED Start Address 00ff7c00, Length 227
+
+
+// Segment #17, EXCLUDED Start Address 00ff7f00, Length 192
+
+
+// Segment #17, Start Address 00ff7fc0, Length 64
+0xff,0x00,0xc0,0x7f,0x40,0x00,
+    0x40, 0x01, 0x02, 0x00, 0xd7, 0x31, 0x02, 0x00, 0x03, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x01, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+
+// Segment #18, Start Address 00ff0ac0, Length 4163
+0xff,0x00,0xc0,0x0a,0x43,0x10,
+    0xca, 0x08, 0x7e, 0x01, 0x08, 0x7a, 0x03, 0x3f, 0xf0, 0xda, 0x08, 0x22, 0x80, 0x50, 0x0b, 0x1a, 
+    0x60, 0x0b, 0x35, 0x0b, 0x1a, 0x70, 0x0b, 0x35, 0x0b, 0x1a, 0x80, 0x0b, 0x35, 0x0b, 0x1a, 0x90, 
+    0x0b, 0x35, 0x0b, 0x1a, 0xa0, 0x0b, 0x35, 0x0b, 0x1a, 0xb0, 0x0b, 0x35, 0x0b, 0x1a, 0xc0, 0x0b, 
+    0x35, 0x0b, 0x1a, 0xd0, 0x0b, 0x35, 0x1b, 0x0a, 0x60, 0x0b, 0x15, 0x1b, 0x0a, 0x70, 0x0b, 0x15, 
+    0x1b, 0x0a, 0x80, 0x0b, 0x15, 0x1b, 0x0a, 0x90, 0x0b, 0x15, 0x1b, 0x0a, 0xa0, 0x0b, 0x15, 0x1b, 
+    0x0a, 0xb0, 0x0b, 0x15, 0x1b, 0x0a, 0xc0, 0x0b, 0x15, 0x1b, 0x0a, 0xd0, 0x0b, 0x15, 0x9e, 0x44, 
+    0x00, 0x10, 0x50, 0xaa, 0x2e, 0x44, 0x00, 0x10, 0x68, 0x0e, 0x7e, 0x1b, 0xc0, 0x7a, 0x0b, 0xc0, 
+    0x0b, 0x14, 0x0b, 0x34, 0x1b, 0x44, 0x78, 0xf2, 0x22, 0x7f, 0x6f, 0x7f, 0xf0, 0x1b, 0xfc, 0x7c, 
+    0x54, 0x7d, 0x32, 0x80, 0x08, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0x9e, 0x44, 0x00, 
+    0x10, 0x50, 0xf2, 0x2e, 0x44, 0x00, 0x10, 0x68, 0x06, 0xca, 0x48, 0x1b, 0x44, 0x78, 0xfa, 0x7f, 
+    0xf6, 0x89, 0xe4, 0xca, 0x6b, 0x5e, 0xd4, 0x00, 0x3f, 0x68, 0x20, 0x7e, 0x84, 0x00, 0x40, 0x9d, 
+    0x8d, 0xda, 0x6b, 0xbd, 0x87, 0x38, 0x16, 0xca, 0x79, 0x7d, 0x78, 0x12, 0x0b, 0x8d, 0xda, 0x79, 
+    0x40, 0x08, 0x9d, 0x78, 0x68, 0x02, 0x80, 0x05, 0xc2, 0xd7, 0x22, 0xda, 0x6b, 0x7e, 0xc0, 0x03, 
+    0x7e, 0xd0, 0x00, 0x7a, 0xd3, 0x90, 0x00, 0x74, 0xaa, 0x39, 0xb5, 0x55, 0x55, 0x74, 0x55, 0x39, 
+    0xb5, 0x2a, 0xaa, 0x74, 0xa0, 0x39, 0xb5, 0x55, 0x55, 0x7e, 0x04, 0x00, 0x40, 0x9d, 0x70, 0x50, 
+    0x06, 0x2d, 0x70, 0x7d, 0x07, 0x6d, 0x77, 0x7c, 0x31, 0x7e, 0x7b, 0x00, 0x7a, 0x6b, 0x00, 0x0b, 
+    0x7c, 0x0b, 0x6c, 0xa5, 0xd9, 0xf3, 0x7f, 0x16, 0x1b, 0x1c, 0x7e, 0x54, 0x27, 0x10, 0x7e, 0x1b, 
+    0x10, 0xbc, 0x10, 0x68, 0x06, 0x1b, 0x54, 0x78, 0xf5, 0x80, 0x2f, 0x6d, 0x00, 0x7c, 0x20, 0x7f, 
+    0x16, 0x9f, 0x10, 0x7f, 0x27, 0x9f, 0x20, 0x7e, 0x2b, 0x00, 0x7e, 0x1b, 0x10, 0xbc, 0x01, 0x78, 
+    0x19, 0x0b, 0x2c, 0x0b, 0x1c, 0xa5, 0xdb, 0xef, 0x7c, 0xb6, 0x20, 0xe0, 0x06, 0x6c, 0xdc, 0x7a, 
+    0xd3, 0x90, 0x00, 0x4d, 0x77, 0x78, 0x90, 0xc2, 0xd7, 0x22, 0xd2, 0xd7, 0x22, 0x00, 0x04, 0x00, 
+    0x04, 0x00, 0x00, 0x06, 0x04, 0x02, 0x04, 0x00, 0x02, 0x01, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x00, 0x08, 0x10, 0x02, 0x10, 
+    0x04, 0x02, 0x08, 0x00, 0x01, 0x01, 0x08, 0x7e, 0x18, 0x7f, 0xbd, 0x7a, 0x1c, 0x00, 0xff, 0x0b, 
+    0x1a, 0x00, 0x5e, 0x10, 0x1f, 0xbe, 0x10, 0x14, 0x38, 0x1a, 0x0a, 0x51, 0x23, 0x7e, 0x18, 0x0c, 
+    0x0d, 0x7a, 0x1c, 0x00, 0xff, 0x2d, 0x35, 0x0b, 0x1a, 0x50, 0x60, 0x08, 0xa5, 0xb8, 0x02, 0x03, 
+    0x4e, 0xa0, 0x08, 0x22, 0x80, 0xfe, 0x7e, 0xe8, 0x7f, 0xbf, 0x7a, 0xec, 0x00, 0xff, 0xe0, 0xf5, 
+    0x23, 0x54, 0xc0, 0x68, 0x38, 0x7e, 0xe8, 0x7f, 0xbe, 0x7a, 0xec, 0x00, 0xff, 0xe0, 0x60, 0x2e, 
+    0x12, 0x0c, 0x37, 0xf5, 0x21, 0x7a, 0xa1, 0x20, 0x20, 0x09, 0x0c, 0x20, 0x0a, 0x12, 0x7e, 0xb0, 
+    0x0e, 0x7a, 0xb3, 0x92, 0x00, 0x80, 0x10, 0x7e, 0xb0, 0x02, 0x7a, 0xb3, 0x92, 0x00, 0x80, 0x07, 
+    0x7e, 0xb0, 0x0a, 0x7a, 0xb3, 0x92, 0x00, 0x7a, 0xb1, 0x0d, 0x02, 0x0c, 0xc4, 0x22, 0x7e, 0xb0, 
+    0x02, 0x7a, 0xb3, 0x90, 0x00, 0x12, 0x19, 0x0c, 0x7e, 0xb0, 0x03, 0x7a, 0xb3, 0x90, 0x00, 0x12, 
+    0x19, 0x0c, 0x80, 0xea, 0xc2, 0xaf, 0xc2, 0x11, 0xc2, 0x12, 0x75, 0xb0, 0xdf, 0x7e, 0x00, 0x01, 
+    0x7a, 0x03, 0x93, 0x00, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x90, 0x00, 0x6c, 0x00, 0x7e, 0x10, 0x03, 
+    0x12, 0x0c, 0xf5, 0x7e, 0x68, 0x2c, 0x66, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x0b, 0x00, 
+    0x80, 0x32, 0x02, 0x1a, 0x6e, 0x20, 0x11, 0x2b, 0x7e, 0xb0, 0x01, 0x7a, 0xb3, 0x90, 0x00, 0x12, 
+    0x19, 0x0c, 0x7e, 0xb0, 0x03, 0x7a, 0xb3, 0x90, 0x00, 0x12, 0x19, 0x0c, 0x7e, 0xb0, 0x02, 0x7a, 
+    0xb3, 0x90, 0x00, 0x12, 0x19, 0x0c, 0xa5, 0xd9, 0xdc, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x90, 0x00, 
+    0x12, 0x19, 0x0c, 0x22, 0x7e, 0x68, 0x2c, 0xf9, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 
+    0xe4, 0x10, 0x00, 0x7e, 0x40, 0x55, 0x7a, 0xe9, 0x40, 0x0b, 0xe4, 0x7e, 0x50, 0xaa, 0x7a, 0xe9, 
+    0x50, 0x1b, 0xe4, 0xbe, 0xe9, 0x40, 0x68, 0x19, 0x7e, 0x68, 0x2c, 0xdf, 0x7a, 0x6c, 0x00, 0xff, 
+    0x12, 0x19, 0xc4, 0x12, 0x19, 0x19, 0x30, 0x11, 0x13, 0x7a, 0xe9, 0x40, 0x7e, 0xe9, 0x10, 0x80, 
+    0xf8, 0x7e, 0x68, 0x2c, 0xda, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x0b, 0x00, 0x7e, 0x68, 
+    0x2d, 0x3d, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 0x78, 0x00, 0x00, 0x7e, 0x70, 0x0e, 
+    0x7e, 0xa4, 0xff, 0xff, 0x7e, 0xb4, 0xbf, 0xff, 0x7d, 0xcb, 0x0e, 0xc4, 0x7d, 0xdc, 0x5d, 0xdb, 
+    0x6c, 0xbb, 0x7d, 0xfa, 0x5e, 0xf4, 0x7f, 0xff, 0x7a, 0x7b, 0xb0, 0x0b, 0xb0, 0x7d, 0xfb, 0x5e, 
+    0xf4, 0x7f, 0xff, 0x7a, 0x7b, 0xb0, 0x0b, 0xb0, 0x7d, 0xfc, 0x5e, 0xf4, 0x7f, 0xff, 0x7a, 0x7b, 
+    0xb0, 0x0b, 0xb0, 0x7d, 0xfd, 0x5e, 0xf4, 0x7f, 0xff, 0x7a, 0x7b, 0xb0, 0x6c, 0xbb, 0x7d, 0xfa, 
+    0x5e, 0xf4, 0x7f, 0xff, 0xbe, 0x7b, 0xb0, 0x78, 0x41, 0x0b, 0xb0, 0x7d, 0xfb, 0x5e, 0xf4, 0x7f, 
+    0xff, 0xbe, 0x7b, 0xb0, 0x78, 0x34, 0x0b, 0xb0, 0x7d, 0xfc, 0x5e, 0xf4, 0x7f, 0xff, 0xbe, 0x7b, 
+    0xb0, 0x78, 0x27, 0x0b, 0xb0, 0x7d, 0xfd, 0x5e, 0xf4, 0x7f, 0xff, 0xbe, 0x7b, 0xb0, 0x78, 0x1a, 
+    0x0b, 0xb0, 0xbe, 0xc4, 0xff, 0xfe, 0x78, 0x92, 0x0e, 0xb4, 0xa5, 0xdf, 0x8b, 0x7e, 0x68, 0x2c, 
+    0xe7, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x80, 0x77, 0xca, 0x5b, 0xca, 0x6b, 0x7e, 0x68, 
+    0x2c, 0xf0, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 0x68, 0x2d, 0x8f, 0x7a, 0x6c, 0x00, 
+    0xff, 0x12, 0x19, 0xc4, 0x0a, 0x47, 0x12, 0x19, 0xfa, 0x7e, 0x68, 0x2d, 0xde, 0x7a, 0x6c, 0x00, 
+    0xff, 0x12, 0x19, 0xc4, 0x6c, 0x77, 0xda, 0x6b, 0xca, 0x6b, 0x0b, 0x70, 0x0e, 0xc4, 0xbe, 0xc4, 
+    0xff, 0xff, 0x78, 0xf6, 0x1b, 0x70, 0x0a, 0x47, 0x12, 0x19, 0xfa, 0x12, 0x19, 0x19, 0x30, 0x11, 
+    0x30, 0xda, 0x6b, 0xda, 0x5b, 0x6c, 0xbb, 0x7e, 0x78, 0x00, 0x00, 0x7d, 0xfa, 0x5e, 0xf4, 0x7f, 
+    0xff, 0x7a, 0x7b, 0xb0, 0x7d, 0xfb, 0x5e, 0xf4, 0x7f, 0xff, 0x7a, 0x7b, 0xb0, 0x7d, 0xfc, 0x5e, 
+    0xf4, 0x7f, 0xff, 0x7a, 0x7b, 0xb0, 0x7d, 0xfd, 0x5e, 0xf4, 0x7f, 0xff, 0x7a, 0x7b, 0xb0, 0x80, 
+    0xd4, 0x7e, 0x68, 0x2d, 0x1b, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x30, 0x1f, 0x0e, 0x7e, 
+    0x78, 0x04, 0x20, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x44, 0x7b, 0xe0, 0x80, 0x0c, 0x7e, 0x78, 0x00, 
+    0x00, 0x7a, 0x7c, 0x00, 0x01, 0x7e, 0x44, 0x80, 0x00, 0x0b, 0x00, 0x7e, 0x40, 0x3a, 0x7c, 0x54, 
+    0x7f, 0x57, 0x7d, 0x84, 0x6c, 0x66, 0x7a, 0x5b, 0x50, 0x0b, 0x5c, 0x0b, 0x50, 0xa5, 0xde, 0x02, 
+    0x0b, 0x50, 0x1b, 0x84, 0x78, 0xf0, 0x7c, 0x54, 0x7f, 0x57, 0x7d, 0x84, 0x6c, 0x66, 0xbe, 0x5b, 
+    0x50, 0x78, 0x1a, 0x0b, 0x5c, 0x0b, 0x50, 0xa5, 0xde, 0x02, 0x0b, 0x50, 0x1b, 0x84, 0x78, 0xee, 
+    0x7e, 0x68, 0x2c, 0xda, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x80, 0x4b, 0x7f, 0x45, 0x7e, 
+    0x68, 0x2c, 0xdf, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 0x68, 0x2d, 0x5f, 0x7a, 0x6c, 
+    0x00, 0xff, 0x12, 0x19, 0xc4, 0x7d, 0x4b, 0x12, 0x19, 0xfa, 0x7e, 0x68, 0x2d, 0x74, 0x7a, 0x6c, 
+    0x00, 0xff, 0x12, 0x19, 0xc4, 0x6c, 0x88, 0x7c, 0x95, 0x12, 0x19, 0xfa, 0x7e, 0x68, 0x2d, 0x82, 
+    0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 0x4b, 0x90, 0x12, 0x19, 0xfa, 0x12, 0x19, 0x19, 
+    0x30, 0x11, 0x05, 0x7e, 0x4b, 0x90, 0x80, 0xfb, 0x7e, 0x68, 0x2e, 0x28, 0x7a, 0x6c, 0x00, 0xff, 
+    0x12, 0x19, 0xc4, 0x0b, 0x00, 0x7e, 0xb0, 0x80, 0x7a, 0xb3, 0x91, 0x00, 0x7e, 0xa0, 0x55, 0x7a, 
+    0xa3, 0x91, 0x10, 0x7e, 0xb3, 0x91, 0x07, 0x7e, 0xb3, 0x91, 0x10, 0xbc, 0xab, 0x78, 0x20, 0x7e, 
+    0xa0, 0xaa, 0x7a, 0xa3, 0x91, 0x10, 0x7e, 0xb3, 0x91, 0x07, 0x7e, 0xb3, 0x91, 0x10, 0xbc, 0xab, 
+    0x78, 0x0d, 0x7e, 0x68, 0x2c, 0xda, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x80, 0x1b, 0x7e, 
+    0x68, 0x2c, 0xdf, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 0x19, 0x19, 0x30, 0x11, 0x0a, 
+    0x7a, 0xa3, 0x91, 0x10, 0x7e, 0xb3, 0x91, 0x10, 0x80, 0xf6, 0x7e, 0x68, 0x2e, 0x4a, 0x7a, 0x6c, 
+    0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 0x12, 0x31, 0x0b, 0x00, 0x7e, 0xe4, 0x10, 0x00, 0x7e, 0xa0, 
+    0xa5, 0xca, 0xa8, 0x7a, 0xe9, 0xa0, 0x7e, 0xb0, 0x30, 0x7a, 0xb3, 0x95, 0x00, 0x7e, 0xe9, 0xa0, 
+    0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x95, 0x00, 0x12, 0x19, 0x0c, 0x0b, 0xe5, 0x7e, 0xb0, 0x20, 0x7a, 
+    0xb3, 0x95, 0x00, 0x7e, 0xe9, 0xb0, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x95, 0x00, 0x7e, 0xe9, 0xb0, 
+    0xda, 0xa8, 0xbc, 0xab, 0x78, 0x0d, 0x7e, 0x68, 0x2c, 0xda, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 
+    0xc4, 0x80, 0x1d, 0x7e, 0x68, 0x2c, 0xdf, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 0x19, 
+    0x19, 0x30, 0x11, 0x0c, 0x7e, 0xb0, 0x38, 0x7a, 0xb3, 0x95, 0x00, 0x7e, 0xe9, 0xb0, 0x80, 0xfb, 
+    0x80, 0x00, 0x7e, 0x68, 0x2d, 0xe4, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x0b, 0x00, 0x75, 
+    0xb0, 0xdf, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 0x00, 0x08, 0xbe, 0xb0, 0x01, 0x78, 0x0b, 0x09, 
+    0xb2, 0x00, 0x14, 0xbe, 0xb0, 0x60, 0x78, 0x02, 0x80, 0x17, 0x7e, 0x68, 0x2c, 0xdf, 0x7a, 0x6c, 
+    0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 0x19, 0x19, 0x30, 0x11, 0x11, 0x09, 0xb2, 0x00, 0x08, 0x80, 
+    0xfa, 0x7e, 0x68, 0x2c, 0xda, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 0x68, 0x2e, 0x06, 
+    0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x0b, 0x00, 0x75, 0xb0, 0xef, 0x12, 0x18, 0xff, 0x7e, 
+    0x24, 0x80, 0x00, 0x7e, 0xa0, 0x55, 0x19, 0xa2, 0x00, 0x1c, 0x7e, 0xb0, 0x01, 0x19, 0xb2, 0x00, 
+    0x08, 0x09, 0xb2, 0x00, 0x1c, 0xbc, 0xab, 0x78, 0x37, 0x09, 0xb2, 0x00, 0x08, 0x5e, 0xb0, 0xc0, 
+    0xbe, 0xb0, 0xc0, 0x78, 0x2b, 0x7e, 0xa0, 0xaa, 0x19, 0xa2, 0x00, 0x1c, 0x6c, 0xbb, 0x19, 0xb2, 
+    0x00, 0x08, 0x09, 0xb2, 0x00, 0x1c, 0xbc, 0xab, 0x78, 0x16, 0x09, 0xb2, 0x00, 0x08, 0x5e, 0xb0, 
+    0xc0, 0x78, 0x0d, 0x7e, 0x68, 0x2c, 0xda, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x80, 0x1b, 
+    0x7e, 0x68, 0x2c, 0xdf, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 0x19, 0x19, 0x30, 0x11, 
+    0x0a, 0x19, 0xa2, 0x00, 0x1c, 0x09, 0xb2, 0x00, 0x1c, 0x80, 0xf6, 0x7e, 0x68, 0x2e, 0x6c, 0x7a, 
+    0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 0x68, 0x2e, 0xee, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 
+    0xc4, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x7e, 0xb0, 0x01, 0x19, 0xb2, 0x00, 0x1c, 0x2e, 
+    0x24, 0x01, 0x00, 0x0b, 0xb0, 0xa5, 0xd9, 0xf3, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x7e, 
+    0xb0, 0x01, 0x0b, 0x00, 0x09, 0xa2, 0x00, 0x1c, 0xbc, 0xab, 0x78, 0x16, 0x7e, 0x68, 0x2c, 0xe7, 
+    0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x2e, 0x24, 0x01, 0x00, 0x0b, 0xb0, 0xa5, 0xd9, 0xe2, 
+    0x80, 0x25, 0x7e, 0x68, 0x2c, 0xf0, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 0x19, 0x19, 
+    0x30, 0x11, 0xe4, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x09, 0xa2, 0x00, 0x1c, 0x2e, 0x24, 
+    0x01, 0x00, 0xa5, 0xd9, 0xf5, 0x80, 0xec, 0x7e, 0x68, 0x2f, 0x12, 0x7a, 0x6c, 0x00, 0xff, 0x12, 
+    0x19, 0xc4, 0x12, 0x12, 0x31, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x0b, 0x00, 0x74, 0x10, 
+    0x19, 0xb2, 0x00, 0x10, 0x12, 0x11, 0xaa, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xee, 0x7e, 0x68, 
+    0x2f, 0x36, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 
+    0x0b, 0x00, 0xe4, 0x19, 0xb2, 0x00, 0x10, 0x12, 0x11, 0xaa, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 
+    0xef, 0x30, 0x00, 0x03, 0x02, 0x17, 0x3b, 0x02, 0x12, 0x6a, 0x74, 0x07, 0x19, 0xb2, 0x00, 0x08, 
+    0x12, 0x19, 0x0c, 0x09, 0xb2, 0x00, 0x00, 0x09, 0xb2, 0x00, 0x14, 0x09, 0xb2, 0x00, 0x00, 0x09, 
+    0xb2, 0x00, 0x14, 0x09, 0xb2, 0x00, 0x00, 0x09, 0xb2, 0x00, 0x14, 0x09, 0xb2, 0x00, 0x00, 0x09, 
+    0xb2, 0x00, 0x14, 0xc2, 0x13, 0x7e, 0xb0, 0x55, 0x12, 0x12, 0x0b, 0x7e, 0xb0, 0xaa, 0x12, 0x12, 
+    0x0b, 0x7e, 0xb0, 0x00, 0x12, 0x12, 0x0b, 0x7e, 0xb0, 0xff, 0x12, 0x12, 0x0b, 0x30, 0x13, 0x0f, 
+    0x7e, 0x68, 0x2c, 0xf0, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 0x19, 0x19, 0x22, 0x7e, 
+    0x68, 0x2c, 0xe7, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x22, 0x19, 0xb2, 0x00, 0x00, 0x12, 
+    0x18, 0xff, 0x09, 0xa2, 0x00, 0x00, 0xbc, 0xab, 0x78, 0x01, 0x22, 0x20, 0x11, 0x03, 0xd2, 0x13, 
+    0x22, 0x12, 0x19, 0x19, 0x19, 0xb2, 0x00, 0x00, 0x12, 0x18, 0xff, 0x09, 0xa2, 0x00, 0x00, 0x80, 
+    0xf3, 0x75, 0xb0, 0xdf, 0x12, 0x18, 0xff, 0x75, 0xb0, 0xef, 0x12, 0x18, 0xff, 0x7e, 0x24, 0x80, 
+    0x00, 0x7e, 0x11, 0x21, 0x74, 0x80, 0x19, 0xb2, 0x00, 0x0c, 0x7e, 0x54, 0x00, 0x02, 0x19, 0xa2, 
+    0x00, 0x04, 0x19, 0xb2, 0x00, 0x00, 0x74, 0x03, 0x19, 0xb2, 0x00, 0x0c, 0x74, 0x06, 0x19, 0xb2, 
+    0x00, 0x08, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xdb, 0x22, 0x7e, 0x68, 0x2f, 0x5a, 0x7a, 0x6c, 
+    0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x0b, 0x00, 0x12, 0x18, 
+    0xff, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x55, 0x19, 0xa2, 0x00, 0x00, 0x12, 0x18, 0xff, 0x09, 
+    0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x05, 0x78, 0x0d, 0x7e, 0x68, 0x2c, 0xe7, 0x7a, 0x6c, 0x00, 0xff, 
+    0x12, 0x19, 0xc4, 0x80, 0x1a, 0x7e, 0x68, 0x2c, 0xf0, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 
+    0x12, 0x19, 0x19, 0x30, 0x11, 0x09, 0x19, 0xa2, 0x00, 0x00, 0x12, 0x18, 0xff, 0x80, 0xf7, 0x2e, 
+    0x24, 0x01, 0x00, 0xa5, 0xd9, 0xb6, 0x7e, 0x68, 0x2f, 0x7e, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 
+    0xc4, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x0b, 0x00, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 
+    0x18, 0x7e, 0xa0, 0x55, 0x19, 0xa2, 0x00, 0x00, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x5e, 
+    0xb0, 0x0a, 0x78, 0x0d, 0x7e, 0x68, 0x2c, 0xe7, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x80, 
+    0x1a, 0x7e, 0x68, 0x2c, 0xf0, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 0x19, 0x19, 0x30, 
+    0x11, 0x09, 0x19, 0xa2, 0x00, 0x00, 0x12, 0x18, 0xff, 0x80, 0xf7, 0x2e, 0x24, 0x01, 0x00, 0xa5, 
+    0xd9, 0xb6, 0x30, 0x04, 0x03, 0x02, 0x15, 0x9f, 0x7e, 0x68, 0x2f, 0xa2, 0x7a, 0x6c, 0x00, 0xff, 
+    0x12, 0x19, 0xc4, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x0b, 0x00, 0x6c, 0xaa, 0x19, 0xa2, 
+    0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 
+    0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x0a, 
+    0x78, 0x3c, 0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 
+    0x7e, 0xa0, 0x03, 0x19, 0xa2, 0x00, 0x10, 0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 
+    0xff, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x0a, 0x78, 0x14, 0x7e, 0x68, 0x2c, 0xe7, 0x7a, 0x6c, 
+    0x00, 0xff, 0x12, 0x19, 0xc4, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0x9e, 0x80, 0x20, 0x7e, 0x68, 
+    0x2c, 0xf0, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 0x19, 0x19, 0x30, 0x11, 0xe6, 0x7e, 
+    0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x80, 0xf1, 0x7e, 0x68, 
+    0x2f, 0xea, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 
+    0x0b, 0x00, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x7e, 
+    0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 
+    0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x05, 0x78, 0x3c, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x12, 
+    0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x03, 0x19, 0xa2, 0x00, 0x10, 0x7e, 0xa0, 0x02, 
+    0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x05, 0x78, 0x14, 
+    0x7e, 0x68, 0x2c, 0xe7, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x2e, 0x24, 0x01, 0x00, 0xa5, 
+    0xd9, 0x9e, 0x80, 0x20, 0x7e, 0x68, 0x2c, 0xf0, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 
+    0x19, 0x19, 0x30, 0x11, 0xe6, 0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 
+    0x00, 0x10, 0x80, 0xf1, 0x7e, 0x68, 0x30, 0x32, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 
+    0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x0b, 0x00, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x12, 
+    0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x50, 0xbe, 0xb0, 0x50, 0x78, 0x1f, 0x6c, 0xaa, 
+    0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x50, 0x78, 0x0d, 
+    0x7e, 0x68, 0x2c, 0xe7, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x80, 0x20, 0x7e, 0x68, 0x2c, 
+    0xf0, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 0x19, 0x19, 0x30, 0x11, 0x0f, 0x7e, 0xa0, 
+    0x02, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x80, 0xf1, 0x2e, 0x24, 0x01, 
+    0x00, 0xa5, 0xd9, 0xa2, 0x7e, 0x68, 0x30, 0x7a, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 
+    0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x0b, 0x00, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x01, 0x19, 
+    0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0xa0, 0xbe, 0xb0, 0xa0, 
+    0x78, 0x1f, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x5e, 
+    0xb0, 0xa0, 0x78, 0x0d, 0x7e, 0x68, 0x2c, 0xe7, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x80, 
+    0x20, 0x7e, 0x68, 0x2c, 0xf0, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 0x19, 0x19, 0x30, 
+    0x11, 0x0f, 0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x80, 
+    0xf1, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0x9e, 0x7e, 0x68, 0x30, 0x9e, 0x7a, 0x6c, 0x00, 0xff, 
+    0x12, 0x19, 0xc4, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x0b, 0x00, 0x20, 0xb1, 0x26, 0x7e, 
+    0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x30, 0xb1, 0x19, 0x6c, 0xaa, 0x19, 0xa2, 
+    0x00, 0x10, 0x12, 0x18, 0xff, 0x20, 0xb1, 0x0d, 0x7e, 0x68, 0x2c, 0xe7, 0x7a, 0x6c, 0x00, 0xff, 
+    0x12, 0x19, 0xc4, 0x80, 0x20, 0x7e, 0x68, 0x2c, 0xf0, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 
+    0x12, 0x19, 0x19, 0x30, 0x11, 0x0f, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 
+    0xa2, 0x00, 0x10, 0x80, 0xf1, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xae, 0x02, 0x17, 0x3b, 0x7e, 
+    0x68, 0x2f, 0xc6, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 
+    0x21, 0x0b, 0x00, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 
+    0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 
+    0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x06, 0x78, 0x3c, 0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 
+    0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x03, 0x19, 0xa2, 0x00, 0x10, 0x7e, 0xa0, 
+    0x01, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x06, 0x78, 
+    0x14, 0x7e, 0x68, 0x2c, 0xe7, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x2e, 0x24, 0x01, 0x00, 
+    0xa5, 0xd9, 0x9e, 0x80, 0x20, 0x7e, 0x68, 0x2c, 0xf0, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 
+    0x12, 0x19, 0x19, 0x30, 0x11, 0xe6, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 
+    0xa2, 0x00, 0x10, 0x80, 0xf1, 0x7e, 0x68, 0x30, 0x0e, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 
+    0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x0b, 0x00, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 
+    0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x01, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 
+    0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x09, 0x78, 0x3c, 0x7e, 
+    0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x7e, 0xa0, 0x03, 
+    0x19, 0xa2, 0x00, 0x10, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 
+    0x00, 0x18, 0x5e, 0xb0, 0x09, 0x78, 0x14, 0x7e, 0x68, 0x2c, 0xe7, 0x7a, 0x6c, 0x00, 0xff, 0x12, 
+    0x19, 0xc4, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0x9e, 0x80, 0x20, 0x7e, 0x68, 0x2c, 0xf0, 0x7a, 
+    0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 0x19, 0x19, 0x30, 0x11, 0xe6, 0x7e, 0xa0, 0x01, 0x19, 
+    0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x80, 0xf1, 0x7e, 0x68, 0x30, 0x56, 0x7a, 
+    0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x0b, 0x00, 0x7e, 
+    0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 0x00, 0x18, 0x5e, 0xb0, 0x90, 
+    0xbe, 0xb0, 0x90, 0x78, 0x1f, 0x6c, 0xaa, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x09, 0xb2, 
+    0x00, 0x18, 0x5e, 0xb0, 0x90, 0x78, 0x0d, 0x7e, 0x68, 0x2c, 0xe7, 0x7a, 0x6c, 0x00, 0xff, 0x12, 
+    0x19, 0xc4, 0x80, 0x20, 0x7e, 0x68, 0x2c, 0xf0, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x12, 
+    0x19, 0x19, 0x30, 0x11, 0x0f, 0x7e, 0xa0, 0x02, 0x19, 0xa2, 0x00, 0x10, 0x6c, 0xaa, 0x19, 0xa2, 
+    0x00, 0x10, 0x80, 0xf1, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xa2, 0x20, 0x1f, 0x68, 0x12, 0x12, 
+    0x31, 0x12, 0x17, 0xa9, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 0x0b, 0x00, 0x20, 0x89, 0x26, 
+    0x7e, 0xa0, 0xff, 0x19, 0xa2, 0x00, 0x04, 0x12, 0x18, 0xff, 0x7e, 0xb0, 0x55, 0x19, 0xb2, 0x00, 
+    0x00, 0x12, 0x18, 0xff, 0x30, 0x89, 0x0f, 0x7e, 0xa0, 0x00, 0x19, 0xa2, 0x00, 0x04, 0x12, 0x18, 
+    0xff, 0x20, 0x89, 0x02, 0x80, 0x26, 0x12, 0x19, 0x19, 0x30, 0x11, 0x20, 0x7e, 0xa0, 0xff, 0x19, 
+    0xa2, 0x00, 0x04, 0x12, 0x18, 0xff, 0x7e, 0xb0, 0x55, 0x19, 0xb2, 0x00, 0x00, 0x12, 0x18, 0xff, 
+    0x7e, 0xa0, 0x00, 0x19, 0xa2, 0x00, 0x04, 0x12, 0x18, 0xff, 0x80, 0xe0, 0x2e, 0x24, 0x01, 0x00, 
+    0xa5, 0xd9, 0xa8, 0x02, 0x17, 0xc2, 0x02, 0x18, 0x4c, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x21, 
+    0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, 0x10, 0x12, 0x18, 0xff, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 
+    0xef, 0x22, 0x30, 0x1f, 0x03, 0x02, 0x18, 0x4c, 0xc2, 0x8a, 0x12, 0x17, 0xa9, 0x0b, 0x00, 0x12, 
+    0x18, 0x16, 0x20, 0x8b, 0x24, 0x74, 0x03, 0x7a, 0xb3, 0x91, 0x06, 0x74, 0x02, 0x7a, 0xb3, 0x91, 
+    0x07, 0x74, 0x0c, 0x7a, 0xb3, 0x91, 0x06, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x07, 0x12, 0x19, 0x0c, 
+    0x30, 0x8b, 0x06, 0x12, 0x18, 0x16, 0x30, 0x8b, 0xad, 0x12, 0x19, 0x19, 0x30, 0x11, 0xa7, 0x12, 
+    0x18, 0x16, 0x74, 0x03, 0x7a, 0xb3, 0x91, 0x06, 0x74, 0x02, 0x7a, 0xb3, 0x91, 0x07, 0x12, 0x19, 
+    0x0c, 0x12, 0x18, 0x16, 0x80, 0xe9, 0x7e, 0xa0, 0x00, 0x74, 0x02, 0x7a, 0xb3, 0x91, 0x06, 0x7a, 
+    0xa3, 0x91, 0x07, 0x74, 0x03, 0x7a, 0xb3, 0x91, 0x06, 0x7a, 0xa3, 0x91, 0x07, 0x12, 0x18, 0xff, 
+    0x74, 0xef, 0x7a, 0xb3, 0x91, 0x04, 0x74, 0x80, 0x7a, 0xb3, 0x91, 0x03, 0x74, 0x0c, 0x7a, 0xb3, 
+    0x91, 0x06, 0x74, 0x08, 0x7a, 0xb3, 0x91, 0x07, 0x12, 0x19, 0x0c, 0x22, 0x30, 0x12, 0x19, 0x7e, 
+    0x68, 0x30, 0xc2, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0xd2, 0x11, 0x12, 0x18, 0xff, 0x12, 
+    0x18, 0xff, 0x12, 0x18, 0xff, 0x02, 0x0c, 0xca, 0x30, 0x1f, 0x1c, 0x7e, 0x68, 0x31, 0x3c, 0x7a, 
+    0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x7e, 0x68, 0x31, 0x5e, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 
+    0xc4, 0x12, 0x1a, 0x6e, 0x02, 0x18, 0xf7, 0x0b, 0x00, 0x7e, 0x78, 0x18, 0xb1, 0x7a, 0x7c, 0x00, 
+    0xff, 0x7f, 0x67, 0x7a, 0x6c, 0x00, 0x00, 0x7e, 0x70, 0x3e, 0x7e, 0x7b, 0xb0, 0x7a, 0x6b, 0xb0, 
+    0x0b, 0x7c, 0x0b, 0x6c, 0xa5, 0xdf, 0xf3, 0x7e, 0x78, 0x18, 0xb1, 0x7a, 0x7c, 0x00, 0x00, 0x89, 
+    0x78, 0x7e, 0x78, 0x00, 0x00, 0x7a, 0x7c, 0x00, 0xfe, 0x7e, 0x68, 0x7f, 0xbf, 0x7a, 0x6c, 0x00, 
+    0xfe, 0x74, 0xaa, 0x39, 0xb7, 0x55, 0x55, 0x74, 0x55, 0x39, 0xb7, 0x2a, 0xaa, 0x74, 0xa0, 0x39, 
+    0xb7, 0x55, 0x55, 0x6c, 0x99, 0x7a, 0x6b, 0x90, 0x7e, 0x54, 0x27, 0x10, 0x7e, 0x6b, 0x80, 0xbc, 
+    0x89, 0x68, 0x08, 0x1b, 0x54, 0x78, 0xf5, 0x8a, 0xff, 0x18, 0xef, 0x8a, 0xff, 0x18, 0xf7, 0x12, 
+    0x19, 0x19, 0x7e, 0x6b, 0x80, 0x80, 0xfb, 0x7e, 0x10, 0xff, 0x12, 0x19, 0xac, 0x80, 0xf8, 0xca, 
+    0xf9, 0x7e, 0xf4, 0x00, 0xff, 0x1b, 0xf4, 0x78, 0xfc, 0xda, 0xf9, 0x22, 0xca, 0xf9, 0x7e, 0xf4, 
+    0x00, 0x00, 0x1b, 0xf4, 0x78, 0xfc, 0xda, 0xf9, 0x22, 0x20, 0x11, 0x20, 0xd2, 0x12, 0x12, 0x19, 
+    0x0c, 0x7e, 0xb0, 0x02, 0x7a, 0xb3, 0x90, 0x00, 0x12, 0x19, 0x0c, 0x12, 0x19, 0x0c, 0x12, 0x19, 
+    0x0c, 0x12, 0x19, 0x0c, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x90, 0x00, 0x22, 0xca, 0x0b, 0x7e, 0x10, 
+    0x03, 0x7c, 0x30, 0x6c, 0x22, 0x0b, 0x20, 0x9e, 0x30, 0x0a, 0x50, 0xf9, 0x2e, 0x30, 0x0b, 0x1b, 
+    0x20, 0x68, 0x20, 0x12, 0x19, 0x0c, 0x12, 0x19, 0x0c, 0x7e, 0xb0, 0x03, 0x7a, 0xb3, 0x90, 0x00, 
+    0x12, 0x19, 0x0c, 0x12, 0x19, 0x0c, 0x12, 0x19, 0x0c, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x90, 0x00, 
+    0xa5, 0xda, 0xe0, 0x12, 0x19, 0x0c, 0x12, 0x19, 0x0c, 0x1b, 0x30, 0x68, 0x20, 0x12, 0x19, 0x0c, 
+    0x12, 0x19, 0x0c, 0x7e, 0xb0, 0x02, 0x7a, 0xb3, 0x90, 0x00, 0x12, 0x19, 0x0c, 0x12, 0x19, 0x0c, 
+    0x12, 0x19, 0x0c, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x90, 0x00, 0xa5, 0xdb, 0xe0, 0x7e, 0x20, 0x0a, 
+    0x12, 0x19, 0x0c, 0xa5, 0xda, 0xfa, 0xa5, 0xd9, 0x98, 0xda, 0x0b, 0x22, 0x20, 0x11, 0x14, 0x12, 
+    0x19, 0x0c, 0x7e, 0xb0, 0x01, 0x7a, 0xb3, 0x90, 0x00, 0x12, 0x19, 0x0c, 0x7e, 0xb0, 0x00, 0x7a, 
+    0xb3, 0x90, 0x00, 0x22, 0x30, 0x1f, 0x32, 0x20, 0x11, 0x2f, 0xca, 0x2b, 0xca, 0x7b, 0x7e, 0x78, 
+    0x80, 0x00, 0x7a, 0x7c, 0x00, 0xfe, 0x12, 0x1a, 0x4d, 0x7e, 0x6b, 0xa0, 0x5c, 0xaa, 0x68, 0x10, 
+    0x29, 0xb7, 0x00, 0x14, 0x54, 0x60, 0x68, 0xf8, 0x39, 0xa7, 0x00, 0x00, 0x0b, 0x6c, 0x80, 0xe9, 
+    0x12, 0x18, 0xff, 0xd2, 0xb5, 0xda, 0x7b, 0xda, 0x2b, 0x22, 0x12, 0x1a, 0x05, 0x7e, 0x68, 0x00, 
+    0x0c, 0x12, 0x19, 0xc4, 0x22, 0xca, 0x59, 0xca, 0x5b, 0x7e, 0xb4, 0x00, 0x0c, 0x7c, 0xb8, 0xc4, 
+    0x12, 0x1a, 0x35, 0x7c, 0xb8, 0x12, 0x1a, 0x35, 0x7c, 0xb9, 0xc4, 0x12, 0x1a, 0x35, 0x7c, 0xb9, 
+    0x12, 0x1a, 0x35, 0x7e, 0xb0, 0x68, 0x7a, 0xb9, 0xb0, 0x0b, 0xb4, 0x6c, 0xbb, 0x7a, 0xb9, 0xb0, 
+    0xda, 0x59, 0xda, 0x5b, 0x22, 0x5e, 0xb0, 0x0f, 0x7c, 0xab, 0x9e, 0xa0, 0x0a, 0x40, 0x05, 0x2e, 
+    0xb0, 0x37, 0x80, 0x03, 0x2e, 0xb0, 0x30, 0x7a, 0xb9, 0xb0, 0x0b, 0xb4, 0x22, 0xc2, 0xb5, 0x75, 
+    0xb0, 0xef, 0x12, 0x18, 0xff, 0x74, 0x80, 0x39, 0xb7, 0x00, 0x0c, 0x7e, 0x54, 0x00, 0x06, 0x39, 
+    0xa7, 0x00, 0x04, 0x39, 0xb7, 0x00, 0x00, 0x74, 0x03, 0x39, 0xb7, 0x00, 0x0c, 0x22, 0x7e, 0x78, 
+    0x00, 0x00, 0x7a, 0x7c, 0x00, 0xff, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0x01, 0x7f, 0x65, 
+    0x7e, 0x74, 0x20, 0x00, 0x12, 0x0b, 0x63, 0x40, 0x58, 0x7e, 0x78, 0x7c, 0x00, 0x7a, 0x7c, 0x00, 
+    0xff, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0x01, 0x7e, 0x68, 0x7c, 0x00, 0x7a, 0x6c, 0x00, 
+    0x01, 0x7e, 0x74, 0x04, 0x00, 0x12, 0x0b, 0x63, 0x40, 0x37, 0x74, 0x80, 0x12, 0x1a, 0xea, 0x40, 
+    0x30, 0x7e, 0x00, 0x03, 0x7a, 0x03, 0x90, 0x00, 0xd2, 0x10, 0x7e, 0x04, 0x00, 0x08, 0x7e, 0x14, 
+    0x00, 0x00, 0x84, 0xa5, 0xdb, 0xfc, 0xa5, 0xda, 0xf9, 0xa5, 0xd9, 0xf6, 0x74, 0x40, 0x12, 0x1a, 
+    0xea, 0x40, 0x0e, 0x7e, 0x68, 0x31, 0x8d, 0x7a, 0x6c, 0x00, 0xff, 0x12, 0x19, 0xc4, 0x02, 0x18, 
+    0xf7, 0x7e, 0xb0, 0x02, 0x7a, 0xb3, 0x90, 0x00, 0x80, 0xfe, 0xf5, 0x0b, 0x7e, 0x78, 0x00, 0x0b, 
+    0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x68, 0x7f, 0xbf, 0x7a, 0x6c, 0x00, 0x01, 0x7e, 0x74, 0x00, 0x01, 
+    0x02, 0x0b, 0x63, 
+
+// Segment #19, EXCLUDED Start Address 00ff2c66, Length 1393
+
+};
+
+static EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME = {
+       2, 0, 3 };              // Major, Minor, Build
+
+#undef IMAGE_VERSION_NAME
+
+#undef IMAGE_ARRAY_NAME
+
diff --git a/drivers/usb/serial/io_fw_down.h b/drivers/usb/serial/io_fw_down.h
new file mode 100644 (file)
index 0000000..336c04e
--- /dev/null
@@ -0,0 +1,1123 @@
+//**************************************************************
+//* Edgeport/4 Binary Image
+//* Generated by HEX2C v1.06
+//* Copyright(c) 1998 Inside Out Networks, All rights reserved.
+//*    This program is free software; you can redistribute it and/or modify
+//*    it under the terms of the GNU General Public License as published by
+//*    the Free Software Foundation; either version 2 of the License, or
+//*    (at your option) any later version.
+//**************************************************************
+
+
+//Image structure definition
+#if !defined(DEFINED_EDGE_FIRMWARE_IMAGE_RECORD)
+       #define DEFINED_EDGE_FIRMWARE_IMAGE_RECORD
+       typedef struct _EDGE_FIRMWARE_IMAGE_RECORD
+       {
+               unsigned short  ExtAddr;
+               unsigned short  Addr;
+               unsigned short  Len;
+               unsigned char   Data[0];
+       } EDGE_FIRMWARE_IMAGE_RECORD, *PEDGE_FIRMWARE_IMAGE_RECORD;
+
+       typedef struct _EDGE_FIRMWARE_VERSION_INFO
+       {
+               unsigned char   MajorVersion;
+               unsigned char   MinorVersion;
+               unsigned short  BuildNumber;
+       } EDGE_FIRMWARE_VERSION_INFO, *PEDGE_FIRMWARE_VERSION_INFO;
+
+#endif
+
+#if !defined(IMAGE_ARRAY_NAME)
+       #define IMAGE_ARRAY_NAME        FirmwareImage
+       #define IMAGE_VERSION_NAME      FirmwareImageVersion
+#endif
+
+static unsigned char IMAGE_ARRAY_NAME[] = {
+
+// Segment #1, Start Address 00ff0000, Length 6
+0xff,0x00,0x00,0x00,0x06,0x00,
+    0x02, 0x00, 0x80, 0x02, 0x49, 0x39, 
+
+// Segment #2, Start Address 00ff000b, Length 3
+0xff,0x00,0x0b,0x00,0x03,0x00,
+    0x02, 0x44, 0x1a, 
+
+// Segment #3, Start Address 00ff0013, Length 3
+0xff,0x00,0x13,0x00,0x03,0x00,
+    0x02, 0x00, 0x13, 
+
+// Segment #4, Start Address 00ff001b, Length 3
+0xff,0x00,0x1b,0x00,0x03,0x00,
+    0x02, 0x00, 0x1b, 
+
+// Segment #5, Start Address 00ff0023, Length 3
+0xff,0x00,0x23,0x00,0x03,0x00,
+    0x02, 0x00, 0x23, 
+
+// Segment #6, Start Address 00ff002b, Length 3
+0xff,0x00,0x2b,0x00,0x03,0x00,
+    0x02, 0x00, 0x2b, 
+
+// Segment #7, Start Address 00ff0033, Length 3
+0xff,0x00,0x33,0x00,0x03,0x00,
+    0x02, 0x00, 0x33, 
+
+// Segment #8, Start Address 00ff003b, Length 3
+0xff,0x00,0x3b,0x00,0x03,0x00,
+    0x02, 0x00, 0x3b, 
+
+// Segment #9, Start Address 00ff0043, Length 3
+0xff,0x00,0x43,0x00,0x03,0x00,
+    0x02, 0x00, 0x43, 
+
+// Segment #10, Start Address 00ff004b, Length 3
+0xff,0x00,0x4b,0x00,0x03,0x00,
+    0x02, 0x70, 0xd4, 
+
+// Segment #11, Start Address 00ff0053, Length 3
+0xff,0x00,0x53,0x00,0x03,0x00,
+    0x02, 0x77, 0x9d, 
+
+// Segment #12, Start Address 00ff007b, Length 3
+0xff,0x00,0x7b,0x00,0x03,0x00,
+    0x02, 0x00, 0x7b, 
+
+// Segment #13, Start Address 00ff0080, Length 7
+0xff,0x00,0x80,0x00,0x07,0x00,
+    0x7e, 0x14, 0x00, 0x00, 0x02, 0x40, 0x51, 
+
+// Segment #14, Start Address 00ff4000, Length 15920
+0xff,0x00,0x00,0x40,0x30,0x3e,
+    0x7e, 0x04, 0x00, 0x01, 0x7e, 0x14, 0x7f, 0xf8, 0x7e, 0x24, 0x00, 0xfe, 0x7d, 0x31, 0x0b, 0x1a, 
+    0x50, 0x1b, 0x0a, 0x50, 0x7e, 0x14, 0x40, 0x1b, 0x02, 0x40, 0x6a, 0x7e, 0xf8, 0x00, 0x59, 0xd2, 
+    0x04, 0xc2, 0x94, 0xd2, 0x95, 0x7e, 0xf4, 0x40, 0x2c, 0x02, 0x40, 0x7c, 0x12, 0x7f, 0x3f, 0xf5, 
+    0x2e, 0x7a, 0xa1, 0x2d, 0x7a, 0x11, 0x58, 0x12, 0x77, 0xda, 0x12, 0x40, 0xdc, 0x7e, 0xb3, 0x3f, 
+    0xf1, 0x60, 0x03, 0x12, 0x43, 0x68, 0x75, 0xf1, 0x00, 0x12, 0x78, 0x7f, 0xd2, 0xaf, 0x02, 0x44, 
+    0x06, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 0x40, 0x5f, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xa9, 
+    0x25, 0x87, 0x03, 0xa9, 0xd5, 0x87, 0xd2, 0x93, 0x89, 0x08, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 
+    0x40, 0x78, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xc2, 0x93, 0x89, 0x08, 0x7e, 0x08, 0x00, 0x20, 
+    0x7e, 0x44, 0x04, 0x00, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0x8e, 0x02, 0x7e, 0x4b, 0x7e, 0x08, 
+    0x01, 0x59, 0x7e, 0x44, 0x28, 0x7c, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0xa0, 0x02, 0x7e, 0x4b, 
+    0x7e, 0x08, 0x00, 0x59, 0x7e, 0x44, 0x01, 0x00, 0x7e, 0x40, 0x53, 0x7e, 0xe4, 0x40, 0xb2, 0x02, 
+    0x7e, 0x4b, 0x75, 0x57, 0x20, 0x75, 0x56, 0x30, 0x7e, 0x04, 0x00, 0x08, 0x75, 0x54, 0x58, 0x75, 
+    0x55, 0x08, 0x75, 0x51, 0x08, 0x75, 0x53, 0x01, 0x75, 0x89, 0x01, 0x75, 0x8a, 0x01, 0x75, 0x8c, 
+    0x00, 0xd2, 0x8c, 0x7e, 0x04, 0x00, 0x02, 0x7a, 0x05, 0x42, 0x89, 0xf4, 0x75, 0xb7, 0x7f, 0x75, 
+    0xb8, 0x7f, 0x75, 0xb3, 0x07, 0x75, 0xb2, 0x07, 0xd2, 0xa9, 0x22, 0xd2, 0x92, 0xe4, 0xd5, 0xe0, 
+    0xfd, 0xc2, 0x92, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x2e, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, 
+    0x10, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xf2, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x72, 0x0b, 0x20, 
+    0xbe, 0x21, 0x2e, 0x78, 0xf6, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x74, 0xbf, 0x19, 0xb0, 
+    0x00, 0x0c, 0x74, 0x10, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x80, 0x19, 0xb0, 0x00, 0x0c, 0x7e, 0x54, 
+    0x00, 0x02, 0x19, 0xa0, 0x00, 0x04, 0x19, 0xb0, 0x00, 0x00, 0x74, 0x03, 0x19, 0xb0, 0x00, 0x0c, 
+    0x74, 0x07, 0x20, 0x68, 0x02, 0x74, 0x0f, 0x19, 0xb0, 0x00, 0x04, 0x30, 0x6b, 0x17, 0x74, 0xbf, 
+    0x19, 0xb0, 0x00, 0x0c, 0x74, 0x28, 0x20, 0x68, 0x02, 0x74, 0x20, 0x19, 0xb0, 0x00, 0x04, 0x74, 
+    0x03, 0x19, 0xb0, 0x00, 0x0c, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x0c, 0x19, 0xb0, 0x00, 
+    0x10, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0xe4, 0x19, 0xb0, 0x00, 0x04, 0x09, 0xb0, 0x00, 
+    0x10, 0x54, 0x08, 0x19, 0xb0, 0x00, 0x10, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x22, 0x7c, 0xb2, 
+    0x23, 0x0a, 0x2b, 0x49, 0x22, 0x41, 0x99, 0x89, 0x24, 0x41, 0xa9, 0x41, 0xc6, 0x41, 0xe3, 0x42, 
+    0x00, 0x42, 0x1d, 0x42, 0x3a, 0x42, 0x57, 0x42, 0x74, 0xc2, 0x10, 0xc2, 0x18, 0xc2, 0x08, 0x7e, 
+    0x04, 0x09, 0xcd, 0x7a, 0x07, 0x01, 0x59, 0x7a, 0x07, 0x01, 0x69, 0x6d, 0x00, 0x7a, 0x07, 0x01, 
+    0x79, 0x7a, 0x07, 0x01, 0x89, 0x22, 0xc2, 0x11, 0xc2, 0x19, 0xc2, 0x09, 0x7e, 0x04, 0x0d, 0xcd, 
+    0x7a, 0x07, 0x01, 0x5b, 0x7a, 0x07, 0x01, 0x6b, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 0x07, 
+    0x01, 0x8b, 0x22, 0xc2, 0x12, 0xc2, 0x1a, 0xc2, 0x0a, 0x7e, 0x04, 0x11, 0xcd, 0x7a, 0x07, 0x01, 
+    0x5d, 0x7a, 0x07, 0x01, 0x6d, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7d, 0x7a, 0x07, 0x01, 0x8d, 0x22, 
+    0xc2, 0x13, 0xc2, 0x1b, 0xc2, 0x0b, 0x7e, 0x04, 0x15, 0xcd, 0x7a, 0x07, 0x01, 0x5f, 0x7a, 0x07, 
+    0x01, 0x6f, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7f, 0x7a, 0x07, 0x01, 0x8f, 0x22, 0xc2, 0x14, 0xc2, 
+    0x1c, 0xc2, 0x0c, 0x7e, 0x04, 0x19, 0xcd, 0x7a, 0x07, 0x01, 0x61, 0x7a, 0x07, 0x01, 0x71, 0x6d, 
+    0x00, 0x7a, 0x07, 0x01, 0x81, 0x7a, 0x07, 0x01, 0x91, 0x22, 0xc2, 0x15, 0xc2, 0x1d, 0xc2, 0x0d, 
+    0x7e, 0x04, 0x1d, 0xcd, 0x7a, 0x07, 0x01, 0x63, 0x7a, 0x07, 0x01, 0x73, 0x6d, 0x00, 0x7a, 0x07, 
+    0x01, 0x83, 0x7a, 0x07, 0x01, 0x93, 0x22, 0xc2, 0x16, 0xc2, 0x1e, 0xc2, 0x0e, 0x7e, 0x04, 0x21, 
+    0xcd, 0x7a, 0x07, 0x01, 0x65, 0x7a, 0x07, 0x01, 0x75, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x85, 0x7a, 
+    0x07, 0x01, 0x95, 0x22, 0xc2, 0x17, 0xc2, 0x1f, 0xc2, 0x0f, 0x7e, 0x04, 0x25, 0xcd, 0x7a, 0x07, 
+    0x01, 0x67, 0x7a, 0x07, 0x01, 0x77, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x87, 0x7a, 0x07, 0x01, 0x97, 
+    0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x42, 0x9c, 0x89, 0x24, 0x42, 0xac, 0x42, 0xc3, 
+    0x42, 0xda, 0x42, 0xf1, 0x43, 0x08, 0x43, 0x1f, 0x43, 0x36, 0x43, 0x4d, 0x30, 0x40, 0x07, 0x20, 
+    0x58, 0x04, 0xc2, 0x28, 0x80, 0x0c, 0x30, 0x48, 0x07, 0x20, 0x50, 0x04, 0xc2, 0x28, 0x80, 0x02, 
+    0xd2, 0x28, 0x22, 0x30, 0x41, 0x07, 0x20, 0x59, 0x04, 0xc2, 0x29, 0x80, 0x0c, 0x30, 0x49, 0x07, 
+    0x20, 0x51, 0x04, 0xc2, 0x29, 0x80, 0x02, 0xd2, 0x29, 0x22, 0x30, 0x42, 0x07, 0x20, 0x5a, 0x04, 
+    0xc2, 0x2a, 0x80, 0x0c, 0x30, 0x4a, 0x07, 0x20, 0x52, 0x04, 0xc2, 0x2a, 0x80, 0x02, 0xd2, 0x2a, 
+    0x22, 0x30, 0x43, 0x07, 0x20, 0x5b, 0x04, 0xc2, 0x2b, 0x80, 0x0c, 0x30, 0x4b, 0x07, 0x20, 0x53, 
+    0x04, 0xc2, 0x2b, 0x80, 0x02, 0xd2, 0x2b, 0x22, 0x30, 0x44, 0x07, 0x20, 0x5c, 0x04, 0xc2, 0x2c, 
+    0x80, 0x0c, 0x30, 0x4c, 0x07, 0x20, 0x54, 0x04, 0xc2, 0x2c, 0x80, 0x02, 0xd2, 0x2c, 0x22, 0x30, 
+    0x45, 0x07, 0x20, 0x5d, 0x04, 0xc2, 0x2d, 0x80, 0x0c, 0x30, 0x4d, 0x07, 0x20, 0x55, 0x04, 0xc2, 
+    0x2d, 0x80, 0x02, 0xd2, 0x2d, 0x22, 0x30, 0x46, 0x07, 0x20, 0x5e, 0x04, 0xc2, 0x2e, 0x80, 0x0c, 
+    0x30, 0x4e, 0x07, 0x20, 0x56, 0x04, 0xc2, 0x2e, 0x80, 0x02, 0xd2, 0x2e, 0x22, 0x30, 0x47, 0x07, 
+    0x20, 0x5f, 0x04, 0xc2, 0x2f, 0x80, 0x0c, 0x30, 0x4f, 0x07, 0x20, 0x57, 0x04, 0xc2, 0x2f, 0x80, 
+    0x02, 0xd2, 0x2f, 0x22, 0x43, 0xcc, 0x43, 0x79, 0xbe, 0xb0, 0x02, 0x40, 0x01, 0x22, 0x23, 0x0a, 
+    0x5b, 0x49, 0x55, 0x43, 0x64, 0x99, 0x54, 0xd3, 0x22, 0xa9, 0xc5, 0x87, 0x12, 0x43, 0xd7, 0x7e, 
+    0x04, 0x05, 0xcd, 0x7a, 0x07, 0x01, 0xc1, 0x7a, 0x07, 0x01, 0xc3, 0x7e, 0x04, 0x01, 0xcd, 0x7a, 
+    0x07, 0x01, 0xc7, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x04, 0x76, 0xbd, 0x7a, 0x05, 0x4b, 0x75, 0xf1, 
+    0x01, 0x75, 0xe1, 0x1f, 0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x75, 0xf1, 0x02, 0x75, 0xe1, 0x03, 
+    0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x43, 0xa2, 0x1c, 0x12, 0x40, 0xeb, 0x7e, 0x20, 0x00, 0x12, 
+    0x41, 0x8e, 0x0b, 0x20, 0xbe, 0x21, 0x2e, 0x78, 0xf6, 0xd2, 0xa8, 0x22, 0xa9, 0xd5, 0x87, 0x12, 
+    0x43, 0xd7, 0xd2, 0x92, 0xc2, 0xa8, 0x22, 0x75, 0xa3, 0x00, 0x53, 0xa2, 0x03, 0x75, 0xc1, 0x00, 
+    0x53, 0xc0, 0x03, 0x7e, 0x00, 0x05, 0x7a, 0x01, 0xf1, 0x43, 0xf4, 0x80, 0x43, 0xe4, 0x80, 0xe5, 
+    0xf2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xf2, 0xe5, 0xe2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xe2, 0x75, 
+    0xe1, 0x10, 0xa5, 0xd8, 0xe1, 0x22, 0x12, 0x44, 0x76, 0x12, 0x44, 0x8c, 0x12, 0x45, 0x27, 0x12, 
+    0x45, 0x57, 0x12, 0x49, 0x0f, 0x12, 0x44, 0xd8, 0x80, 0xec, 0xca, 0x09, 0x12, 0x44, 0x58, 0x10, 
+    0x01, 0x12, 0xd5, 0x51, 0x1e, 0x63, 0x53, 0x01, 0x7e, 0x00, 0x54, 0x2e, 0x01, 0x53, 0xa5, 0xe6, 
+    0xf5, 0x51, 0x80, 0x12, 0x20, 0x02, 0x1e, 0x75, 0x53, 0x00, 0x85, 0x54, 0x51, 0xd2, 0x02, 0x74, 
+    0x00, 0x80, 0x0d, 0x30, 0x02, 0x0f, 0xc2, 0x02, 0x7e, 0x00, 0x56, 0x2e, 0x01, 0x53, 0xa5, 0xe6, 
+    0x53, 0x90, 0xcf, 0x42, 0x90, 0xda, 0x09, 0x32, 0xe5, 0x23, 0x60, 0x19, 0x7e, 0x14, 0x00, 0x00, 
+    0x09, 0xb1, 0x01, 0xb9, 0xb4, 0x00, 0x02, 0x80, 0x05, 0x14, 0x19, 0xb1, 0x01, 0xb9, 0xa5, 0x0a, 
+    0xbe, 0x21, 0x2e, 0x78, 0xeb, 0x22, 0xc2, 0xaf, 0x7e, 0xb3, 0x3f, 0xf1, 0xb4, 0x01, 0x0a, 0xc0, 
+    0xf1, 0x75, 0xf1, 0x02, 0x12, 0x72, 0xff, 0xd0, 0xf1, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x22, 
+    0x60, 0x43, 0x7e, 0x07, 0x01, 0xcb, 0xbe, 0x04, 0x03, 0x80, 0x38, 0x39, 0x7e, 0x04, 0x80, 0x00, 
+    0x7e, 0x20, 0x00, 0x13, 0x50, 0x21, 0x09, 0xa0, 0x00, 0x04, 0x4e, 0xa0, 0x05, 0x19, 0xa0, 0x00, 
+    0x04, 0x0a, 0x32, 0x09, 0x53, 0x6a, 0x93, 0x5e, 0x51, 0x27, 0x68, 0x0b, 0x09, 0xa0, 0x00, 0x10, 
+    0x4e, 0xa0, 0x01, 0x19, 0xa0, 0x00, 0x10, 0x2e, 0x04, 0x01, 0x00, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 
+    0x78, 0xd1, 0x75, 0x22, 0x00, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x26, 0x60, 0x36, 0x7e, 0x20, 
+    0x00, 0x7e, 0x30, 0x01, 0xe5, 0x26, 0xa5, 0x5b, 0x68, 0x21, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 
+    0x32, 0x01, 0x79, 0xbe, 0x34, 0x00, 0x00, 0x68, 0x12, 0x7e, 0xb1, 0x21, 0xa5, 0x4b, 0x7a, 0xb1, 
+    0x21, 0xca, 0x19, 0x49, 0x22, 0x45, 0x17, 0x99, 0x24, 0xda, 0x19, 0x3e, 0x30, 0xa5, 0x0a, 0xbe, 
+    0x21, 0x2e, 0x78, 0xd0, 0xd2, 0xaf, 0x22, 0x4a, 0x98, 0x4d, 0xcd, 0x51, 0x02, 0x54, 0x37, 0x57, 
+    0x6c, 0x5a, 0xa1, 0x5d, 0xd6, 0x61, 0x0b, 0xc2, 0xaf, 0xe5, 0x24, 0x60, 0x14, 0x7e, 0x20, 0x00, 
+    0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x45, 0x44, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 
+    0xef, 0xd2, 0xaf, 0x22, 0xca, 0x28, 0x12, 0x6a, 0xac, 0xda, 0x28, 0x40, 0x09, 0x0a, 0x22, 0x09, 
+    0xb2, 0x6a, 0x93, 0xf4, 0x52, 0x24, 0x22, 0xc2, 0xaf, 0xe5, 0x23, 0x60, 0x14, 0x7e, 0x20, 0x00, 
+    0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x45, 0x74, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 
+    0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x45, 0x7f, 0x89, 0x24, 0x45, 
+    0x8f, 0x45, 0xff, 0x46, 0x6f, 0x46, 0xdf, 0x47, 0x4f, 0x47, 0xbf, 0x48, 0x2f, 0x48, 0x9f, 0x7e, 
+    0x27, 0x01, 0x79, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 0x00, 
+    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4d, 
+    0x96, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
+    0x89, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x89, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xb9, 0x80, 0x2e, 
+    0x7e, 0x63, 0x01, 0xb9, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
+    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x18, 0x6c, 0x00, 
+    0x7a, 0x03, 0x01, 0xb9, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
+    0x27, 0x01, 0x7b, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 0x00, 
+    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x50, 
+    0xcb, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
+    0x8b, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8b, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xba, 0x80, 0x2e, 
+    0x7e, 0x63, 0x01, 0xba, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
+    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x19, 0x6c, 0x00, 
+    0x7a, 0x03, 0x01, 0xba, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
+    0x27, 0x01, 0x7d, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x82, 0x00, 0x09, 0xb2, 0x00, 
+    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x54, 
+    0x00, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
+    0x8d, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8d, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbb, 0x80, 0x2e, 
+    0x7e, 0x63, 0x01, 0xbb, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
+    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1a, 0x6c, 0x00, 
+    0x7a, 0x03, 0x01, 0xbb, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
+    0x27, 0x01, 0x7f, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, 0x00, 
+    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x57, 
+    0x35, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
+    0x8f, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8f, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbc, 0x80, 0x2e, 
+    0x7e, 0x63, 0x01, 0xbc, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
+    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1b, 0x6c, 0x00, 
+    0x7a, 0x03, 0x01, 0xbc, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
+    0x27, 0x01, 0x81, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 0x00, 
+    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5a, 
+    0x6a, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
+    0x91, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x91, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbd, 0x80, 0x2e, 
+    0x7e, 0x63, 0x01, 0xbd, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
+    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1c, 0x6c, 0x00, 
+    0x7a, 0x03, 0x01, 0xbd, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
+    0x27, 0x01, 0x83, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, 0x00, 
+    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5d, 
+    0x9f, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
+    0x93, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x93, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbe, 0x80, 0x2e, 
+    0x7e, 0x63, 0x01, 0xbe, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
+    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1d, 0x6c, 0x00, 
+    0x7a, 0x03, 0x01, 0xbe, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
+    0x27, 0x01, 0x85, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 0x00, 
+    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x60, 
+    0xd4, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
+    0x95, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x95, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbf, 0x80, 0x2e, 
+    0x7e, 0x63, 0x01, 0xbf, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
+    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1e, 0x6c, 0x00, 
+    0x7a, 0x03, 0x01, 0xbf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
+    0x27, 0x01, 0x87, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x87, 0x00, 0x09, 0xb2, 0x00, 
+    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x64, 
+    0x09, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
+    0x97, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x97, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xc0, 0x80, 0x2e, 
+    0x7e, 0x63, 0x01, 0xc0, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
+    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1f, 0x6c, 0x00, 
+    0x7a, 0x03, 0x01, 0xc0, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0xc2, 
+    0xaf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0xa9, 0x32, 0xf2, 0x1a, 0x7e, 0x07, 0x01, 0xcb, 0xbe, 0x04, 
+    0x00, 0x00, 0x78, 0x10, 0xe5, 0xf5, 0x33, 0x82, 0xe7, 0x40, 0x09, 0x85, 0x31, 0x2f, 0x12, 0x7e, 
+    0x30, 0x75, 0xf6, 0x00, 0xd0, 0xf1, 0xd2, 0xaf, 0x22, 0xc0, 0xd0, 0xc0, 0xd1, 0xc0, 0xe0, 0xc0, 
+    0xf0, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xd2, 0x01, 0x75, 0x2f, 0x89, 0x12, 0x7e, 0x30, 0x7e, 
+    0x14, 0x80, 0x00, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x49, 0xd8, 0x20, 0x70, 0x5a, 
+    0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x49, 0xf0, 0x20, 0x71, 0x4b, 0xa5, 
+    0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x08, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 
+    0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x20, 0x20, 0x72, 0x30, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 
+    0x20, 0xe0, 0x03, 0x02, 0x4a, 0x38, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 
+    0x4a, 0x50, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x68, 0xa5, 0x0a, 
+    0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x80, 0x30, 0x04, 0x0c, 0xc2, 0x04, 0xc0, 
+    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0xd0, 
+    0xf0, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 0x32, 0x75, 0x2f, 0x80, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
+    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x66, 0x34, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
+    0x75, 0x2f, 0x81, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
+    0x66, 0x74, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x82, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
+    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x66, 0xb4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
+    0x75, 0x2f, 0x83, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
+    0x66, 0xf4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x84, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
+    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x67, 0x34, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
+    0x75, 0x2f, 0x85, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
+    0x67, 0x74, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x86, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
+    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x67, 0xb4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
+    0x75, 0x2f, 0x87, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
+    0x67, 0xf4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x10, 0x08, 0x01, 0x22, 0x20, 0x28, 0x03, 0xd2, 
+    0x08, 0x22, 0x75, 0x2f, 0xa0, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x80, 0x00, 0x80, 0x06, 0x20, 0x28, 
+    0x03, 0xd2, 0x08, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 
+    0x03, 0x12, 0x4d, 0x96, 0x30, 0x30, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x08, 0x22, 0x30, 0xe6, 0x02, 
+    0xd2, 0x60, 0x7e, 0x37, 0x01, 0x79, 0x7e, 0x27, 0x01, 0x99, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 
+    0x2e, 0x05, 0x32, 0x7a, 0x05, 0x32, 0x7a, 0x37, 0x01, 0x79, 0x7e, 0x37, 0x01, 0x59, 0x7d, 0x43, 
+    0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x59, 0x75, 0x2f, 0x94, 0x12, 
+    0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x60, 0xc4, 0x22, 0xc2, 
+    0x60, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x79, 0xbe, 0x24, 0x00, 
+    0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x99, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x99, 0x7e, 0x37, 0x01, 
+    0x79, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x32, 0x7a, 0x05, 0x32, 0x7a, 0x37, 0x01, 0x79, 0x7e, 
+    0x37, 0x01, 0x59, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 
+    0x59, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 
+    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x0d, 0xcd, 
+    0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x09, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 
+    0x59, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4b, 0x0b, 0x22, 0xd2, 0x08, 0x7e, 
+    0x04, 0x09, 0xcd, 0x7a, 0x07, 0x01, 0x59, 0x7a, 0x07, 0x01, 0x69, 0x75, 0x2f, 0x94, 0x12, 0x7e, 
+    0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 
+    0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 
+    0x7e, 0x27, 0x01, 0xa9, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 
+    0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 
+    0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 
+    0x00, 0x00, 0x2e, 0x27, 0x01, 0xa9, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
+    0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 
+    0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x38, 0x0a, 0x09, 
+    0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 0x80, 0x7f, 0x7a, 0x51, 
+    0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x00, 0x00, 0x2e, 0x67, 
+    0x01, 0xa9, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 
+    0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 
+    0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 
+    0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x00, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 
+    0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 
+    0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 
+    0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 
+    0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 
+    0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 
+    0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 
+    0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 
+    0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 
+    0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x4c, 0x6f, 0x75, 
+    0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 
+    0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 0xda, 
+    0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4c, 0x6f, 0xda, 0xb8, 0x02, 
+    0x4d, 0x96, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 
+    0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 
+    0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 
+    0x50, 0x80, 0x02, 0xc2, 0x50, 0x12, 0x42, 0xac, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 
+    0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 
+    0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 
+    0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 
+    0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4c, 0xc3, 0x75, 
+    0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x09, 0x01, 
+    0x22, 0x20, 0x29, 0x03, 0xd2, 0x09, 0x22, 0x75, 0x2f, 0xa1, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x81, 
+    0x00, 0x80, 0x06, 0x20, 0x29, 0x03, 0xd2, 0x09, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 
+    0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x50, 0xcb, 0x30, 0x31, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 
+    0x09, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x61, 0x7e, 0x37, 0x01, 0x7b, 0x7e, 0x27, 0x01, 0x9b, 0x9d, 
+    0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x34, 0x7a, 0x05, 0x34, 0x7a, 0x37, 0x01, 0x7b, 0x7e, 
+    0x37, 0x01, 0x5b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 
+    0x5b, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 
+    0x10, 0x61, 0xc4, 0x22, 0xc2, 0x61, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 
+    0x01, 0x7b, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x9b, 0x28, 0x04, 0x7e, 0x27, 
+    0x01, 0x9b, 0x7e, 0x37, 0x01, 0x7b, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x34, 0x7a, 0x05, 0x34, 
+    0x7a, 0x37, 0x01, 0x7b, 0x7e, 0x37, 0x01, 0x5b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xcc, 
+    0x38, 0x13, 0x7a, 0x47, 0x01, 0x5b, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 
+    0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
+    0x30, 0x9e, 0x44, 0x11, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x0d, 0xcd, 0x7d, 0x24, 
+    0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5b, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4e, 
+    0x40, 0x22, 0xd2, 0x09, 0x7e, 0x04, 0x0d, 0xcd, 0x7a, 0x07, 0x01, 0x5b, 0x7a, 0x07, 0x01, 0x6b, 
+    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 
+    0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 
+    0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xab, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 
+    0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 
+    0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 
+    0x47, 0x01, 0xc9, 0x7e, 0x24, 0x01, 0x00, 0x2e, 0x27, 0x01, 0xab, 0x1b, 0x38, 0x20, 0x0b, 0x35, 
+    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 
+    0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 
+    0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 
+    0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 
+    0x64, 0x01, 0x00, 0x2e, 0x67, 0x01, 0xab, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 
+    0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 
+    0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 
+    0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x01, 0x7a, 
+    0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 
+    0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 
+    0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 
+    0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 
+    0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 
+    0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 
+    0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 
+    0xe7, 0x02, 0x4f, 0xa4, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 
+    0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 
+    0x10, 0xd2, 0x11, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 
+    0x4f, 0xa4, 0xda, 0xb8, 0x02, 0x50, 0xcb, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 
+    0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x80, 0x68, 0x04, 0xd2, 0x51, 0x80, 0x02, 0xc2, 0x51, 0x12, 0x42, 0xc3, 0x02, 0x65, 0x9c, 
+    0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 
+    0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 
+    0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 
+    0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 
+    0x22, 0x02, 0x4f, 0xf8, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 
+    0x30, 0x22, 0x10, 0x0a, 0x01, 0x22, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x75, 0x2f, 0xa2, 0x12, 
+    0x7e, 0x30, 0x7e, 0x14, 0x82, 0x00, 0x80, 0x06, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x09, 0xb1, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x54, 0x00, 0x30, 0x32, 
+    0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0a, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x62, 0x7e, 0x37, 0x01, 0x7d, 
+    0x7e, 0x27, 0x01, 0x9d, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x36, 0x7a, 0x05, 0x36, 
+    0x7a, 0x37, 0x01, 0x7d, 0x7e, 0x37, 0x01, 0x5d, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xcc, 
+    0x38, 0x68, 0x7a, 0x47, 0x01, 0x5d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 
+    0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x62, 0xc4, 0x22, 0xc2, 0x62, 0x2d, 0x23, 0x68, 0x78, 0x6d, 
+    0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x7d, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 
+    0x9d, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 
+    0x05, 0x36, 0x7a, 0x05, 0x36, 0x7a, 0x37, 0x01, 0x7d, 0x7e, 0x37, 0x01, 0x5d, 0x7d, 0x43, 0x2d, 
+    0x42, 0xbe, 0x44, 0x15, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x5d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 
+    0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
+    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x15, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 
+    0x34, 0x11, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5d, 0x12, 0x68, 0x34, 0xbe, 0x25, 
+    0x20, 0x78, 0x03, 0x02, 0x51, 0x75, 0x22, 0xd2, 0x0a, 0x7e, 0x04, 0x11, 0xcd, 0x7a, 0x07, 0x01, 
+    0x5d, 0x7a, 0x07, 0x01, 0x6d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 
+    0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 
+    0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xad, 0x2e, 0x24, 
+    0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 
+    0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x02, 0x00, 0x2e, 0x27, 0x01, 0xad, 
+    0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 
+    0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 
+    0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 
+    0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 
+    0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x02, 0x00, 0x2e, 0x67, 0x01, 0xad, 0x9e, 0x24, 0x00, 0x02, 
+    0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 
+    0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 
+    0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 
+    0x23, 0x23, 0x44, 0x02, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 
+    0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 
+    0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 
+    0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 
+    0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 
+    0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 
+    0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 
+    0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 
+    0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 
+    0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x52, 0xd9, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 
+    0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 
+    0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 
+    0x68, 0x07, 0xca, 0xb8, 0x12, 0x52, 0xd9, 0xda, 0xb8, 0x02, 0x54, 0x00, 0x09, 0xb1, 0x00, 0x18, 
+    0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 
+    0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 
+    0xc2, 0x5a, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x52, 0x80, 0x02, 0xc2, 0x52, 0x12, 
+    0x42, 0xda, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x53, 0x2d, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 
+    0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0b, 0x01, 0x22, 0x20, 0x2b, 0x03, 0xd2, 0x0b, 
+    0x22, 0x75, 0x2f, 0xa3, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x83, 0x00, 0x80, 0x06, 0x20, 0x2b, 0x03, 
+    0xd2, 0x0b, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
+    0x12, 0x57, 0x35, 0x30, 0x33, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0b, 0x22, 0x30, 0xe6, 0x02, 0xd2, 
+    0x63, 0x7e, 0x37, 0x01, 0x7f, 0x7e, 0x27, 0x01, 0x9f, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 
+    0x05, 0x38, 0x7a, 0x05, 0x38, 0x7a, 0x37, 0x01, 0x7f, 0x7e, 0x37, 0x01, 0x5f, 0x7d, 0x43, 0x2d, 
+    0x42, 0xbe, 0x44, 0x19, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x5f, 0x75, 0x2f, 0x94, 0x12, 0x7e, 
+    0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x63, 0xc4, 0x22, 0xc2, 0x63, 
+    0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x7f, 0xbe, 0x24, 0x00, 0x00, 
+    0x68, 0x6a, 0xbe, 0x27, 0x01, 0x9f, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x9f, 0x7e, 0x37, 0x01, 0x7f, 
+    0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x38, 0x7a, 0x05, 0x38, 0x7a, 0x37, 0x01, 0x7f, 0x7e, 0x37, 
+    0x01, 0x5f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x19, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x5f, 
+    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 
+    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x19, 0xcd, 0x9d, 
+    0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x15, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5f, 
+    0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x54, 0xaa, 0x22, 0xd2, 0x0b, 0x7e, 0x04, 
+    0x15, 0xcd, 0x7a, 0x07, 0x01, 0x5f, 0x7a, 0x07, 0x01, 0x6f, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
+    0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 
+    0x27, 0x01, 0xaf, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 
+    0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x03, 
+    0x00, 0x2e, 0x27, 0x01, 0xaf, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 
+    0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 
+    0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 
+    0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x03, 0x00, 0x2e, 0x67, 0x01, 
+    0xaf, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 
+    0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 
+    0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 
+    0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x03, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 
+    0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 
+    0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 
+    0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 
+    0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 
+    0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 
+    0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 
+    0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 
+    0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 
+    0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x56, 0x0e, 0x75, 0x2f, 
+    0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 
+    0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0xda, 0xb8, 
+    0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x56, 0x0e, 0xda, 0xb8, 0x02, 0x57, 
+    0x35, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 
+    0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 
+    0x04, 0xd2, 0x5b, 0x80, 0x02, 0xc2, 0x5b, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x53, 
+    0x80, 0x02, 0xc2, 0x53, 0x12, 0x42, 0xf1, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 
+    0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 
+    0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 
+    0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 
+    0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x56, 0x62, 0x75, 0x2f, 
+    0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0c, 0x01, 0x22, 
+    0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x75, 0x2f, 0xa4, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x84, 0x00, 
+    0x80, 0x06, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 
+    0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5a, 0x6a, 0x30, 0x34, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0c, 
+    0x22, 0x30, 0xe6, 0x02, 0xd2, 0x64, 0x7e, 0x37, 0x01, 0x81, 0x7e, 0x27, 0x01, 0xa1, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3a, 0x7a, 0x05, 0x3a, 0x7a, 0x37, 0x01, 0x81, 0x7e, 0x37, 
+    0x01, 0x61, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x61, 
+    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 
+    0x64, 0xc4, 0x22, 0xc2, 0x64, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x81, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa1, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xa1, 0x7e, 0x37, 0x01, 0x81, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x3a, 0x7a, 0x05, 0x3a, 0x7a, 
+    0x37, 0x01, 0x81, 0x7e, 0x37, 0x01, 0x61, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xcc, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x61, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
+    0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 
+    0x9e, 0x44, 0x1d, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x19, 0xcd, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x61, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x57, 0xdf, 
+    0x22, 0xd2, 0x0c, 0x7e, 0x04, 0x19, 0xcd, 0x7a, 0x07, 0x01, 0x61, 0x7a, 0x07, 0x01, 0x71, 0x75, 
+    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 
+    0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb1, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 
+    0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xc9, 0x7e, 0x24, 0x04, 0x00, 0x2e, 0x27, 0x01, 0xb1, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 
+    0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x30, 0x3c, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x14, 0x22, 
+    0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 
+    0x04, 0x00, 0x2e, 0x67, 0x01, 0xb1, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 
+    0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x04, 0x7a, 0x69, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 
+    0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 
+    0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
+    0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
+    0x02, 0x59, 0x43, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0xb1, 0x00, 0x04, 0x30, 0x3c, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
+    0xd2, 0x14, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x59, 
+    0x43, 0xda, 0xb8, 0x02, 0x5a, 0x6a, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 
+    0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 
+    0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0xa5, 0xfd, 0x5e, 0x50, 
+    0x80, 0x68, 0x04, 0xd2, 0x54, 0x80, 0x02, 0xc2, 0x54, 0x12, 0x43, 0x08, 0x02, 0x65, 0x9c, 0x75, 
+    0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 
+    0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 
+    0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 
+    0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 
+    0x02, 0x59, 0x97, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 
+    0x22, 0x10, 0x0d, 0x01, 0x22, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 0x22, 0x75, 0x2f, 0xa5, 0x12, 0x7e, 
+    0x30, 0x7e, 0x14, 0x85, 0x00, 0x80, 0x06, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 0x22, 0x09, 0xb1, 0x00, 
+    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5d, 0x9f, 0x30, 0x35, 0x06, 
+    0x20, 0xe6, 0x4f, 0xd2, 0x0d, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x65, 0x7e, 0x37, 0x01, 0x83, 0x7e, 
+    0x27, 0x01, 0xa3, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3c, 0x7a, 0x05, 0x3c, 0x7a, 
+    0x37, 0x01, 0x83, 0x7e, 0x37, 0x01, 0x63, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x21, 0xcc, 0x38, 
+    0x68, 0x7a, 0x47, 0x01, 0x63, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
+    0x30, 0x12, 0x68, 0x34, 0x10, 0x65, 0xc4, 0x22, 0xc2, 0x65, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 
+    0x80, 0x1a, 0x7e, 0x27, 0x01, 0x83, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa3, 
+    0x28, 0x04, 0x7e, 0x27, 0x01, 0xa3, 0x7e, 0x37, 0x01, 0x83, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 
+    0x3c, 0x7a, 0x05, 0x3c, 0x7a, 0x37, 0x01, 0x83, 0x7e, 0x37, 0x01, 0x63, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x21, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x63, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
+    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 
+    0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x21, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 
+    0x1d, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x63, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 
+    0x78, 0x03, 0x02, 0x5b, 0x14, 0x22, 0xd2, 0x0d, 0x7e, 0x04, 0x1d, 0xcd, 0x7a, 0x07, 0x01, 0x63, 
+    0x7a, 0x07, 0x01, 0x73, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 
+    0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 
+    0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb3, 0x2e, 0x24, 0x00, 
+    0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 
+    0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 
+    0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x05, 0x00, 0x2e, 0x27, 0x01, 0xb3, 0x1b, 
+    0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 
+    0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 
+    0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 
+    0x00, 0x10, 0xd2, 0x15, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 
+    0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x05, 0x00, 0x2e, 0x67, 0x01, 0xb3, 0x9e, 0x24, 0x00, 0x02, 0x40, 
+    0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 
+    0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 
+    0x23, 0x44, 0x05, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 
+    0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 
+    0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 
+    0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 
+    0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 
+    0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 
+    0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 
+    0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 
+    0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5c, 0x78, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 
+    0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 
+    0x07, 0xca, 0xb8, 0x12, 0x5c, 0x78, 0xda, 0xb8, 0x02, 0x5d, 0x9f, 0x09, 0xb1, 0x00, 0x18, 0x7e, 
+    0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 
+    0x5d, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x55, 0x80, 0x02, 0xc2, 0x55, 0x12, 0x43, 
+    0x1f, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 
+    0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 
+    0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 
+    0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 
+    0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5c, 0xcc, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 
+    0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0e, 0x01, 0x22, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 
+    0x75, 0x2f, 0xa6, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x86, 0x00, 0x80, 0x06, 0x20, 0x2e, 0x03, 0xd2, 
+    0x0e, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 
+    0x60, 0xd4, 0x30, 0x36, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0e, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x66, 
+    0x7e, 0x37, 0x01, 0x85, 0x7e, 0x27, 0x01, 0xa5, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 
+    0x3e, 0x7a, 0x05, 0x3e, 0x7a, 0x37, 0x01, 0x85, 0x7e, 0x37, 0x01, 0x65, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x25, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x65, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
+    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x66, 0xc4, 0x22, 0xc2, 0x66, 0x2d, 
+    0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x85, 0xbe, 0x24, 0x00, 0x00, 0x68, 
+    0x6a, 0xbe, 0x27, 0x01, 0xa5, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa5, 0x7e, 0x37, 0x01, 0x85, 0x9d, 
+    0x32, 0x7d, 0x02, 0x2e, 0x05, 0x3e, 0x7a, 0x05, 0x3e, 0x7a, 0x37, 0x01, 0x85, 0x7e, 0x37, 0x01, 
+    0x65, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x65, 0x75, 
+    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 
+    0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x25, 0xcd, 0x9d, 0x24, 
+    0x12, 0x68, 0x34, 0x7e, 0x34, 0x21, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x65, 0x12, 
+    0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5e, 0x49, 0x22, 0xd2, 0x0e, 0x7e, 0x04, 0x21, 
+    0xcd, 0x7a, 0x07, 0x01, 0x65, 0x7a, 0x07, 0x01, 0x75, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 
+    0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 
+    0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 
+    0x01, 0xb5, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 
+    0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 
+    0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x06, 0x00, 
+    0x2e, 0x27, 0x01, 0xb5, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 
+    0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 
+    0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 
+    0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 
+    0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x06, 0x00, 0x2e, 0x67, 0x01, 0xb5, 
+    0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 
+    0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 
+    0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 
+    0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x06, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 
+    0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 
+    0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 
+    0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 
+    0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 
+    0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 
+    0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 
+    0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 
+    0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 
+    0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5f, 0xad, 0x75, 0x2f, 0x99, 
+    0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 
+    0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 0xda, 0xb8, 0x30, 
+    0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5f, 0xad, 0xda, 0xb8, 0x02, 0x60, 0xd4, 
+    0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 
+    0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 
+    0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x56, 0x80, 
+    0x02, 0xc2, 0x56, 0x12, 0x43, 0x36, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 
+    0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 
+    0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 
+    0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x60, 0x01, 0x75, 0x2f, 0x95, 
+    0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0f, 0x01, 0x22, 0x20, 
+    0x2f, 0x03, 0xd2, 0x0f, 0x22, 0x75, 0x2f, 0xa7, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x87, 0x00, 0x80, 
+    0x06, 0x20, 0x2f, 0x03, 0xd2, 0x0f, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 
+    0xda, 0xb8, 0x68, 0x03, 0x12, 0x64, 0x09, 0x30, 0x37, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0f, 0x22, 
+    0x30, 0xe6, 0x02, 0xd2, 0x67, 0x7e, 0x37, 0x01, 0x87, 0x7e, 0x27, 0x01, 0xa7, 0x9d, 0x32, 0x40, 
+    0x31, 0x7d, 0x02, 0x2e, 0x05, 0x40, 0x7a, 0x05, 0x40, 0x7a, 0x37, 0x01, 0x87, 0x7e, 0x37, 0x01, 
+    0x67, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x67, 0x75, 
+    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x67, 
+    0xc4, 0x22, 0xc2, 0x67, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x87, 
+    0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa7, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa7, 
+    0x7e, 0x37, 0x01, 0x87, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x40, 0x7a, 0x05, 0x40, 0x7a, 0x37, 
+    0x01, 0x87, 0x7e, 0x37, 0x01, 0x67, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xcc, 0x38, 0x13, 
+    0x7a, 0x47, 0x01, 0x67, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 
+    0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 
+    0x44, 0x29, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x25, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0x67, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x61, 0x7e, 0x22, 
+    0xd2, 0x0f, 0x7e, 0x04, 0x25, 0xcd, 0x7a, 0x07, 0x01, 0x67, 0x7a, 0x07, 0x01, 0x77, 0x75, 0x2f, 
+    0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 
+    0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 
+    0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb7, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 
+    0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 
+    0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 
+    0xc9, 0x7e, 0x24, 0x07, 0x00, 0x2e, 0x27, 0x01, 0xb7, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 
+    0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 
+    0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 
+    0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0x80, 
+    0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x07, 
+    0x00, 0x2e, 0x67, 0x01, 0xb7, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 
+    0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 
+    0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 
+    0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x07, 0x7a, 0x69, 0xb0, 
+    0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 
+    0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 
+    0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 
+    0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 
+    0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 
+    0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 
+    0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 
+    0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 
+    0x62, 0xe2, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 
+    0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 
+    0x17, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x62, 0xe2, 
+    0xda, 0xb8, 0x02, 0x64, 0x09, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 
+    0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 
+    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
+    0x68, 0x04, 0xd2, 0x57, 0x80, 0x02, 0xc2, 0x57, 0x12, 0x43, 0x4d, 0x02, 0x65, 0x9c, 0x75, 0x2f, 
+    0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 
+    0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 
+    0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 
+    0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 
+    0x63, 0x36, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 
+    0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 
+    0x20, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 
+    0xd2, 0x50, 0x80, 0x02, 0xc2, 0x50, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 
+    0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 
+    0xc2, 0x59, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x51, 0x80, 0x02, 0xc2, 0x51, 0x02, 
+    0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 
+    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
+    0x68, 0x04, 0xd2, 0x52, 0x80, 0x02, 0xc2, 0x52, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 
+    0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5b, 
+    0x80, 0x02, 0xc2, 0x5b, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x53, 0x80, 0x02, 0xc2, 
+    0x53, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x80, 0x68, 0x04, 0xd2, 0x54, 0x80, 0x02, 0xc2, 0x54, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 
+    0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 
+    0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x55, 0x80, 
+    0x02, 0xc2, 0x55, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 
+    0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0xa5, 
+    0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x56, 0x80, 0x02, 0xc2, 0x56, 0x02, 0x65, 0x88, 0x7c, 
+    0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 
+    0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 
+    0x57, 0x80, 0x02, 0xc2, 0x57, 0x02, 0x65, 0x88, 0x54, 0xf0, 0xc4, 0xa5, 0xff, 0xc4, 0xa5, 0x4f, 
+    0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0x22, 0xca, 0x19, 0x5e, 0x20, 
+    0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xcd, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 
+    0xb0, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x02, 0x7e, 0x64, 0x00, 0x02, 0x02, 0x65, 0xe7, 0xca, 
+    0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xcd, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 
+    0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0x7a, 0x79, 0x60, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x03, 
+    0x7e, 0x64, 0x00, 0x03, 0x02, 0x65, 0xe7, 0xd2, 0x04, 0x7e, 0x27, 0x01, 0xcb, 0x2d, 0x26, 0xbe, 
+    0x24, 0x04, 0x00, 0x38, 0x2e, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7e, 0x79, 0xa0, 
+    0x7a, 0x09, 0xa0, 0x0b, 0x04, 0x0b, 0x74, 0xbd, 0x04, 0x68, 0x23, 0xa5, 0xdb, 0xef, 0x7a, 0x27, 
+    0x01, 0xcb, 0x7e, 0x25, 0x30, 0x2d, 0x26, 0x7a, 0x25, 0x30, 0x7a, 0x07, 0x01, 0xc9, 0xda, 0x19, 
+    0xc2, 0xd7, 0x22, 0x75, 0x2f, 0x9a, 0x12, 0x7e, 0x30, 0xda, 0x19, 0xd2, 0xd7, 0x22, 0x7e, 0x04, 
+    0x01, 0xcd, 0x80, 0xd7, 0x4d, 0x42, 0x4a, 0xae, 0x4b, 0xa8, 0x4d, 0x7b, 0x49, 0x4f, 0x49, 0x4f, 
+    0x4c, 0xa7, 0x49, 0x4f, 0x4d, 0xbf, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x4d, 0xc6, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x50, 0x77, 0x4d, 0xe3, 0x4e, 0xdd, 0x50, 0xb0, 0x49, 0x4f, 0x49, 0x4f, 
+    0x4f, 0xdc, 0x49, 0x4f, 0x50, 0xf4, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x50, 0xfb, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x53, 0xac, 0x51, 0x18, 0x52, 0x12, 0x53, 0xe5, 0x49, 0x4f, 0x49, 0x4f, 
+    0x53, 0x11, 0x49, 0x4f, 0x54, 0x29, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x54, 0x30, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x56, 0xe1, 0x54, 0x4d, 0x55, 0x47, 0x57, 0x1a, 0x49, 0x4f, 0x49, 0x4f, 
+    0x56, 0x46, 0x49, 0x4f, 0x57, 0x5e, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x57, 0x65, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x5a, 0x16, 0x57, 0x82, 0x58, 0x7c, 0x5a, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x59, 0x7b, 0x49, 0x4f, 0x5a, 0x93, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x5a, 0x9a, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x5d, 0x4b, 0x5a, 0xb7, 0x5b, 0xb1, 0x5d, 0x84, 0x49, 0x4f, 0x49, 0x4f, 
+    0x5c, 0xb0, 0x49, 0x4f, 0x5d, 0xc8, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x5d, 0xcf, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x60, 0x80, 0x5d, 0xec, 0x5e, 0xe6, 0x60, 0xb9, 0x49, 0x4f, 0x49, 0x4f, 
+    0x5f, 0xe5, 0x49, 0x4f, 0x60, 0xfd, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x61, 0x04, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x63, 0xb5, 0x61, 0x21, 0x62, 0x1b, 0x63, 0xee, 0x49, 0x4f, 0x49, 0x4f, 
+    0x63, 0x1a, 0x49, 0x4f, 0x64, 0x32, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x64, 0x39, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
+    0x49, 0x4f, 0x49, 0x4f, 0xca, 0x29, 0x1e, 0x50, 0x40, 0x0d, 0x7e, 0x54, 0x0b, 0x10, 0x9c, 0xb5, 
+    0xa4, 0x2e, 0x54, 0x68, 0x51, 0x89, 0x54, 0x7e, 0x39, 0x00, 0x7a, 0x19, 0x00, 0x0b, 0x34, 0x80, 
+    0xe9, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 
+    0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 
+    0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 
+    0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 
+    0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 
+    0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 
+    0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 
+    0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 
+    0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 
+    0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 
+    0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 
+    0x35, 0xda, 0x29, 0x22, 0x1e, 0x50, 0x40, 0x0d, 0x7e, 0x54, 0x0b, 0x1c, 0x9c, 0xb5, 0xa4, 0x2e, 
+    0x54, 0x69, 0x1f, 0x89, 0x54, 0x7e, 0x19, 0x00, 0x7a, 0x39, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x7e, 
+    0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 
+    0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 
+    0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 
+    0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 
+    0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 
+    0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 
+    0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 
+    0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 
+    0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 
+    0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 
+    0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 
+    0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 
+    0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 
+    0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 
+    0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 
+    0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 
+    0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 
+    0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 
+    0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 
+    0x00, 0x0b, 0x35, 0x22, 0x6a, 0x9b, 0x6c, 0x4f, 0x6c, 0x67, 0x6c, 0x82, 0x6d, 0x1d, 0x6d, 0xb5, 
+    0x6d, 0xd0, 0x6e, 0x62, 0x6d, 0xeb, 0x6e, 0x2c, 0x7c, 0xb3, 0xbe, 0xb0, 0x09, 0x28, 0x14, 0x75, 
+    0x2f, 0x09, 0x12, 0x7e, 0x30, 0x75, 0x57, 0x10, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x43, 0xe1, 0xc0, 
+    0xd0, 0xf1, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0x23, 0x6c, 0xaa, 0x2e, 0x54, 0x6a, 0x54, 0x0b, 0x58, 
+    0x50, 0x89, 0x54, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x75, 0x2f, 0xb0, 0x12, 0x7e, 
+    0x30, 0x0a, 0x22, 0x09, 0xb2, 0x6a, 0x93, 0x42, 0x24, 0xd0, 0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 
+    0x3b, 0x49, 0x33, 0x6a, 0xb7, 0x89, 0x34, 0x6a, 0xc7, 0x6a, 0xf5, 0x6b, 0x23, 0x6b, 0x51, 0x6b, 
+    0x7f, 0x6b, 0xad, 0x6b, 0xdb, 0x6c, 0x09, 0x12, 0x41, 0xa9, 0xd2, 0x28, 0xd2, 0x08, 0xc2, 0x40, 
+    0xc2, 0x48, 0xc2, 0x38, 0xc2, 0x30, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xb9, 0x7e, 0x04, 0x00, 0x20, 
+    0x7a, 0x07, 0x01, 0x99, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xa9, 0x12, 0x41, 0x16, 0x12, 
+    0x64, 0x40, 0x02, 0x6c, 0x37, 0x12, 0x41, 0xc6, 0xd2, 0x29, 0xd2, 0x09, 0xc2, 0x41, 0xc2, 0x49, 
+    0xc2, 0x39, 0xc2, 0x31, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xba, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 
+    0x01, 0x9b, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xab, 0x12, 0x41, 0x16, 0x12, 0x64, 0x69, 
+    0x02, 0x6c, 0x37, 0x12, 0x41, 0xe3, 0xd2, 0x2a, 0xd2, 0x0a, 0xc2, 0x42, 0xc2, 0x4a, 0xc2, 0x3a, 
+    0xc2, 0x32, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbb, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0x9d, 
+    0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xad, 0x12, 0x41, 0x16, 0x12, 0x64, 0x92, 0x02, 0x6c, 
+    0x37, 0x12, 0x42, 0x00, 0xd2, 0x2b, 0xd2, 0x0b, 0xc2, 0x43, 0xc2, 0x4b, 0xc2, 0x3b, 0xc2, 0x33, 
+    0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbc, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0x9f, 0x7e, 0x04, 
+    0x00, 0x38, 0x7a, 0x07, 0x01, 0xaf, 0x12, 0x41, 0x16, 0x12, 0x64, 0xbb, 0x02, 0x6c, 0x37, 0x12, 
+    0x42, 0x1d, 0xd2, 0x2c, 0xd2, 0x0c, 0xc2, 0x44, 0xc2, 0x4c, 0xc2, 0x3c, 0xc2, 0x34, 0x6d, 0x00, 
+    0x7a, 0x03, 0x01, 0xbd, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa1, 0x7e, 0x04, 0x00, 0x38, 
+    0x7a, 0x07, 0x01, 0xb1, 0x12, 0x41, 0x16, 0x12, 0x64, 0xe4, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x3a, 
+    0xd2, 0x2d, 0xd2, 0x0d, 0xc2, 0x45, 0xc2, 0x4d, 0xc2, 0x3d, 0xc2, 0x35, 0x6d, 0x00, 0x7a, 0x03, 
+    0x01, 0xbe, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa3, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 
+    0x01, 0xb3, 0x12, 0x41, 0x16, 0x12, 0x65, 0x0d, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x57, 0xd2, 0x2e, 
+    0xd2, 0x0e, 0xc2, 0x46, 0xc2, 0x4e, 0xc2, 0x3e, 0xc2, 0x36, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbf, 
+    0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa5, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xb5, 
+    0x12, 0x41, 0x16, 0x12, 0x65, 0x36, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x74, 0xd2, 0x2f, 0xd2, 0x0f, 
+    0xc2, 0x47, 0xc2, 0x4f, 0xc2, 0x3f, 0xc2, 0x37, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xc0, 0x7e, 0x04, 
+    0x00, 0x20, 0x7a, 0x07, 0x01, 0xa7, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xb7, 0x12, 0x41, 
+    0x16, 0x12, 0x65, 0x5f, 0x02, 0x6c, 0x37, 0x7e, 0xa0, 0xd0, 0x7e, 0x60, 0x0f, 0x12, 0x65, 0xbf, 
+    0x40, 0x0c, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xc2, 0xd7, 0x22, 0x75, 
+    0x2f, 0xb1, 0x12, 0x7e, 0x30, 0x0a, 0x52, 0x23, 0x6d, 0x00, 0x59, 0x05, 0x00, 0x32, 0x12, 0x41, 
+    0x72, 0x12, 0x41, 0x8e, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb2, 0x12, 0x7e, 0x30, 0x0a, 0x22, 0x09, 
+    0xb2, 0x6a, 0x93, 0x42, 0x23, 0x7e, 0xb0, 0x9c, 0x19, 0xb2, 0x01, 0xb9, 0x12, 0x45, 0x74, 0xd0, 
+    0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 
+    0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 
+    0x12, 0x44, 0x40, 0xca, 0xb8, 0x09, 0xb0, 0x00, 0x10, 0x44, 0x02, 0x19, 0xb0, 0x00, 0x10, 0xda, 
+    0xb8, 0x80, 0x02, 0x54, 0xbf, 0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x08, 0x80, 0x02, 
+    0x54, 0xf7, 0x09, 0x30, 0x00, 0x0c, 0xca, 0xb8, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xda, 0xb8, 
+    0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 0x62, 0x09, 0xb6, 0x6a, 0x93, 0x3e, 0x20, 
+    0x0a, 0x62, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x20, 0x42, 0x27, 0xca, 0xb8, 0x74, 0x61, 0x19, 
+    0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x10, 0x59, 0x46, 0x01, 0xa9, 0x09, 0xb0, 0x00, 0x10, 0x44, 
+    0x01, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x11, 0xf4, 0x52, 0x27, 0x74, 0xa1, 0x19, 0xb0, 
+    0x00, 0x08, 0x7e, 0x44, 0x00, 0x38, 0x59, 0x46, 0x01, 0xa9, 0xd0, 0xa8, 0x22, 0x7c, 0x74, 0x7e, 
+    0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 
+    0xb0, 0x00, 0x08, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x04, 0x44, 0x80, 0x80, 0x02, 0x54, 0x7f, 
+    0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x02, 0x80, 0x02, 0x54, 0xfd, 0x19, 0xb0, 0x00, 
+    0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 0x62, 0x09, 0xb6, 0x6a, 0x93, 0xa5, 0xfd, 0xf4, 0xa5, 0xfe, 
+    0xca, 0x28, 0x3e, 0x20, 0x0a, 0x62, 0xda, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x10, 0xa5, 
+    0xed, 0x42, 0x28, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0x99, 0x80, 0x04, 0xa5, 
+    0xee, 0x52, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x04, 0x68, 0x10, 0xa5, 0xed, 0x42, 0x29, 0x42, 0x26, 
+    0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0x99, 0x80, 0x15, 0xa5, 0xee, 0x52, 0x29, 0x7c, 0x74, 
+    0x5e, 0x70, 0x02, 0x78, 0x0a, 0x52, 0x26, 0x7e, 0x44, 0x00, 0x20, 0x59, 0x46, 0x01, 0x99, 0x12, 
+    0x42, 0x91, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 
+    0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 0x00, 0x10, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 
+    0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 
+    0x19, 0x40, 0x00, 0x18, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb5, 0x12, 0x7e, 
+    0x30, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0xb0, 0x00, 0x0c, 0x44, 0x40, 0x19, 0xb0, 0x00, 
+    0x0c, 0xe5, 0x58, 0xb4, 0x07, 0x23, 0x09, 0xb0, 0x00, 0x10, 0x4e, 0xb0, 0x02, 0x19, 0xb0, 0x00, 
+    0x10, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x54, 
+    0xf7, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb6, 0x12, 
+    0x7e, 0x30, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0xe5, 0x58, 0xb4, 0x07, 0x18, 0x09, 0x30, 0x00, 
+    0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x44, 0x08, 0x19, 0xb0, 0x00, 
+    0x04, 0x19, 0x30, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x0c, 0x54, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xd0, 
+    0xa8, 0x22, 0x75, 0x2f, 0xb4, 0x12, 0x7e, 0x30, 0x7a, 0x21, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x41, 
+    0x2f, 0x12, 0x7e, 0x30, 0x7e, 0xb0, 0x01, 0x7e, 0xa0, 0xc8, 0x7c, 0x64, 0x12, 0x65, 0xbf, 0xc0, 
+    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xd0, 0xa8, 0x22, 0x6e, 0x9c, 0x6e, 0xe3, 
+    0x6f, 0x2a, 0x6f, 0x71, 0x6f, 0xb8, 0x6f, 0xff, 0x70, 0x46, 0x70, 0x8d, 0x75, 0x2f, 0x55, 0x12, 
+    0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 
+    0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x69, 0x7e, 0x27, 0x01, 0x79, 0x2d, 0x23, 0x7e, 0x09, 
+    0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x0d, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 
+    0x78, 0xec, 0x7a, 0x17, 0x01, 0x69, 0x7a, 0x27, 0x01, 0x79, 0x02, 0x4a, 0x98, 0x7e, 0x14, 0x09, 
+    0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x01, 0x12, 0x7e, 0x30, 0x7a, 
+    0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6b, 0x7e, 
+    0x27, 0x01, 0x7b, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 
+    0x14, 0x11, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x6b, 0x7a, 0x27, 0x01, 
+    0x7b, 0x02, 0x4d, 0xcd, 0x7e, 0x14, 0x0d, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 
+    0x75, 0x2f, 0x02, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 
+    0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6d, 0x7e, 0x27, 0x01, 0x7d, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 
+    0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x15, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 
+    0x7a, 0x17, 0x01, 0x6d, 0x7a, 0x27, 0x01, 0x7d, 0x02, 0x51, 0x02, 0x7e, 0x14, 0x11, 0xcd, 0x80, 
+    0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x03, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 
+    0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6f, 0x7e, 0x27, 0x01, 
+    0x7f, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x19, 
+    0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x6f, 0x7a, 0x27, 0x01, 0x7f, 0x02, 
+    0x54, 0x37, 0x7e, 0x14, 0x15, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 
+    0x04, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 
+    0x7e, 0x17, 0x01, 0x71, 0x7e, 0x27, 0x01, 0x81, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 
+    0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x1d, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 
+    0x01, 0x71, 0x7a, 0x27, 0x01, 0x81, 0x02, 0x57, 0x6c, 0x7e, 0x14, 0x19, 0xcd, 0x80, 0xeb, 0x75, 
+    0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x05, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 
+    0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x73, 0x7e, 0x27, 0x01, 0x83, 0x2d, 
+    0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x21, 0xcc, 0x38, 
+    0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x73, 0x7a, 0x27, 0x01, 0x83, 0x02, 0x5a, 0xa1, 
+    0x7e, 0x14, 0x1d, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x06, 0x12, 
+    0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 
+    0x01, 0x75, 0x7e, 0x27, 0x01, 0x85, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 
+    0x0b, 0x14, 0xbe, 0x14, 0x25, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x75, 
+    0x7a, 0x27, 0x01, 0x85, 0x02, 0x5d, 0xd6, 0x7e, 0x14, 0x21, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 
+    0x12, 0x7e, 0x30, 0x75, 0x2f, 0x07, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 
+    0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x77, 0x7e, 0x27, 0x01, 0x87, 0x2d, 0x23, 0x7e, 
+    0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x29, 0xcc, 0x38, 0x0f, 0x1b, 
+    0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x77, 0x7a, 0x27, 0x01, 0x87, 0x02, 0x61, 0x0b, 0x7e, 0x14, 
+    0x25, 0xcd, 0x80, 0xeb, 0xca, 0xb8, 0xc0, 0xf1, 0x75, 0x2f, 0x02, 0x12, 0x7e, 0x30, 0xe5, 0xc0, 
+    0x54, 0x03, 0x68, 0x05, 0x12, 0x77, 0xdd, 0x80, 0xf5, 0x30, 0xc2, 0x08, 0x75, 0xf1, 0x01, 0x12, 
+    0x71, 0xe9, 0x80, 0x14, 0x30, 0xc3, 0x08, 0x75, 0xf1, 0x01, 0x12, 0x71, 0x0d, 0x80, 0x09, 0x30, 
+    0xc4, 0x06, 0x75, 0xf1, 0x02, 0x12, 0x72, 0xf9, 0xd0, 0xf1, 0xda, 0xb8, 0x32, 0x75, 0x2f, 0x10, 
+    0x12, 0x7e, 0x30, 0xca, 0x0b, 0xca, 0x39, 0xca, 0x59, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x5c, 0xe5, 
+    0xe5, 0x54, 0xc0, 0x68, 0x4f, 0xe5, 0xe6, 0x6c, 0xaa, 0x7e, 0x37, 0x01, 0xc5, 0x2d, 0x35, 0xbe, 
+    0x34, 0x04, 0x00, 0x38, 0x4a, 0x7a, 0x37, 0x01, 0xc5, 0x7e, 0x37, 0x01, 0xc3, 0x7d, 0x43, 0x2d, 
+    0x45, 0xbe, 0x44, 0x09, 0xcc, 0x38, 0x40, 0x7a, 0x47, 0x01, 0xc3, 0x75, 0x2f, 0x11, 0x12, 0x7e, 
+    0x30, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x73, 0xc8, 0xa9, 0x21, 0xe5, 0x1f, 0xa9, 0xd4, 
+    0xe4, 0xa9, 0x24, 0xe4, 0xfc, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x3b, 0xe5, 0xe5, 0x54, 0xc0, 0x78, 
+    0xb4, 0x12, 0x76, 0x6a, 0xda, 0x59, 0xda, 0x39, 0xda, 0x0b, 0x22, 0x80, 0x29, 0x80, 0x58, 0x75, 
+    0x2f, 0x16, 0x12, 0x7e, 0x30, 0x80, 0xed, 0x75, 0x2f, 0x12, 0x12, 0x7e, 0x30, 0x7a, 0xb1, 0x2f, 
+    0x12, 0x7e, 0x30, 0x9e, 0x44, 0x09, 0xcd, 0x9d, 0x54, 0x12, 0x73, 0xc8, 0x7e, 0x34, 0x05, 0xcd, 
+    0x7d, 0x54, 0x2d, 0x43, 0x80, 0xa1, 0xe5, 0xe5, 0x54, 0x03, 0x78, 0x12, 0x75, 0x2f, 0x13, 0x12, 
+    0x7e, 0x30, 0x7e, 0x0f, 0x29, 0xe9, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xe9, 0x80, 0xa7, 0x75, 0x2f, 
+    0x14, 0x12, 0x7e, 0x30, 0x7e, 0x0f, 0x29, 0xed, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xed, 0xa9, 0xd7, 
+    0xe4, 0xa9, 0x27, 0xe4, 0xfc, 0x80, 0x9d, 0x75, 0x2f, 0x15, 0x12, 0x7e, 0x30, 0x7e, 0x0f, 0x29, 
+    0xf1, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf1, 0x80, 0xe5, 0x75, 0x2f, 0x18, 0x12, 0x7e, 0x30, 0xca, 
+    0x09, 0xca, 0x39, 0xca, 0x2b, 0xc2, 0xc2, 0xa9, 0x21, 0xf2, 0x52, 0xe5, 0xf5, 0x33, 0x82, 0xe7, 
+    0x40, 0x44, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x54, 0x00, 0x40, 0x9d, 0x35, 0x40, 0x43, 0x7a, 0x37, 
+    0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc7, 0x7d, 0x43, 0x2d, 0x45, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x52, 
+    0x7a, 0x47, 0x01, 0xc7, 0x7d, 0x45, 0x12, 0x75, 0x26, 0xa9, 0x20, 0xf5, 0x22, 0x75, 0x2f, 0x19, 
+    0x12, 0x7e, 0x30, 0x7a, 0x91, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x81, 0xf7, 0x7a, 0x91, 0xf6, 0xe5, 
+    0xf5, 0x33, 0x82, 0xe7, 0x50, 0xbc, 0xda, 0x2b, 0xda, 0x39, 0xda, 0x09, 0x22, 0x80, 0x41, 0x80, 
+    0x64, 0x2d, 0x53, 0x6d, 0x33, 0x70, 0xb7, 0x7e, 0x04, 0x01, 0xcd, 0x7a, 0x07, 0x01, 0xc9, 0x7a, 
+    0x07, 0x01, 0xc7, 0xa9, 0x32, 0xf2, 0xdf, 0x85, 0x30, 0x2f, 0x12, 0x7e, 0x30, 0x75, 0xf6, 0x00, 
+    0x80, 0xd4, 0xca, 0x59, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x54, 0x12, 0x75, 0x26, 0x7e, 0x34, 0x01, 
+    0xcd, 0x7d, 0x54, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc7, 0x12, 0x75, 0x26, 0xda, 0x49, 0x80, 0x99, 
+    0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x0f, 0x29, 0xd9, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xd9, 
+    0x80, 0x9d, 0x7e, 0x0f, 0x29, 0xe1, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xe1, 0xa9, 0xd7, 0xf4, 0xa9, 
+    0x27, 0xf4, 0xfc, 0x80, 0x8a, 0x7e, 0x0f, 0x29, 0xdd, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xdd, 0x80, 
+    0xeb, 0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x2f, 0x29, 0xf9, 0x0b, 0x2c, 0x7a, 0x2f, 0x29, 
+    0xf9, 0x80, 0x34, 0x7e, 0x2f, 0x2a, 0x01, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x01, 0xa9, 0xd7, 0xf4, 
+    0xa9, 0x27, 0xf4, 0xfc, 0x80, 0x21, 0x7e, 0x2f, 0x29, 0xfd, 0x0b, 0x2c, 0x7a, 0x2f, 0x29, 0xfd, 
+    0x80, 0xeb, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x75, 0x2f, 0x28, 0x12, 0x7e, 0x30, 0xca, 
+    0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xc2, 0xc4, 0xa9, 0x21, 0xf2, 0xb6, 0xe5, 0xf5, 0x33, 0x72, 0xe7, 
+    0x40, 0xe0, 0x7e, 0x0d, 0x30, 0x7e, 0x1d, 0x34, 0x7e, 0x2d, 0x38, 0x7e, 0x3d, 0x3c, 0x7e, 0x85, 
+    0x40, 0x7d, 0x90, 0x4d, 0x91, 0x4d, 0x92, 0x4d, 0x93, 0x4d, 0x94, 0x4d, 0x95, 0x4d, 0x96, 0x4d, 
+    0x97, 0x4d, 0x98, 0x68, 0x72, 0x7a, 0x11, 0xf3, 0x7a, 0x01, 0xf3, 0x7a, 0x31, 0xf3, 0x7a, 0x21, 
+    0xf3, 0x7a, 0x51, 0xf3, 0x7a, 0x41, 0xf3, 0x7a, 0x71, 0xf3, 0x7a, 0x61, 0xf3, 0x7a, 0x91, 0xf3, 
+    0x7a, 0x81, 0xf3, 0x30, 0x73, 0x1a, 0x7a, 0xb1, 0xf3, 0x7a, 0xa1, 0xf3, 0x7a, 0xd1, 0xf3, 0x7a, 
+    0xc1, 0xf3, 0x7a, 0xf1, 0xf3, 0x7a, 0xe1, 0xf3, 0x7d, 0x78, 0x7a, 0xf1, 0xf3, 0x7a, 0xe1, 0xf3, 
+    0xa9, 0x30, 0xf5, 0x03, 0x02, 0x72, 0xe6, 0x75, 0x2f, 0x29, 0x12, 0x7e, 0x30, 0x20, 0x73, 0x0b, 
+    0x75, 0x2f, 0x0a, 0x12, 0x7e, 0x30, 0x75, 0xf6, 0x0a, 0x80, 0x09, 0x75, 0x2f, 0x12, 0x12, 0x7e, 
+    0x30, 0x75, 0xf6, 0x12, 0x6d, 0x00, 0x7d, 0x10, 0x7a, 0x0d, 0x30, 0x7a, 0x0d, 0x34, 0x7a, 0x0d, 
+    0x38, 0x7a, 0x0d, 0x3c, 0x7a, 0x05, 0x40, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x1e, 0xb0, 
+    0x40, 0x0c, 0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x75, 0x0b, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0xa1, 
+    0xe3, 0x7a, 0x39, 0xa0, 0x0b, 0x34, 0x80, 0xea, 0xb4, 0x40, 0xe3, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 
+    0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 
+    0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 
+    0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 
+    0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 
+    0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 
+    0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 
+    0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 
+    0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 
+    0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 
+    0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 
+    0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 
+    0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 
+    0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 
+    0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 
+    0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 
+    0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 
+    0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 
+    0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 
+    0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 
+    0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x22, 0x1e, 0xb0, 0x40, 0x0c, 
+    0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x76, 0x69, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0x39, 0xa0, 0x7a, 
+    0xa1, 0xf3, 0x0b, 0x34, 0x80, 0xea, 0xb4, 0x40, 0xe3, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 
+    0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 
+    0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 
+    0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 
+    0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 
+    0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 
+    0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 
+    0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 
+    0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 
+    0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 
+    0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 
+    0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 
+    0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 
+    0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 
+    0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 
+    0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 
+    0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 
+    0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 
+    0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 
+    0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 
+    0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x22, 0xc2, 0xaf, 0x7e, 0x37, 0x01, 0xc5, 
+    0x4d, 0x33, 0x68, 0x3b, 0x7e, 0x07, 0x01, 0xc1, 0x7e, 0x54, 0x09, 0xcd, 0x9d, 0x50, 0xbd, 0x35, 
+    0x40, 0x02, 0x7d, 0x35, 0xca, 0x39, 0x7e, 0x65, 0x4b, 0x99, 0x64, 0xda, 0x39, 0x7e, 0x07, 0x01, 
+    0xc5, 0x9d, 0x03, 0x7a, 0x07, 0x01, 0xc5, 0x2e, 0x37, 0x01, 0xc1, 0x7a, 0x37, 0x01, 0xc1, 0xbe, 
+    0x34, 0x09, 0xcc, 0x28, 0xc7, 0x7e, 0x34, 0x05, 0xcd, 0x7a, 0x37, 0x01, 0xc1, 0x80, 0xbd, 0xd2, 
+    0xaf, 0x22, 0x75, 0x2f, 0x53, 0x12, 0x7e, 0x30, 0x7e, 0x15, 0x4d, 0x80, 0x11, 0x75, 0x2f, 0x51, 
+    0x12, 0x7e, 0x30, 0x0b, 0x08, 0x10, 0x0b, 0x05, 0x9e, 0x34, 0x00, 0x02, 0x28, 0x4d, 0x7c, 0xb2, 
+    0x20, 0xe7, 0x27, 0x54, 0x07, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x6e, 0x8c, 0x7c, 0xb2, 0x54, 0x78, 
+    0x03, 0x03, 0x03, 0x7c, 0x2b, 0x9d, 0x13, 0x40, 0x1a, 0x68, 0x12, 0x7a, 0x15, 0x4d, 0x7a, 0x25, 
+    0x4f, 0x7e, 0x64, 0x77, 0x47, 0x7a, 0x65, 0x4b, 0x89, 0x24, 0x02, 0x77, 0x55, 0x7e, 0x64, 0x76, 
+    0xbd, 0x80, 0xf2, 0x2d, 0x13, 0x9d, 0x31, 0xca, 0x39, 0x7d, 0x31, 0x2d, 0x10, 0xca, 0x19, 0xca, 
+    0x29, 0x99, 0x24, 0xda, 0x29, 0xda, 0x09, 0xda, 0x39, 0x80, 0xa2, 0x7a, 0x15, 0x4d, 0x7e, 0x64, 
+    0x77, 0x33, 0x4d, 0x33, 0x78, 0x09, 0x7c, 0xb2, 0x20, 0xe7, 0x2a, 0x7e, 0x64, 0x76, 0xb2, 0x7a, 
+    0x65, 0x4b, 0x22, 0x75, 0x2f, 0x52, 0x12, 0x7e, 0x30, 0x7e, 0x21, 0x4d, 0x7e, 0x09, 0x30, 0x0b, 
+    0x04, 0x1b, 0x34, 0x78, 0x89, 0x80, 0xd4, 0x75, 0x2f, 0x54, 0x12, 0x7e, 0x30, 0x7e, 0x15, 0x4d, 
+    0x7e, 0x25, 0x4f, 0x80, 0x90, 0x5e, 0x20, 0x07, 0x54, 0x78, 0x7e, 0x44, 0x77, 0xd1, 0x30, 0xe6, 
+    0x16, 0x4d, 0x33, 0x68, 0x26, 0x1b, 0x34, 0x7e, 0x09, 0x40, 0x0b, 0x04, 0x7e, 0x44, 0x6a, 0x68, 
+    0x20, 0xe3, 0x04, 0x7e, 0x44, 0x77, 0xd9, 0xca, 0x09, 0xca, 0x39, 0x99, 0x44, 0xda, 0x39, 0xda, 
+    0x09, 0x7e, 0x64, 0x76, 0xbd, 0x4d, 0x33, 0x68, 0xa6, 0x89, 0x64, 0x7a, 0x15, 0x4d, 0xf5, 0x4f, 
+    0x7e, 0x64, 0x77, 0x96, 0x80, 0x99, 0x7e, 0x15, 0x4d, 0xe5, 0x4f, 0x80, 0xc4, 0xc0, 0xd0, 0xc0, 
+    0xd1, 0xc0, 0xe0, 0xca, 0x19, 0xa9, 0x20, 0xdf, 0x12, 0xa9, 0x21, 0xdf, 0x1b, 0x75, 0x2f, 0x01, 
+    0x12, 0x7e, 0x30, 0x53, 0xdf, 0xf7, 0x12, 0x40, 0xdc, 0x80, 0x0d, 0x75, 0x2f, 0xfe, 0x12, 0x7e, 
+    0x30, 0x7e, 0x14, 0x00, 0x53, 0x02, 0x40, 0x51, 0xda, 0x19, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 
+    0x32, 0x03, 0xa5, 0xcb, 0x19, 0xb1, 0x80, 0x00, 0x22, 0x22, 0x02, 0x78, 0x52, 0xca, 0x0b, 0xca, 
+    0x1b, 0xca, 0x2b, 0xca, 0x3b, 0xca, 0x4b, 0xca, 0x5b, 0xca, 0x6b, 0xca, 0x7b, 0xca, 0xeb, 0xc0, 
+    0xf1, 0x7e, 0xb3, 0x2a, 0x1d, 0xb4, 0x00, 0x02, 0x80, 0x19, 0xb4, 0x01, 0x16, 0x30, 0xc0, 0x08, 
+    0x75, 0xf1, 0x00, 0x12, 0x78, 0x3c, 0x80, 0x1f, 0x30, 0xc1, 0x1c, 0x75, 0xf1, 0x00, 0x12, 0x78, 
+    0xcd, 0x80, 0x14, 0x30, 0xc1, 0x08, 0x75, 0xf1, 0x00, 0x12, 0x78, 0xcd, 0x80, 0x09, 0x30, 0xc0, 
+    0x06, 0x75, 0xf1, 0x00, 0x12, 0x78, 0x3c, 0xd0, 0xf1, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 0xda, 
+    0x5b, 0xda, 0x4b, 0xda, 0x3b, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0xc2, 0xc0, 0x7e, 0xb3, 
+    0x2a, 0x1d, 0xb4, 0x02, 0x07, 0x12, 0x78, 0x5e, 0x02, 0x78, 0x52, 0x22, 0xb4, 0x01, 0xfc, 0x02, 
+    0x78, 0x98, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x2a, 0x1d, 0x7a, 0x03, 0x2a, 0x1e, 0x22, 0x7e, 0xb3, 
+    0x2a, 0x15, 0x54, 0x60, 0x60, 0x05, 0xb4, 0x40, 0x15, 0x80, 0x13, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 
+    0x05, 0x0c, 0x75, 0x2f, 0x71, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xf5, 0x8f, 0x22, 0x75, 
+    0xf6, 0x00, 0x22, 0xbe, 0x57, 0x2a, 0x1b, 0x28, 0x04, 0x7e, 0x57, 0x2a, 0x1b, 0x7a, 0x0f, 0x2a, 
+    0x20, 0x7a, 0x57, 0x2a, 0x24, 0x02, 0x78, 0x98, 0x7e, 0xef, 0x2a, 0x20, 0x7e, 0xf7, 0x2a, 0x24, 
+    0x7e, 0x07, 0x2a, 0x24, 0x4d, 0x00, 0x68, 0x21, 0x7e, 0x00, 0x00, 0x7e, 0xeb, 0xb0, 0xf5, 0xf3, 
+    0xa3, 0xa5, 0x08, 0x1b, 0xf4, 0x68, 0x04, 0xa5, 0xb8, 0x08, 0xf0, 0x7a, 0xef, 0x2a, 0x20, 0x7a, 
+    0xf7, 0x2a, 0x24, 0x75, 0x2f, 0x06, 0x12, 0x7e, 0x30, 0x7a, 0x01, 0xf6, 0x22, 0xc2, 0xc1, 0x75, 
+    0x2f, 0x03, 0x12, 0x7e, 0x30, 0xa9, 0x36, 0xe2, 0x16, 0xe5, 0xf5, 0x54, 0xc0, 0x68, 0x07, 0xa9, 
+    0xd7, 0xf4, 0xa9, 0x27, 0xf4, 0xfc, 0x53, 0xe1, 0x3f, 0x43, 0xf2, 0x88, 0x02, 0x79, 0x44, 0x7e, 
+    0xb3, 0x2a, 0x1e, 0xb4, 0x02, 0x0f, 0xa9, 0xd4, 0xe4, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x2a, 0x1e, 
+    0x7a, 0xb3, 0x2a, 0x1d, 0x22, 0xb4, 0x01, 0x39, 0x7e, 0x21, 0xe6, 0x7c, 0x32, 0x7e, 0x13, 0x2a, 
+    0x1f, 0x2c, 0x21, 0x7a, 0x23, 0x2a, 0x1f, 0x7e, 0x00, 0x00, 0x2e, 0x04, 0x2a, 0x26, 0xe5, 0xe3, 
+    0x7a, 0x09, 0xb0, 0x0b, 0x04, 0xa5, 0xdb, 0xf6, 0xa9, 0xd4, 0xe4, 0x75, 0x2f, 0x70, 0x12, 0x7e, 
+    0x30, 0x7e, 0xb3, 0x2a, 0x1f, 0x7e, 0xa3, 0x2a, 0x1c, 0xbc, 0xab, 0x78, 0x03, 0x12, 0x79, 0xdb, 
+    0x22, 0x02, 0x7d, 0x44, 0xe5, 0xe6, 0xb4, 0x08, 0x65, 0xa9, 0xc4, 0xe2, 0x7e, 0x01, 0xe3, 0x7e, 
+    0x11, 0xe3, 0x7e, 0x31, 0xe3, 0x7e, 0x21, 0xe3, 0x7e, 0x51, 0xe3, 0x7e, 0x41, 0xe3, 0x7e, 0x71, 
+    0xe3, 0x7e, 0x61, 0xe3, 0x7a, 0x0f, 0x2a, 0x15, 0x7a, 0x1f, 0x2a, 0x19, 0x75, 0x2f, 0x04, 0x12, 
+    0x7e, 0x30, 0x7a, 0x01, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x21, 
+    0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x31, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x41, 0x2f, 0x12, 0x7e, 0x30, 
+    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 
+    0x7e, 0x30, 0xa9, 0xd4, 0xe4, 0xa9, 0xd7, 0xf4, 0xa9, 0xc6, 0xe2, 0x12, 0x79, 0xaf, 0x22, 0x6d, 
+    0x00, 0x7e, 0x14, 0x01, 0x02, 0x7a, 0x07, 0x2a, 0x24, 0x7a, 0x03, 0x2a, 0x1f, 0x7e, 0xb3, 0x2a, 
+    0x15, 0x20, 0xe7, 0x0f, 0x7a, 0x23, 0x2a, 0x1e, 0x7a, 0x33, 0x2a, 0x1d, 0xbe, 0x07, 0x2a, 0x1b, 
+    0x68, 0x09, 0x22, 0x7a, 0x33, 0x2a, 0x1e, 0x7a, 0x23, 0x2a, 0x1d, 0x7e, 0xb3, 0x2a, 0x15, 0x54, 
+    0xe3, 0x23, 0x23, 0x30, 0xe0, 0x02, 0xd2, 0xe5, 0x30, 0xe7, 0x02, 0xd2, 0xe4, 0x30, 0xe5, 0x06, 
+    0x30, 0xe4, 0x03, 0x02, 0x7d, 0x44, 0x54, 0x3e, 0xf5, 0xf0, 0x03, 0x54, 0x1f, 0xc3, 0x25, 0xf0, 
+    0x90, 0x7a, 0x07, 0x75, 0x84, 0xff, 0x73, 0x02, 0x7b, 0x5b, 0x02, 0x7a, 0x4f, 0x02, 0x7b, 0xf8, 
+    0x02, 0x7c, 0x13, 0x02, 0x7a, 0xf4, 0x02, 0x7a, 0xb5, 0x02, 0x7c, 0x2c, 0x02, 0x7c, 0x2c, 0x02, 
+    0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 
+    0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x35, 0x02, 0x7c, 0xe9, 0x02, 0x7c, 0x32, 
+    0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x7e, 
+    0xb3, 0x2a, 0x16, 0xb4, 0x06, 0x2a, 0x7e, 0xb3, 0x2a, 0x17, 0x60, 0x56, 0x7c, 0x0b, 0x7e, 0x13, 
+    0x2a, 0x18, 0x7e, 0x17, 0x2a, 0x19, 0x75, 0x2f, 0x72, 0x12, 0x7e, 0x30, 0x7a, 0x01, 0x2f, 0x12, 
+    0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x7d, 0x4e, 0x40, 0x35, 0x02, 0x78, 0x83, 
+    0xb4, 0x08, 0x10, 0x75, 0x2f, 0x74, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x3f, 0xf1, 0xf5, 0xf3, 0x75, 
+    0xf6, 0x01, 0x22, 0xb4, 0x00, 0x1c, 0x75, 0x2f, 0x75, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x3f, 0xf2, 
+    0x30, 0xe0, 0x05, 0x75, 0xf3, 0x02, 0x80, 0x03, 0x75, 0xf3, 0x00, 0x75, 0xf3, 0x00, 0x75, 0xf6, 
+    0x02, 0x22, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x00, 0x35, 0x75, 0x2f, 0x76, 0x12, 
+    0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0xf5, 0xf1, 0x7e, 0xb3, 0x2a, 0x1a, 0x20, 0xe7, 
+    0x09, 0xe5, 0xe1, 0x30, 0xe7, 0x0d, 0x74, 0x01, 0x80, 0x0b, 0xe5, 0xe1, 0x30, 0xe6, 0x04, 0x74, 
+    0x01, 0x80, 0x02, 0x74, 0x00, 0x53, 0xf1, 0x80, 0xf5, 0xf3, 0x75, 0xf3, 0x00, 0x75, 0xf6, 0x02, 
+    0x22, 0x02, 0x7d, 0x44, 0xc0, 0xf1, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0x42, 0xf1, 0x7e, 0xb3, 
+    0x2a, 0x18, 0xb4, 0x00, 0x45, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x01, 0x24, 0x75, 0x2f, 0x77, 0x12, 
+    0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0x78, 0x05, 0x53, 0xe1, 0x3f, 0x80, 0x37, 0x7e, 
+    0xb3, 0x2a, 0x1a, 0x20, 0xe7, 0x05, 0x53, 0xe1, 0x7f, 0x80, 0x2b, 0x53, 0xe1, 0xbf, 0x80, 0x26, 
+    0xb4, 0x03, 0x17, 0x75, 0x2f, 0x78, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x20, 0xe7, 0x05, 
+    0x43, 0xe1, 0x80, 0x80, 0x11, 0x43, 0xe1, 0x40, 0x80, 0x0c, 0x43, 0xe1, 0xc0, 0xd0, 0xf1, 0x75, 
+    0x2f, 0x07, 0x12, 0x7e, 0x30, 0x22, 0xd0, 0xf1, 0x02, 0x78, 0x7f, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 
+    0x09, 0x23, 0x75, 0x2f, 0x79, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xbe, 0xb3, 0x3f, 0xf1, 
+    0x68, 0x11, 0xca, 0xb8, 0xc0, 0xf1, 0x12, 0x43, 0x68, 0xd0, 0xf1, 0xda, 0xb8, 0x50, 0x76, 0x7a, 
+    0xb3, 0x3f, 0xf1, 0x80, 0x6d, 0xb4, 0x05, 0x08, 0x75, 0x2f, 0x7a, 0x12, 0x7e, 0x30, 0x80, 0x62, 
+    0xb4, 0x03, 0x19, 0x75, 0x2f, 0x7b, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xb4, 0x01, 0x55, 
+    0x7e, 0xb3, 0x3f, 0xf2, 0x44, 0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x46, 0xb4, 0x01, 0x19, 0x75, 
+    0x2f, 0x7c, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xb4, 0x01, 0x39, 0x7e, 0xb3, 0x3f, 0xf2, 
+    0x54, 0xfe, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x2a, 0xb4, 0x07, 0x2a, 0x7e, 0xb3, 0x2a, 0x17, 0x60, 
+    0x24, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x18, 0x7e, 0x17, 0x2a, 0x19, 0x75, 0x2f, 0x73, 0x12, 0x7e, 
+    0x30, 0x7a, 0x01, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x7d, 0x7a, 
+    0x40, 0x03, 0x02, 0x78, 0x7f, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x0b, 0xf6, 0x75, 
+    0x2f, 0x7d, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0x7e, 0xa3, 0x2a, 0x1a, 0x4c, 0xab, 0x78, 
+    0xe4, 0x80, 0xdf, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x0a, 0xdb, 0x75, 0x2f, 0x7e, 0x12, 0x7e, 0x30, 
+    0x7e, 0xb3, 0x2a, 0x18, 0x70, 0xcf, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 0x22, 0x02, 0x7d, 0x44, 0x02, 
+    0x7d, 0x44, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x04, 0x20, 0x75, 0x2f, 0xc3, 0x12, 
+    0x7e, 0x30, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x17, 0x7e, 0x18, 0x2a, 0x26, 0x7a, 0x1c, 
+    0x00, 0x00, 0x7e, 0x47, 0x2a, 0x1b, 0x12, 0x7e, 0x3c, 0x02, 0x7c, 0xe3, 0xb4, 0x06, 0x3a, 0x75, 
+    0x2f, 0xc1, 0x12, 0x7e, 0x30, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7d, 0xca, 0x7e, 
+    0xd7, 0x2a, 0x17, 0x7e, 0x78, 0x2a, 0x26, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x2a, 0x1b, 0x75, 
+    0x2f, 0xc1, 0x12, 0x7e, 0x30, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7e, 
+    0x75, 0xd0, 0x87, 0xd0, 0xa8, 0x40, 0x4f, 0x80, 0x4a, 0xb4, 0x00, 0x1c, 0xc2, 0xaf, 0xa9, 0xd5, 
+    0x87, 0x12, 0x78, 0x7f, 0xe4, 0x8d, 0xef, 0x8d, 0xef, 0x8d, 0xef, 0xd5, 0xe0, 0xf7, 0xc0, 0xd1, 
+    0xca, 0x02, 0xff, 0xca, 0x06, 0x00, 0x00, 0x32, 0xb4, 0x09, 0x12, 0x7e, 0x57, 0x2a, 0x17, 0x4d, 
+    0x55, 0x68, 0x05, 0xa9, 0xd2, 0xb1, 0x80, 0x03, 0xa9, 0xc2, 0xb1, 0x80, 0x16, 0xb4, 0x07, 0x16, 
+    0xc2, 0xaf, 0x7e, 0x07, 0x2a, 0x19, 0x7e, 0x17, 0x2a, 0x17, 0xc0, 0xd1, 0xca, 0x18, 0xca, 0x38, 
+    0xca, 0x28, 0x32, 0x02, 0x78, 0x7f, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x03, 0x15, 
+    0x75, 0x2f, 0xc2, 0x12, 0x7e, 0x30, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x17, 0x7e, 0x57, 
+    0x2a, 0x1b, 0x02, 0x78, 0x83, 0xb4, 0x05, 0x39, 0x75, 0x2f, 0xc0, 0x12, 0x7e, 0x30, 0xc0, 0xa8, 
+    0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x7e, 0x08, 0x2a, 0x26, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 
+    0x24, 0x00, 0xfe, 0x7e, 0x37, 0x2a, 0x17, 0x7e, 0x47, 0x2a, 0x1b, 0x12, 0x7e, 0x3c, 0xd0, 0x87, 
+    0xd0, 0xa8, 0x7e, 0x08, 0x2a, 0x26, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x57, 0x2a, 0x1b, 0x02, 0x78, 
+    0x83, 0x02, 0x7d, 0x44, 0x75, 0x2f, 0x07, 0x12, 0x7e, 0x30, 0x43, 0xe1, 0xc0, 0x22, 0xc0, 0xa8, 
+    0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7d, 0xb9, 0x40, 0x19, 0x7e, 0x08, 0x2a, 0x26, 
+    0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0xca, 0x49, 0x12, 0x7e, 0x3c, 0xda, 0x59, 0xda, 0x0b, 0xd0, 
+    0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0x22, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 
+    0xa9, 0xd5, 0x87, 0x12, 0x7d, 0xb9, 0x40, 0x2b, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 
+    0x7f, 0x61, 0x7e, 0x78, 0x2a, 0x26, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x2a, 0x1b, 0xbd, 0x74, 
+    0x78, 0x11, 0x75, 0x2f, 0xc1, 0x12, 0x7e, 0x30, 0x12, 0x7e, 0x75, 0x40, 0x06, 0xd0, 0x87, 0xd0, 
+    0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0xd3, 0x22, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x34, 0x7f, 
+    0xca, 0x0b, 0x1a, 0x50, 0xc5, 0xf0, 0x7d, 0x62, 0x7d, 0x75, 0x7d, 0x87, 0x7e, 0x34, 0x7f, 0xc2, 
+    0x7e, 0x1b, 0xb0, 0x7e, 0x34, 0x7f, 0x03, 0xb4, 0x01, 0x04, 0x7e, 0x34, 0x7f, 0xcc, 0x7e, 0x1b, 
+    0xb0, 0xbc, 0x0b, 0x50, 0x49, 0x3e, 0x00, 0x3e, 0x00, 0x0a, 0x50, 0x2d, 0x75, 0x0b, 0x3a, 0x30, 
+    0x69, 0x53, 0x00, 0x02, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbc, 0x1b, 0x50, 0x30, 0x3e, 0x10, 
+    0x3e, 0x10, 0x0a, 0x51, 0x2d, 0x35, 0x69, 0x41, 0x00, 0x02, 0x0b, 0x1a, 0x30, 0xbd, 0x38, 0x50, 
+    0x02, 0x2d, 0x38, 0xbe, 0x44, 0xff, 0xff, 0x78, 0x05, 0x7e, 0x1b, 0x90, 0x0a, 0x49, 0x4d, 0x44, 
+    0x68, 0x0c, 0xbe, 0x44, 0x00, 0xff, 0x28, 0x04, 0x7e, 0x44, 0x00, 0xff, 0xc3, 0x22, 0xd3, 0x22, 
+
+// Segment #15, Start Address 00ff7fc6, Length 4
+0xff,0x00,0xc6,0x7f,0x04,0x00,
+    0x01, 0x0c, 0x03, 0x00, 
+
+// Segment #16, Start Address 00ff7e30, Length 315
+0xff,0x00,0x30,0x7e,0x3b,0x01,
+    0xca, 0x08, 0x7e, 0x01, 0x2f, 0x7a, 0x03, 0x3f, 0xf0, 0xda, 0x08, 0x22, 0x7e, 0x1b, 0xc0, 0x7a, 
+    0x0b, 0xc0, 0x0b, 0x14, 0x0b, 0x34, 0x1b, 0x44, 0x78, 0xf2, 0x22, 0x7f, 0x6f, 0x7f, 0xf0, 0x1b, 
+    0xfc, 0x7c, 0x54, 0x7d, 0x32, 0x80, 0x08, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0x9e, 
+    0x44, 0x00, 0x10, 0x50, 0xf2, 0x2e, 0x44, 0x00, 0x10, 0x68, 0x06, 0xca, 0x48, 0x1b, 0x44, 0x78, 
+    0xfa, 0x7f, 0xf6, 0x89, 0xe4, 0xca, 0x6b, 0x5e, 0xd4, 0x00, 0x3f, 0x68, 0x20, 0x7e, 0x84, 0x00, 
+    0x40, 0x9d, 0x8d, 0xda, 0x6b, 0xbd, 0x87, 0x38, 0x16, 0xca, 0x79, 0x7d, 0x78, 0x12, 0x7e, 0x9f, 
+    0xda, 0x79, 0x40, 0x08, 0x9d, 0x78, 0x68, 0x02, 0x80, 0x05, 0xc2, 0xd7, 0x22, 0xda, 0x6b, 0x43, 
+    0x90, 0x30, 0x74, 0xaa, 0x39, 0xb5, 0x55, 0x55, 0x74, 0x55, 0x39, 0xb5, 0x2a, 0xaa, 0x74, 0xa0, 
+    0x39, 0xb5, 0x55, 0x55, 0x7e, 0x04, 0x00, 0x40, 0x9d, 0x70, 0x50, 0x06, 0x2d, 0x70, 0x7d, 0x07, 
+    0x6d, 0x77, 0x7c, 0x31, 0x7e, 0x7b, 0x00, 0x7a, 0x6b, 0x00, 0x0b, 0x7c, 0x0b, 0x6c, 0xa5, 0xd9, 
+    0xf3, 0x7f, 0x16, 0x1b, 0x1c, 0x7e, 0x54, 0x27, 0x10, 0x7e, 0x1b, 0x10, 0xbc, 0x10, 0x68, 0x06, 
+    0x1b, 0x54, 0x78, 0xf5, 0x80, 0x2c, 0x6d, 0x00, 0x7c, 0x20, 0x7f, 0x16, 0x9f, 0x10, 0x7f, 0x27, 
+    0x9f, 0x20, 0x7e, 0x2b, 0x00, 0x7e, 0x1b, 0x10, 0xbc, 0x01, 0x78, 0x16, 0x0b, 0x2c, 0x0b, 0x1c, 
+    0xa5, 0xdb, 0xef, 0x7c, 0xb6, 0x20, 0xe0, 0x03, 0x63, 0x90, 0x30, 0x4d, 0x77, 0x78, 0x93, 0xc2, 
+    0xd7, 0x22, 0xd2, 0xd7, 0x22, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x06, 0x04, 0x02, 0x04, 0x00, 
+    0x02, 0x01, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 
+    0x02, 0x02, 0x04, 0x00, 0x08, 0x10, 0x02, 0x10, 0x04, 0x02, 0x08, 0x00, 0x01, 0x01, 0x08, 0x7e, 
+    0x18, 0x7f, 0xbd, 0x7a, 0x1c, 0x00, 0xfe, 0x0b, 0x1a, 0x00, 0xbe, 0x10, 0x14, 0x38, 0x1a, 0x0a, 
+    0x51, 0x23, 0x7e, 0x18, 0x7f, 0x15, 0x7a, 0x1c, 0x00, 0xff, 0x2d, 0x35, 0x0b, 0x1a, 0x50, 0x60, 
+    0x08, 0xa5, 0xb8, 0x02, 0x03, 0x4e, 0xa0, 0x08, 0x22, 0x80, 0xfe, 
+};
+
+static EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME = {
+       1, 12, 3 };             // Major, Minor, Build
+
+#undef IMAGE_VERSION_NAME
+
+#undef IMAGE_ARRAY_NAME
+
diff --git a/drivers/usb/serial/io_fw_down2.h b/drivers/usb/serial/io_fw_down2.h
new file mode 100644 (file)
index 0000000..1ca4042
--- /dev/null
@@ -0,0 +1,1135 @@
+//**************************************************************
+//* Edgeport/4 Binary Image
+//* Generated by HEX2C v1.06
+//* Copyright(c) 1998 Inside Out Networks, All rights reserved.
+//*    This program is free software; you can redistribute it and/or modify
+//*    it under the terms of the GNU General Public License as published by
+//*    the Free Software Foundation; either version 2 of the License, or
+//*    (at your option) any later version.
+//**************************************************************
+
+
+//Image structure definition
+#if !defined(DEFINED_EDGE_FIRMWARE_IMAGE_RECORD)
+       #define DEFINED_EDGE_FIRMWARE_IMAGE_RECORD
+       typedef struct _EDGE_FIRMWARE_IMAGE_RECORD
+       {
+               unsigned short ExtAddr;
+               unsigned short Addr;
+               unsigned short Len;
+               unsigned char  Data[0];
+       } EDGE_FIRMWARE_IMAGE_RECORD, *PEDGE_FIRMWARE_IMAGE_RECORD;
+
+       typedef struct _EDGE_FIRMWARE_VERSION_INFO
+       {
+               unsigned char    MajorVersion;
+               unsigned char  MinorVersion;
+               unsigned short BuildNumber;
+       } EDGE_FIRMWARE_VERSION_INFO, *PEDGE_FIRMWARE_VERSION_INFO;
+
+#endif
+
+#if !defined(IMAGE_ARRAY_NAME)
+       #define IMAGE_ARRAY_NAME        FirmwareImage
+       #define IMAGE_VERSION_NAME      FirmwareImageVersion
+#endif
+
+static unsigned char IMAGE_ARRAY_NAME[] = {
+
+// Segment #1, Start Address 00ff0000, Length 6
+0xff,0x00,0x00,0x00,0x06,0x00,
+    0x02, 0x00, 0x80, 0x02, 0x45, 0x14, 
+
+// Segment #2, Start Address 00ff000b, Length 3
+0xff,0x00,0x0b,0x00,0x03,0x00,
+    0x02, 0x44, 0xa5, 
+
+// Segment #3, Start Address 00ff0013, Length 3
+0xff,0x00,0x13,0x00,0x03,0x00,
+    0x02, 0x63, 0xab, 
+
+// Segment #4, Start Address 00ff001b, Length 3
+0xff,0x00,0x1b,0x00,0x03,0x00,
+    0x02, 0x00, 0x1b, 
+
+// Segment #5, Start Address 00ff0023, Length 3
+0xff,0x00,0x23,0x00,0x03,0x00,
+    0x02, 0x00, 0x23, 
+
+// Segment #6, Start Address 00ff002b, Length 3
+0xff,0x00,0x2b,0x00,0x03,0x00,
+    0x02, 0x00, 0x2b, 
+
+// Segment #7, Start Address 00ff0033, Length 3
+0xff,0x00,0x33,0x00,0x03,0x00,
+    0x02, 0x00, 0x33, 
+
+// Segment #8, Start Address 00ff003b, Length 3
+0xff,0x00,0x3b,0x00,0x03,0x00,
+    0x02, 0x00, 0x3b, 
+
+// Segment #9, Start Address 00ff0043, Length 3
+0xff,0x00,0x43,0x00,0x03,0x00,
+    0x02, 0x00, 0x43, 
+
+// Segment #10, Start Address 00ff004b, Length 3
+0xff,0x00,0x4b,0x00,0x03,0x00,
+    0x02, 0x00, 0x4b, 
+
+// Segment #11, Start Address 00ff0053, Length 3
+0xff,0x00,0x53,0x00,0x03,0x00,
+    0x02, 0x67, 0x5f, 
+
+// Segment #12, Start Address 00ff007b, Length 3
+0xff,0x00,0x7b,0x00,0x03,0x00,
+    0x02, 0x00, 0x7b, 
+
+// Segment #13, Start Address 00ff0080, Length 7
+0xff,0x00,0x80,0x00,0x07,0x00,
+    0x7e, 0x14, 0x00, 0x00, 0x02, 0x40, 0x52, 
+
+// Segment #14, Start Address 00ff3000, Length 2918
+0xff,0x00,0x00,0x30,0x66,0x0b,
+    0x12, 0x30, 0x64, 0x12, 0x30, 0xff, 0x12, 0x31, 0x2f, 0x12, 0x30, 0xb0, 0x80, 0xf2, 0xe5, 0x23, 
+    0x60, 0x19, 0x7e, 0x14, 0x00, 0x00, 0x09, 0xb1, 0x01, 0xb9, 0xb4, 0x00, 0x02, 0x80, 0x05, 0x14, 
+    0x19, 0xb1, 0x01, 0xb9, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 0xeb, 0x22, 0xc2, 0xaf, 0x7e, 0xb3, 
+    0x3f, 0xf1, 0xb4, 0x01, 0x03, 0x12, 0x65, 0x67, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x7e, 0xb3, 0x3f, 
+    0xf1, 0xb4, 0x01, 0x1d, 0x74, 0x40, 0x7a, 0xb3, 0x91, 0x00, 0x7e, 0xb3, 0x91, 0x1a, 0x6c, 0xaa, 
+    0x60, 0x0f, 0xca, 0x0b, 0xca, 0x39, 0xca, 0x59, 0x12, 0x64, 0x24, 0xda, 0x59, 0xda, 0x39, 0xda, 
+    0x0b, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x22, 0x60, 0x43, 0x7e, 0x07, 0x01, 0xcb, 0xbe, 0x04, 
+    0x03, 0x80, 0x38, 0x39, 0x7e, 0x04, 0x80, 0x00, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x21, 0x09, 0xa0, 
+    0x00, 0x04, 0x4e, 0xa0, 0x05, 0x19, 0xa0, 0x00, 0x04, 0x0a, 0x32, 0x09, 0x53, 0x35, 0x33, 0x5e, 
+    0x51, 0x27, 0x68, 0x0b, 0x09, 0xa0, 0x00, 0x10, 0x4e, 0xa0, 0x01, 0x19, 0xa0, 0x00, 0x10, 0x2e, 
+    0x04, 0x01, 0x00, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 0xd1, 0x75, 0x22, 0x00, 0xd2, 0xaf, 0x22, 
+    0xc2, 0xaf, 0xe5, 0x26, 0x60, 0x36, 0x7e, 0x20, 0x00, 0x7e, 0x30, 0x01, 0xe5, 0x26, 0xa5, 0x5b, 
+    0x68, 0x21, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x32, 0x01, 0x79, 0xbe, 0x34, 0x00, 0x00, 0x68, 
+    0x12, 0x7e, 0xb1, 0x21, 0xa5, 0x4b, 0x7a, 0xb1, 0x21, 0xca, 0x19, 0x49, 0x22, 0x30, 0xef, 0x99, 
+    0x24, 0xda, 0x19, 0x3e, 0x30, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 0xd0, 0xd2, 0xaf, 0x22, 0x46, 
+    0x4f, 0x49, 0x7c, 0x4c, 0xa9, 0x4f, 0xd6, 0x53, 0x03, 0x56, 0x30, 0x59, 0x5d, 0x5c, 0x8a, 0xc2, 
+    0xaf, 0xe5, 0x24, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x31, 0x1c, 
+    0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 0xef, 0xd2, 0xaf, 0x22, 0xca, 0x28, 0x12, 0x35, 
+    0x4c, 0xda, 0x28, 0x40, 0x09, 0x0a, 0x22, 0x09, 0xb2, 0x35, 0x33, 0xf4, 0x52, 0x24, 0x22, 0xc2, 
+    0xaf, 0xe5, 0x23, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x31, 0x4c, 
+    0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 
+    0x2b, 0x49, 0x22, 0x31, 0x57, 0x89, 0x24, 0x31, 0x67, 0x31, 0xd0, 0x32, 0x39, 0x32, 0xa2, 0x33, 
+    0x0b, 0x33, 0x74, 0x33, 0xdd, 0x34, 0x46, 0x7e, 0x27, 0x01, 0x79, 0xbe, 0x24, 0x00, 0x00, 0x78, 
+    0x24, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 
+    0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x49, 0x45, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 
+    0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 0x89, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x89, 0x7e, 
+    0x60, 0x9c, 0x7a, 0x63, 0x01, 0xb9, 0x80, 0x27, 0x7e, 0x63, 0x01, 0xb9, 0xa5, 0xbe, 0x00, 0x1f, 
+    0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 0xc8, 0x12, 0x61, 0x36, 0x40, 0x11, 0x75, 0x2f, 
+    0xb3, 0x12, 0x73, 0x35, 0xc2, 0x18, 0x6c, 0x00, 0x7a, 0x03, 0x01, 0xb9, 0x12, 0x64, 0x86, 0x22, 
+    0x7e, 0x27, 0x01, 0x7b, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x4c, 0x72, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0x8b, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8b, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xba, 0x80, 
+    0x27, 0x7e, 0x63, 0x01, 0xba, 0xa5, 0xbe, 0x00, 0x1f, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x61, 0x36, 0x40, 0x11, 0x75, 0x2f, 0xb3, 0x12, 0x73, 0x35, 0xc2, 0x19, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xba, 0x12, 0x64, 0x86, 0x22, 0x7e, 0x27, 0x01, 0x7d, 0xbe, 0x24, 0x00, 
+    0x00, 0x78, 0x24, 0x7e, 0x24, 0x82, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 
+    0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4f, 0x9f, 0x7d, 0x21, 0xda, 0x19, 0x30, 
+    0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 0x8d, 0x68, 0x0d, 0x7a, 0x27, 0x01, 
+    0x8d, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbb, 0x80, 0x27, 0x7e, 0x63, 0x01, 0xbb, 0xa5, 0xbe, 
+    0x00, 0x1f, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 0xc8, 0x12, 0x61, 0x36, 0x40, 0x11, 
+    0x75, 0x2f, 0xb3, 0x12, 0x73, 0x35, 0xc2, 0x1a, 0x6c, 0x00, 0x7a, 0x03, 0x01, 0xbb, 0x12, 0x64, 
+    0x86, 0x22, 0x7e, 0x27, 0x01, 0x7f, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x83, 0x00, 
+    0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 
+    0x12, 0x12, 0x52, 0xcc, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 
+    0xbe, 0x27, 0x01, 0x8f, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8f, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 
+    0xbc, 0x80, 0x27, 0x7e, 0x63, 0x01, 0xbc, 0xa5, 0xbe, 0x00, 0x1f, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 
+    0x00, 0x7e, 0xa0, 0xc8, 0x12, 0x61, 0x36, 0x40, 0x11, 0x75, 0x2f, 0xb3, 0x12, 0x73, 0x35, 0xc2, 
+    0x1b, 0x6c, 0x00, 0x7a, 0x03, 0x01, 0xbc, 0x12, 0x64, 0x86, 0x22, 0x7e, 0x27, 0x01, 0x81, 0xbe, 
+    0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 
+    0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x55, 0xf9, 0x7d, 0x21, 0xda, 
+    0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 0x91, 0x68, 0x0d, 0x7a, 
+    0x27, 0x01, 0x91, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbd, 0x80, 0x27, 0x7e, 0x63, 0x01, 0xbd, 
+    0xa5, 0xbe, 0x00, 0x1f, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 0xc8, 0x12, 0x61, 0x36, 
+    0x40, 0x11, 0x75, 0x2f, 0xb3, 0x12, 0x73, 0x35, 0xc2, 0x1c, 0x6c, 0x00, 0x7a, 0x03, 0x01, 0xbd, 
+    0x12, 0x64, 0x86, 0x22, 0x7e, 0x27, 0x01, 0x83, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 
+    0x85, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 
+    0x19, 0x7d, 0x12, 0x12, 0x59, 0x26, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 
+    0x80, 0x1e, 0xbe, 0x27, 0x01, 0x93, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x93, 0x7e, 0x60, 0x9c, 0x7a, 
+    0x63, 0x01, 0xbe, 0x80, 0x27, 0x7e, 0x63, 0x01, 0xbe, 0xa5, 0xbe, 0x00, 0x1f, 0x7e, 0x60, 0x01, 
+    0x7e, 0xb0, 0x00, 0x7e, 0xa0, 0xc8, 0x12, 0x61, 0x36, 0x40, 0x11, 0x75, 0x2f, 0xb3, 0x12, 0x73, 
+    0x35, 0xc2, 0x1d, 0x6c, 0x00, 0x7a, 0x03, 0x01, 0xbe, 0x12, 0x64, 0x86, 0x22, 0x7e, 0x27, 0x01, 
+    0x85, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5c, 0x53, 0x7d, 
+    0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 0x95, 0x68, 
+    0x0d, 0x7a, 0x27, 0x01, 0x95, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbf, 0x80, 0x27, 0x7e, 0x63, 
+    0x01, 0xbf, 0xa5, 0xbe, 0x00, 0x1f, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 0xc8, 0x12, 
+    0x61, 0x36, 0x40, 0x11, 0x75, 0x2f, 0xb3, 0x12, 0x73, 0x35, 0xc2, 0x1e, 0x6c, 0x00, 0x7a, 0x03, 
+    0x01, 0xbf, 0x12, 0x64, 0x86, 0x22, 0x7e, 0x27, 0x01, 0x87, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 
+    0x7e, 0x24, 0x87, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 
+    0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5f, 0x80, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 
+    0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 0x97, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x97, 0x7e, 0x60, 
+    0x9c, 0x7a, 0x63, 0x01, 0xc0, 0x80, 0x27, 0x7e, 0x63, 0x01, 0xc0, 0xa5, 0xbe, 0x00, 0x1f, 0x7e, 
+    0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 0xc8, 0x12, 0x61, 0x36, 0x40, 0x11, 0x75, 0x2f, 0xb3, 
+    0x12, 0x73, 0x35, 0xc2, 0x1f, 0x6c, 0x00, 0x7a, 0x03, 0x01, 0xc0, 0x12, 0x64, 0x86, 0x22, 0xc2, 
+    0xaf, 0x7e, 0x07, 0x01, 0xcb, 0xbe, 0x04, 0x00, 0x00, 0x78, 0x28, 0x74, 0x20, 0x7a, 0xb3, 0x91, 
+    0x00, 0x7e, 0xb3, 0x91, 0x15, 0x30, 0xe5, 0x1b, 0x7e, 0xb3, 0x91, 0x1a, 0xbe, 0xb0, 0x3f, 0x38, 
+    0x0c, 0x85, 0x31, 0x2f, 0x12, 0x73, 0x35, 0x74, 0x80, 0x7a, 0xb3, 0x91, 0x1e, 0x74, 0x20, 0x7a, 
+    0xb3, 0x91, 0x15, 0xd2, 0xaf, 0x22, 0x35, 0x3b, 0x36, 0xe8, 0x37, 0x00, 0x37, 0x1b, 0x37, 0xb6, 
+    0x38, 0x4e, 0x38, 0x69, 0x38, 0xfb, 0x38, 0x84, 0x38, 0xc5, 0x7c, 0xb3, 0xbe, 0xb0, 0x09, 0x28, 
+    0x22, 0x75, 0x2f, 0x09, 0x12, 0x73, 0x35, 0x75, 0x57, 0x02, 0x74, 0x20, 0x7a, 0xb3, 0x91, 0x00, 
+    0x74, 0x01, 0x7a, 0xb3, 0x91, 0x11, 0x74, 0x40, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x01, 0x7a, 0xb3, 
+    0x91, 0x11, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0x23, 0x6c, 0xaa, 0x2e, 0x54, 0x34, 0xe6, 0x0b, 0x58, 
+    0x50, 0x89, 0x54, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x75, 0x2f, 0xb0, 0x12, 0x73, 
+    0x35, 0x0a, 0x22, 0x09, 0xb2, 0x35, 0x33, 0x42, 0x24, 0xd0, 0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 
+    0x3b, 0x49, 0x33, 0x35, 0x57, 0x89, 0x34, 0x35, 0x67, 0x35, 0x95, 0x35, 0xc3, 0x35, 0xf1, 0x36, 
+    0x1f, 0x36, 0x4d, 0x36, 0x7b, 0x36, 0xa9, 0x12, 0x41, 0xba, 0xd2, 0x28, 0xd2, 0x08, 0xc2, 0x40, 
+    0xc2, 0x48, 0xc2, 0x38, 0xc2, 0x30, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xb9, 0x7e, 0x04, 0x00, 0x20, 
+    0x7a, 0x07, 0x01, 0x99, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xa9, 0x12, 0x41, 0x27, 0x12, 
+    0x5f, 0xb7, 0x02, 0x36, 0xd7, 0x12, 0x41, 0xd7, 0xd2, 0x29, 0xd2, 0x09, 0xc2, 0x41, 0xc2, 0x49, 
+    0xc2, 0x39, 0xc2, 0x31, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xba, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 
+    0x01, 0x9b, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xab, 0x12, 0x41, 0x27, 0x12, 0x5f, 0xe0, 
+    0x02, 0x36, 0xd7, 0x12, 0x41, 0xf4, 0xd2, 0x2a, 0xd2, 0x0a, 0xc2, 0x42, 0xc2, 0x4a, 0xc2, 0x3a, 
+    0xc2, 0x32, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbb, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0x9d, 
+    0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xad, 0x12, 0x41, 0x27, 0x12, 0x60, 0x09, 0x02, 0x36, 
+    0xd7, 0x12, 0x42, 0x11, 0xd2, 0x2b, 0xd2, 0x0b, 0xc2, 0x43, 0xc2, 0x4b, 0xc2, 0x3b, 0xc2, 0x33, 
+    0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbc, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0x9f, 0x7e, 0x04, 
+    0x00, 0x38, 0x7a, 0x07, 0x01, 0xaf, 0x12, 0x41, 0x27, 0x12, 0x60, 0x32, 0x02, 0x36, 0xd7, 0x12, 
+    0x42, 0x2e, 0xd2, 0x2c, 0xd2, 0x0c, 0xc2, 0x44, 0xc2, 0x4c, 0xc2, 0x3c, 0xc2, 0x34, 0x6d, 0x00, 
+    0x7a, 0x03, 0x01, 0xbd, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa1, 0x7e, 0x04, 0x00, 0x38, 
+    0x7a, 0x07, 0x01, 0xb1, 0x12, 0x41, 0x27, 0x12, 0x60, 0x5b, 0x02, 0x36, 0xd7, 0x12, 0x42, 0x4b, 
+    0xd2, 0x2d, 0xd2, 0x0d, 0xc2, 0x45, 0xc2, 0x4d, 0xc2, 0x3d, 0xc2, 0x35, 0x6d, 0x00, 0x7a, 0x03, 
+    0x01, 0xbe, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa3, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 
+    0x01, 0xb3, 0x12, 0x41, 0x27, 0x12, 0x60, 0x84, 0x02, 0x36, 0xd7, 0x12, 0x42, 0x68, 0xd2, 0x2e, 
+    0xd2, 0x0e, 0xc2, 0x46, 0xc2, 0x4e, 0xc2, 0x3e, 0xc2, 0x36, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbf, 
+    0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa5, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xb5, 
+    0x12, 0x41, 0x27, 0x12, 0x60, 0xad, 0x02, 0x36, 0xd7, 0x12, 0x42, 0x85, 0xd2, 0x2f, 0xd2, 0x0f, 
+    0xc2, 0x47, 0xc2, 0x4f, 0xc2, 0x3f, 0xc2, 0x37, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xc0, 0x7e, 0x04, 
+    0x00, 0x20, 0x7a, 0x07, 0x01, 0xa7, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xb7, 0x12, 0x41, 
+    0x27, 0x12, 0x60, 0xd6, 0x02, 0x36, 0xd7, 0x7e, 0xa0, 0xd0, 0x7e, 0x60, 0x0f, 0x12, 0x61, 0x36, 
+    0x40, 0x05, 0x12, 0x64, 0x86, 0xc2, 0xd7, 0x22, 0x75, 0x2f, 0xb1, 0x12, 0x73, 0x35, 0x0a, 0x52, 
+    0x23, 0x6d, 0x00, 0x59, 0x05, 0x00, 0x32, 0x12, 0x41, 0x83, 0x12, 0x41, 0x9f, 0xd0, 0xa8, 0x22, 
+    0x75, 0x2f, 0xb2, 0x12, 0x73, 0x35, 0x0a, 0x22, 0x09, 0xb2, 0x35, 0x33, 0x42, 0x23, 0x7e, 0xb0, 
+    0x9c, 0x19, 0xb2, 0x01, 0xb9, 0x12, 0x31, 0x4c, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 
+    0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x19, 
+    0x30, 0x00, 0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x12, 0x44, 0x40, 0xca, 0xb8, 0x09, 0xb0, 
+    0x00, 0x10, 0x44, 0x02, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x02, 0x54, 0xbf, 0x7c, 0x74, 
+    0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x08, 0x80, 0x02, 0x54, 0xf7, 0x09, 0x30, 0x00, 0x0c, 0xca, 
+    0xb8, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xda, 0xb8, 0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 
+    0x0c, 0x0a, 0x62, 0x09, 0xb6, 0x35, 0x33, 0x3e, 0x20, 0x0a, 0x62, 0x7c, 0x74, 0x5e, 0x70, 0x02, 
+    0x68, 0x20, 0x42, 0x27, 0xca, 0xb8, 0x74, 0x61, 0x19, 0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x10, 
+    0x59, 0x46, 0x01, 0xa9, 0x09, 0xb0, 0x00, 0x10, 0x44, 0x01, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 
+    0x80, 0x11, 0xf4, 0x52, 0x27, 0x74, 0xa1, 0x19, 0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x38, 0x59, 
+    0x46, 0x01, 0xa9, 0xd0, 0xa8, 0x22, 0x7c, 0x74, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 
+    0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x7c, 0x74, 0x5e, 0x70, 
+    0x01, 0x68, 0x04, 0x44, 0x80, 0x80, 0x02, 0x54, 0x7f, 0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 
+    0x44, 0x02, 0x80, 0x02, 0x54, 0xfd, 0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 0x62, 
+    0x09, 0xb6, 0x35, 0x33, 0xa5, 0xfd, 0xf4, 0xa5, 0xfe, 0xca, 0x28, 0x3e, 0x20, 0x0a, 0x62, 0xda, 
+    0x28, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x10, 0xa5, 0xed, 0x42, 0x28, 0x42, 0x26, 0x7e, 0x44, 
+    0x00, 0x08, 0x59, 0x46, 0x01, 0x99, 0x80, 0x04, 0xa5, 0xee, 0x52, 0x28, 0x7c, 0x74, 0x5e, 0x70, 
+    0x04, 0x68, 0x10, 0xa5, 0xed, 0x42, 0x29, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 
+    0x99, 0x80, 0x15, 0xa5, 0xee, 0x52, 0x29, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x78, 0x0a, 0x52, 0x26, 
+    0x7e, 0x44, 0x00, 0x20, 0x59, 0x46, 0x01, 0x99, 0x12, 0x42, 0xa2, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 
+    0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 
+    0x00, 0x10, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 
+    0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 0x00, 0x18, 0x19, 0x30, 0x00, 
+    0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb5, 0x12, 0x73, 0x35, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 
+    0x09, 0xb0, 0x00, 0x0c, 0x44, 0x40, 0x19, 0xb0, 0x00, 0x0c, 0xe5, 0x58, 0xb4, 0x07, 0x23, 0x09, 
+    0xb0, 0x00, 0x10, 0x4e, 0xb0, 0x02, 0x19, 0xb0, 0x00, 0x10, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 
+    0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x54, 0xf7, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 
+    0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb6, 0x12, 0x73, 0x35, 0x7e, 0x04, 0x80, 0x00, 0x4c, 
+    0x02, 0xe5, 0x58, 0xb4, 0x07, 0x18, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 
+    0x09, 0xb0, 0x00, 0x04, 0x44, 0x08, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 0x00, 0x0c, 0x09, 0xb0, 
+    0x00, 0x0c, 0x54, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb4, 0x12, 0x73, 
+    0x35, 0x7a, 0x21, 0x2f, 0x12, 0x73, 0x35, 0x7a, 0x41, 0x2f, 0x12, 0x73, 0x35, 0x7e, 0xb0, 0x01, 
+    0x7e, 0xa0, 0xc8, 0x7c, 0x64, 0x12, 0x61, 0x36, 0x12, 0x64, 0x86, 0xd0, 0xa8, 0x22, 0x39, 0x2e, 
+    0x39, 0x75, 0x39, 0xbc, 0x3a, 0x03, 0x3a, 0x4a, 0x3a, 0x91, 0x3a, 0xd8, 0x3b, 0x1f, 0x75, 0x2f, 
+    0x55, 0x12, 0x73, 0x35, 0x75, 0x2f, 0x00, 0x12, 0x73, 0x35, 0x7a, 0x61, 0x2f, 0x12, 0x73, 0x35, 
+    0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 0x7e, 0x17, 0x01, 0x69, 0x7e, 0x27, 0x01, 0x79, 0x2d, 0x23, 
+    0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x08, 0x2c, 0x38, 0x0f, 
+    0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x69, 0x7a, 0x27, 0x01, 0x79, 0x02, 0x46, 0x4f, 0x7e, 
+    0x14, 0x04, 0x2d, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x73, 0x35, 0x75, 0x2f, 0x01, 0x12, 0x73, 
+    0x35, 0x7a, 0x61, 0x2f, 0x12, 0x73, 0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 0x7e, 0x17, 0x01, 
+    0x6b, 0x7e, 0x27, 0x01, 0x7b, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 
+    0x14, 0xbe, 0x14, 0x0c, 0x2c, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x6b, 0x7a, 
+    0x27, 0x01, 0x7b, 0x02, 0x49, 0x7c, 0x7e, 0x14, 0x08, 0x2d, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 
+    0x73, 0x35, 0x75, 0x2f, 0x02, 0x12, 0x73, 0x35, 0x7a, 0x61, 0x2f, 0x12, 0x73, 0x35, 0x7a, 0x71, 
+    0x2f, 0x12, 0x73, 0x35, 0x7e, 0x17, 0x01, 0x6d, 0x7e, 0x27, 0x01, 0x7d, 0x2d, 0x23, 0x7e, 0x09, 
+    0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x10, 0x2c, 0x38, 0x0f, 0x1b, 0x34, 
+    0x78, 0xec, 0x7a, 0x17, 0x01, 0x6d, 0x7a, 0x27, 0x01, 0x7d, 0x02, 0x4c, 0xa9, 0x7e, 0x14, 0x0c, 
+    0x2d, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x73, 0x35, 0x75, 0x2f, 0x03, 0x12, 0x73, 0x35, 0x7a, 
+    0x61, 0x2f, 0x12, 0x73, 0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 0x7e, 0x17, 0x01, 0x6f, 0x7e, 
+    0x27, 0x01, 0x7f, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 
+    0x14, 0x14, 0x2c, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x6f, 0x7a, 0x27, 0x01, 
+    0x7f, 0x02, 0x4f, 0xd6, 0x7e, 0x14, 0x10, 0x2d, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x73, 0x35, 
+    0x75, 0x2f, 0x04, 0x12, 0x73, 0x35, 0x7a, 0x61, 0x2f, 0x12, 0x73, 0x35, 0x7a, 0x71, 0x2f, 0x12, 
+    0x73, 0x35, 0x7e, 0x17, 0x01, 0x71, 0x7e, 0x27, 0x01, 0x81, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 
+    0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x18, 0x2c, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 
+    0x7a, 0x17, 0x01, 0x71, 0x7a, 0x27, 0x01, 0x81, 0x02, 0x53, 0x03, 0x7e, 0x14, 0x14, 0x2d, 0x80, 
+    0xeb, 0x75, 0x2f, 0x55, 0x12, 0x73, 0x35, 0x75, 0x2f, 0x05, 0x12, 0x73, 0x35, 0x7a, 0x61, 0x2f, 
+    0x12, 0x73, 0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 0x7e, 0x17, 0x01, 0x73, 0x7e, 0x27, 0x01, 
+    0x83, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x1c, 
+    0x2c, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x73, 0x7a, 0x27, 0x01, 0x83, 0x02, 
+    0x56, 0x30, 0x7e, 0x14, 0x18, 0x2d, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x73, 0x35, 0x75, 0x2f, 
+    0x06, 0x12, 0x73, 0x35, 0x7a, 0x61, 0x2f, 0x12, 0x73, 0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 
+    0x7e, 0x17, 0x01, 0x75, 0x7e, 0x27, 0x01, 0x85, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 
+    0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x20, 0x2c, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 
+    0x01, 0x75, 0x7a, 0x27, 0x01, 0x85, 0x02, 0x59, 0x5d, 0x7e, 0x14, 0x1c, 0x2d, 0x80, 0xeb, 0x75, 
+    0x2f, 0x55, 0x12, 0x73, 0x35, 0x75, 0x2f, 0x07, 0x12, 0x73, 0x35, 0x7a, 0x61, 0x2f, 0x12, 0x73, 
+    0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 0x7e, 0x17, 0x01, 0x77, 0x7e, 0x27, 0x01, 0x87, 0x2d, 
+    0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x24, 0x2c, 0x38, 
+    0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x77, 0x7a, 0x27, 0x01, 0x87, 0x02, 0x5c, 0x8a, 
+    0x7e, 0x14, 0x20, 0x2d, 0x80, 0xeb, 
+
+// Segment #15, Start Address 00ff4000, Length 13109
+0xff,0x00,0x00,0x40,0x35,0x33,
+    0x7e, 0x04, 0x00, 0x01, 0x7e, 0x14, 0x7f, 0xf8, 0x7e, 0x24, 0x00, 0xfe, 0x7d, 0x31, 0x0b, 0x1a, 
+    0x50, 0x1b, 0x0a, 0x50, 0x7e, 0x14, 0x40, 0x1b, 0x02, 0x40, 0x74, 0x7e, 0xf8, 0x00, 0x59, 0x75, 
+    0xb0, 0xdf, 0x7e, 0xb0, 0x01, 0x7a, 0xb3, 0x90, 0x00, 0x7e, 0xf4, 0x40, 0x30, 0x02, 0x40, 0x8b, 
+    0x12, 0x74, 0x4e, 0xf5, 0x2e, 0x7a, 0xa1, 0x2d, 0x7a, 0x11, 0x58, 0x12, 0x6b, 0x02, 0x12, 0x40, 
+    0xeb, 0x7e, 0xb3, 0x3f, 0xf1, 0x60, 0x03, 0x12, 0x43, 0x79, 0x12, 0x6b, 0xde, 0xd2, 0xaf, 0x02, 
+    0x30, 0x00, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 0x40, 0x60, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 
+    0x7e, 0xb0, 0x01, 0x7a, 0xb3, 0x94, 0x00, 0x7a, 0xb3, 0x2c, 0x35, 0x7e, 0xb0, 0x01, 0x7a, 0xb3, 
+    0x93, 0x00, 0x89, 0x08, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 0x40, 0x82, 0x7a, 0x1c, 0x00, 0x01, 
+    0x89, 0x18, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x93, 0x00, 0x89, 0x08, 0x7e, 0x08, 0x00, 0x20, 0x7e, 
+    0x44, 0x04, 0x00, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0x9d, 0x02, 0x73, 0x50, 0x7e, 0x08, 0x01, 
+    0x59, 0x7e, 0x44, 0x2a, 0xdd, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0xaf, 0x02, 0x73, 0x50, 0x7e, 
+    0x08, 0x00, 0x59, 0x7e, 0x44, 0x01, 0x00, 0x7e, 0x40, 0x53, 0x7e, 0xe4, 0x40, 0xc1, 0x02, 0x73, 
+    0x50, 0x75, 0x57, 0x01, 0x75, 0x56, 0x00, 0x7e, 0x04, 0x00, 0x08, 0x75, 0x54, 0x58, 0x75, 0x55, 
+    0x08, 0x75, 0x51, 0x08, 0x75, 0x53, 0x01, 0x75, 0x89, 0x01, 0x75, 0x8a, 0x01, 0x75, 0x8c, 0x00, 
+    0xd2, 0x8c, 0x7e, 0x04, 0x00, 0x02, 0x7a, 0x05, 0x42, 0x89, 0xf4, 0x75, 0xb7, 0x7f, 0x75, 0xb8, 
+    0x7f, 0x75, 0xb3, 0x01, 0x75, 0xb2, 0x01, 0xd2, 0xa9, 0x22, 0x75, 0xb0, 0xdf, 0xe4, 0xd5, 0xe0, 
+    0xfd, 0x75, 0xb0, 0xef, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x2e, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 
+    0x00, 0x10, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xf2, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x83, 0x0b, 
+    0x20, 0xbe, 0x21, 0x2e, 0x78, 0xf6, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x74, 0xbf, 0x19, 
+    0xb0, 0x00, 0x0c, 0x74, 0x10, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x80, 0x19, 0xb0, 0x00, 0x0c, 0x7e, 
+    0x54, 0x00, 0x02, 0x19, 0xa0, 0x00, 0x04, 0x19, 0xb0, 0x00, 0x00, 0x74, 0x03, 0x19, 0xb0, 0x00, 
+    0x0c, 0x74, 0x07, 0x20, 0x68, 0x02, 0x74, 0x0f, 0x19, 0xb0, 0x00, 0x04, 0x30, 0x6b, 0x17, 0x74, 
+    0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x74, 0x28, 0x20, 0x68, 0x02, 0x74, 0x20, 0x19, 0xb0, 0x00, 0x04, 
+    0x74, 0x03, 0x19, 0xb0, 0x00, 0x0c, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x0c, 0x19, 0xb0, 
+    0x00, 0x10, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0xe4, 0x19, 0xb0, 0x00, 0x04, 0x09, 0xb0, 
+    0x00, 0x10, 0x54, 0x08, 0x19, 0xb0, 0x00, 0x10, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x22, 0x7c, 
+    0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x41, 0xaa, 0x89, 0x24, 0x41, 0xba, 0x41, 0xd7, 0x41, 0xf4, 
+    0x42, 0x11, 0x42, 0x2e, 0x42, 0x4b, 0x42, 0x68, 0x42, 0x85, 0xc2, 0x10, 0xc2, 0x18, 0xc2, 0x08, 
+    0x7e, 0x04, 0x04, 0x2d, 0x7a, 0x07, 0x01, 0x59, 0x7a, 0x07, 0x01, 0x69, 0x6d, 0x00, 0x7a, 0x07, 
+    0x01, 0x79, 0x7a, 0x07, 0x01, 0x89, 0x22, 0xc2, 0x11, 0xc2, 0x19, 0xc2, 0x09, 0x7e, 0x04, 0x08, 
+    0x2d, 0x7a, 0x07, 0x01, 0x5b, 0x7a, 0x07, 0x01, 0x6b, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 
+    0x07, 0x01, 0x8b, 0x22, 0xc2, 0x12, 0xc2, 0x1a, 0xc2, 0x0a, 0x7e, 0x04, 0x0c, 0x2d, 0x7a, 0x07, 
+    0x01, 0x5d, 0x7a, 0x07, 0x01, 0x6d, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7d, 0x7a, 0x07, 0x01, 0x8d, 
+    0x22, 0xc2, 0x13, 0xc2, 0x1b, 0xc2, 0x0b, 0x7e, 0x04, 0x10, 0x2d, 0x7a, 0x07, 0x01, 0x5f, 0x7a, 
+    0x07, 0x01, 0x6f, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7f, 0x7a, 0x07, 0x01, 0x8f, 0x22, 0xc2, 0x14, 
+    0xc2, 0x1c, 0xc2, 0x0c, 0x7e, 0x04, 0x14, 0x2d, 0x7a, 0x07, 0x01, 0x61, 0x7a, 0x07, 0x01, 0x71, 
+    0x6d, 0x00, 0x7a, 0x07, 0x01, 0x81, 0x7a, 0x07, 0x01, 0x91, 0x22, 0xc2, 0x15, 0xc2, 0x1d, 0xc2, 
+    0x0d, 0x7e, 0x04, 0x18, 0x2d, 0x7a, 0x07, 0x01, 0x63, 0x7a, 0x07, 0x01, 0x73, 0x6d, 0x00, 0x7a, 
+    0x07, 0x01, 0x83, 0x7a, 0x07, 0x01, 0x93, 0x22, 0xc2, 0x16, 0xc2, 0x1e, 0xc2, 0x0e, 0x7e, 0x04, 
+    0x1c, 0x2d, 0x7a, 0x07, 0x01, 0x65, 0x7a, 0x07, 0x01, 0x75, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x85, 
+    0x7a, 0x07, 0x01, 0x95, 0x22, 0xc2, 0x17, 0xc2, 0x1f, 0xc2, 0x0f, 0x7e, 0x04, 0x20, 0x2d, 0x7a, 
+    0x07, 0x01, 0x67, 0x7a, 0x07, 0x01, 0x77, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x87, 0x7a, 0x07, 0x01, 
+    0x97, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x42, 0xad, 0x89, 0x24, 0x42, 0xbd, 0x42, 
+    0xd4, 0x42, 0xeb, 0x43, 0x02, 0x43, 0x19, 0x43, 0x30, 0x43, 0x47, 0x43, 0x5e, 0x30, 0x40, 0x07, 
+    0x20, 0x58, 0x04, 0xc2, 0x28, 0x80, 0x0c, 0x30, 0x48, 0x07, 0x20, 0x50, 0x04, 0xc2, 0x28, 0x80, 
+    0x02, 0xd2, 0x28, 0x22, 0x30, 0x41, 0x07, 0x20, 0x59, 0x04, 0xc2, 0x29, 0x80, 0x0c, 0x30, 0x49, 
+    0x07, 0x20, 0x51, 0x04, 0xc2, 0x29, 0x80, 0x02, 0xd2, 0x29, 0x22, 0x30, 0x42, 0x07, 0x20, 0x5a, 
+    0x04, 0xc2, 0x2a, 0x80, 0x0c, 0x30, 0x4a, 0x07, 0x20, 0x52, 0x04, 0xc2, 0x2a, 0x80, 0x02, 0xd2, 
+    0x2a, 0x22, 0x30, 0x43, 0x07, 0x20, 0x5b, 0x04, 0xc2, 0x2b, 0x80, 0x0c, 0x30, 0x4b, 0x07, 0x20, 
+    0x53, 0x04, 0xc2, 0x2b, 0x80, 0x02, 0xd2, 0x2b, 0x22, 0x30, 0x44, 0x07, 0x20, 0x5c, 0x04, 0xc2, 
+    0x2c, 0x80, 0x0c, 0x30, 0x4c, 0x07, 0x20, 0x54, 0x04, 0xc2, 0x2c, 0x80, 0x02, 0xd2, 0x2c, 0x22, 
+    0x30, 0x45, 0x07, 0x20, 0x5d, 0x04, 0xc2, 0x2d, 0x80, 0x0c, 0x30, 0x4d, 0x07, 0x20, 0x55, 0x04, 
+    0xc2, 0x2d, 0x80, 0x02, 0xd2, 0x2d, 0x22, 0x30, 0x46, 0x07, 0x20, 0x5e, 0x04, 0xc2, 0x2e, 0x80, 
+    0x0c, 0x30, 0x4e, 0x07, 0x20, 0x56, 0x04, 0xc2, 0x2e, 0x80, 0x02, 0xd2, 0x2e, 0x22, 0x30, 0x47, 
+    0x07, 0x20, 0x5f, 0x04, 0xc2, 0x2f, 0x80, 0x0c, 0x30, 0x4f, 0x07, 0x20, 0x57, 0x04, 0xc2, 0x2f, 
+    0x80, 0x02, 0xd2, 0x2f, 0x22, 0x44, 0x66, 0x43, 0x8a, 0xbe, 0xb0, 0x02, 0x40, 0x01, 0x22, 0x23, 
+    0x0a, 0x5b, 0x49, 0x55, 0x43, 0x75, 0x99, 0x54, 0xd3, 0x22, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x94, 
+    0x00, 0x7a, 0xb3, 0x2c, 0x35, 0x12, 0x44, 0x7a, 0x7e, 0x04, 0x28, 0x2d, 0x7a, 0x07, 0x01, 0xc1, 
+    0x7a, 0x07, 0x01, 0xc3, 0x7e, 0x04, 0x24, 0x2d, 0x7a, 0x07, 0x01, 0xc7, 0x7a, 0x07, 0x01, 0xc9, 
+    0x7e, 0x04, 0x66, 0x7f, 0x7a, 0x05, 0x4b, 0x74, 0x20, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 
+    0xb3, 0x91, 0x1c, 0x74, 0x12, 0x7a, 0xb3, 0x91, 0x06, 0x74, 0x40, 0x7a, 0xb3, 0x91, 0x07, 0x74, 
+    0x1e, 0x7a, 0xb3, 0x91, 0x10, 0x74, 0x48, 0x7a, 0xb3, 0x91, 0x12, 0x74, 0x10, 0x7a, 0xb3, 0x91, 
+    0x13, 0x74, 0x3f, 0x7a, 0xb3, 0x91, 0x14, 0x74, 0x40, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 
+    0xb3, 0x91, 0x1c, 0x74, 0x14, 0x7a, 0xb3, 0x91, 0x06, 0x74, 0x40, 0x7a, 0xb3, 0x91, 0x07, 0x74, 
+    0x16, 0x7a, 0xb3, 0x91, 0x10, 0x74, 0x08, 0x7a, 0xb3, 0x91, 0x11, 0x74, 0x20, 0x7a, 0xb3, 0x91, 
+    0x13, 0x74, 0x3f, 0x7a, 0xb3, 0x91, 0x14, 0x74, 0x60, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 
+    0xb3, 0x91, 0x1c, 0x74, 0x16, 0x7a, 0xb3, 0x91, 0x06, 0x74, 0x20, 0x7a, 0xb3, 0x91, 0x07, 0x74, 
+    0x2f, 0x7a, 0xb3, 0x91, 0x10, 0x74, 0x48, 0x7a, 0xb3, 0x91, 0x12, 0x74, 0x10, 0x7a, 0xb3, 0x91, 
+    0x13, 0x74, 0x3f, 0x7a, 0xb3, 0x91, 0x14, 0x74, 0x02, 0x7a, 0xb3, 0x91, 0x06, 0x74, 0x0f, 0x7a, 
+    0xb3, 0x91, 0x07, 0x12, 0x40, 0xfa, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x9f, 0x0b, 0x20, 0xbe, 0x21, 
+    0x2e, 0x78, 0xf6, 0xd2, 0xa8, 0x22, 0x7e, 0xb0, 0x01, 0x7a, 0xb3, 0x94, 0x00, 0x7a, 0xb3, 0x2c, 
+    0x35, 0x12, 0x44, 0x7a, 0x75, 0xb0, 0xdf, 0xc2, 0xa8, 0x22, 0x74, 0x02, 0x7a, 0xb3, 0x91, 0x06, 
+    0x74, 0x01, 0x7a, 0xb3, 0x91, 0x07, 0x7e, 0x20, 0x04, 0x7c, 0xb2, 0xc2, 0xd7, 0x13, 0x13, 0x13, 
+    0x13, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 0xb3, 0x91, 0x1c, 0x74, 0x02, 0x7a, 0xb3, 0x91, 
+    0x12, 0xa5, 0xda, 0xe5, 0x22, 0xca, 0x09, 0x12, 0x30, 0x0e, 0x10, 0x01, 0x34, 0xd5, 0x51, 0x40, 
+    0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x02, 0x7a, 0xb3, 0x91, 0x06, 0x7e, 0xb3, 0x91, 0x07, 
+    0x74, 0x03, 0x7a, 0xb3, 0x91, 0x06, 0x7e, 0xb3, 0x91, 0x07, 0x7e, 0xb3, 0x91, 0x14, 0x7e, 0xb3, 
+    0x91, 0x04, 0x63, 0x53, 0x01, 0x7e, 0x00, 0x54, 0x2e, 0x01, 0x53, 0xa5, 0xe6, 0xf5, 0x51, 0x80, 
+    0x12, 0x20, 0x02, 0x1d, 0x75, 0x53, 0x00, 0x85, 0x54, 0x51, 0xd2, 0x02, 0x74, 0x03, 0x80, 0x0d, 
+    0x30, 0x02, 0x0e, 0xc2, 0x02, 0x7e, 0x00, 0x56, 0x2e, 0x01, 0x53, 0xa5, 0xe6, 0x7a, 0xb3, 0x90, 
+    0x00, 0xda, 0x09, 0x32, 0x45, 0x6f, 0x45, 0x8b, 0x45, 0xa7, 0x45, 0xc3, 0x45, 0xdf, 0x45, 0xfb, 
+    0x46, 0x17, 0x46, 0x33, 0xc0, 0xd0, 0xc0, 0xd1, 0xc0, 0xe0, 0xc0, 0xf0, 0xca, 0x0b, 0xca, 0x1b, 
+    0xca, 0x2b, 0xd2, 0x01, 0x75, 0x2f, 0x89, 0x12, 0x73, 0x35, 0x7e, 0xb3, 0x90, 0x00, 0x60, 0x28, 
+    0x7e, 0x14, 0x80, 0x00, 0x7e, 0x00, 0x00, 0x13, 0x50, 0x13, 0xca, 0x0b, 0xca, 0x59, 0x7c, 0xb0, 
+    0x23, 0x0a, 0x2b, 0x49, 0x22, 0x45, 0x04, 0x99, 0x24, 0xda, 0x59, 0xda, 0x0b, 0xa5, 0x0a, 0xa5, 
+    0x08, 0xbe, 0x01, 0x2e, 0x78, 0xe1, 0x80, 0xd2, 0x30, 0x04, 0x05, 0xc2, 0x04, 0x12, 0x64, 0x86, 
+    0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0xd0, 0xf0, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 0x32, 0x09, 
+    0xb1, 0x00, 0x08, 0x20, 0xe0, 0x14, 0x75, 0x2f, 0x80, 0x12, 0x73, 0x35, 0x54, 0x3e, 0x0a, 0x5b, 
+    0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x61, 0xab, 0x89, 0x54, 0x22, 0x09, 0xb1, 0x00, 0x08, 0x20, 
+    0xe0, 0x14, 0x75, 0x2f, 0x81, 0x12, 0x73, 0x35, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 
+    0x69, 0x52, 0x61, 0xeb, 0x89, 0x54, 0x22, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x14, 0x75, 0x2f, 
+    0x82, 0x12, 0x73, 0x35, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x62, 0x2b, 
+    0x89, 0x54, 0x22, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x14, 0x75, 0x2f, 0x83, 0x12, 0x73, 0x35, 
+    0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x62, 0x6b, 0x89, 0x54, 0x22, 0x09, 
+    0xb1, 0x00, 0x08, 0x20, 0xe0, 0x14, 0x75, 0x2f, 0x84, 0x12, 0x73, 0x35, 0x54, 0x3e, 0x0a, 0x5b, 
+    0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x62, 0xab, 0x89, 0x54, 0x22, 0x09, 0xb1, 0x00, 0x08, 0x20, 
+    0xe0, 0x14, 0x75, 0x2f, 0x85, 0x12, 0x73, 0x35, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 
+    0x69, 0x52, 0x62, 0xeb, 0x89, 0x54, 0x22, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x14, 0x75, 0x2f, 
+    0x86, 0x12, 0x73, 0x35, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 0x2b, 
+    0x89, 0x54, 0x22, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x14, 0x75, 0x2f, 0x87, 0x12, 0x73, 0x35, 
+    0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 0x6b, 0x89, 0x54, 0x22, 0x10, 
+    0x08, 0x01, 0x22, 0x20, 0x28, 0x03, 0xd2, 0x08, 0x22, 0x75, 0x2f, 0xa0, 0x12, 0x73, 0x35, 0x7e, 
+    0x14, 0x80, 0x00, 0x80, 0x06, 0x20, 0x28, 0x03, 0xd2, 0x08, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x49, 0x45, 0x30, 0x30, 0x06, 0x20, 0xe6, 
+    0x4f, 0xd2, 0x08, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x60, 0x7e, 0x37, 0x01, 0x79, 0x7e, 0x27, 0x01, 
+    0x99, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x32, 0x7a, 0x05, 0x32, 0x7a, 0x37, 0x01, 
+    0x79, 0x7e, 0x37, 0x01, 0x59, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x08, 0x2c, 0x38, 0x68, 0x7a, 
+    0x47, 0x01, 0x59, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x12, 
+    0x69, 0xf0, 0x10, 0x60, 0xc4, 0x22, 0xc2, 0x60, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 
+    0x7e, 0x27, 0x01, 0x79, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x99, 0x28, 0x04, 
+    0x7e, 0x27, 0x01, 0x99, 0x7e, 0x37, 0x01, 0x79, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x32, 0x7a, 
+    0x05, 0x32, 0x7a, 0x37, 0x01, 0x79, 0x7e, 0x37, 0x01, 0x59, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x08, 0x2c, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x59, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 
+    0x2f, 0x12, 0x73, 0x35, 0x02, 0x69, 0xf0, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 
+    0x12, 0x73, 0x35, 0x9e, 0x44, 0x08, 0x2d, 0x9d, 0x24, 0x12, 0x69, 0xf0, 0x7e, 0x34, 0x04, 0x2d, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x59, 0x12, 0x69, 0xf0, 0xbe, 0x25, 0x20, 0x78, 0x03, 
+    0x02, 0x46, 0xc2, 0x22, 0xd2, 0x08, 0x7e, 0x04, 0x04, 0x2d, 0x7a, 0x07, 0x01, 0x59, 0x7a, 0x07, 
+    0x01, 0x69, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x75, 0x2f, 0x00, 0x12, 0x73, 0x35, 0x22, 0x75, 
+    0x2f, 0x92, 0x12, 0x73, 0x35, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 
+    0xb8, 0x78, 0x68, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xa9, 0x2e, 0x24, 0x00, 0x02, 0x2d, 
+    0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x34, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 
+    0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x28, 0x2c, 0x38, 
+    0x3c, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x00, 0x00, 0x2e, 0x27, 0x01, 0xa9, 0x1b, 0x38, 0x20, 
+    0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x02, 0x6a, 0x63, 0x75, 0x2f, 0x99, 0x12, 0x73, 
+    0x35, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x38, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 
+    0x12, 0x73, 0x35, 0x9e, 0x44, 0x28, 0x2d, 0x9d, 0x24, 0x7e, 0x64, 0x00, 0x00, 0x2e, 0x67, 0x01, 
+    0xa9, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x6a, 0x63, 0x7e, 
+    0x34, 0x24, 0x2d, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x6a, 0x63, 0x7a, 0x39, 
+    0xc0, 0x7e, 0x34, 0x24, 0x2d, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 
+    0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x00, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 
+    0x35, 0x75, 0x2f, 0x93, 0x12, 0x73, 0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 0xbd, 0x04, 0x68, 
+    0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 
+    0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 
+    0x7e, 0x04, 0x24, 0x2d, 0x80, 0x28, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0x2a, 0x7e, 0x04, 0x24, 0x2d, 
+    0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 
+    0x01, 0xc9, 0x7e, 0x44, 0x28, 0x2d, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 
+    0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 
+    0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 
+    0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x48, 0x1e, 0x75, 0x2f, 
+    0x99, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x38, 
+    0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 0xda, 0xb8, 
+    0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x48, 0x1e, 0xda, 0xb8, 0x02, 0x49, 
+    0x45, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x73, 0x35, 0xf5, 0x2f, 
+    0x12, 0x73, 0x35, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 
+    0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x50, 
+    0x80, 0x02, 0xc2, 0x50, 0x12, 0x42, 0xbd, 0x02, 0x61, 0x13, 0x75, 0x2f, 0x91, 0x12, 0x73, 0x35, 
+    0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x73, 0x35, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 
+    0xa0, 0x80, 0x02, 0x61, 0x13, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x61, 0x13, 
+    0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 
+    0x12, 0x61, 0x36, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x48, 0x72, 0x75, 0x2f, 
+    0x95, 0x12, 0x73, 0x35, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x73, 0x35, 0x22, 0x10, 0x09, 0x01, 0x22, 
+    0x20, 0x29, 0x03, 0xd2, 0x09, 0x22, 0x75, 0x2f, 0xa1, 0x12, 0x73, 0x35, 0x7e, 0x14, 0x81, 0x00, 
+    0x80, 0x06, 0x20, 0x29, 0x03, 0xd2, 0x09, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 
+    0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x4c, 0x72, 0x30, 0x31, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x09, 
+    0x22, 0x30, 0xe6, 0x02, 0xd2, 0x61, 0x7e, 0x37, 0x01, 0x7b, 0x7e, 0x27, 0x01, 0x9b, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x34, 0x7a, 0x05, 0x34, 0x7a, 0x37, 0x01, 0x7b, 0x7e, 0x37, 
+    0x01, 0x5b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0c, 0x2c, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x5b, 
+    0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x12, 0x69, 0xf0, 0x10, 
+    0x61, 0xc4, 0x22, 0xc2, 0x61, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x7b, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x9b, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0x9b, 0x7e, 0x37, 0x01, 0x7b, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x34, 0x7a, 0x05, 0x34, 0x7a, 
+    0x37, 0x01, 0x7b, 0x7e, 0x37, 0x01, 0x5b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0c, 0x2c, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x5b, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 
+    0x35, 0x02, 0x69, 0xf0, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 
+    0x9e, 0x44, 0x0c, 0x2d, 0x9d, 0x24, 0x12, 0x69, 0xf0, 0x7e, 0x34, 0x08, 0x2d, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x5b, 0x12, 0x69, 0xf0, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x49, 0xef, 
+    0x22, 0xd2, 0x09, 0x7e, 0x04, 0x08, 0x2d, 0x7a, 0x07, 0x01, 0x5b, 0x7a, 0x07, 0x01, 0x6b, 0x75, 
+    0x2f, 0x94, 0x12, 0x73, 0x35, 0x75, 0x2f, 0x00, 0x12, 0x73, 0x35, 0x22, 0x75, 0x2f, 0x92, 0x12, 
+    0x73, 0x35, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x68, 
+    0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xab, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x34, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 
+    0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x28, 0x2c, 0x38, 0x3c, 0x7a, 0x47, 
+    0x01, 0xc9, 0x7e, 0x24, 0x01, 0x00, 0x2e, 0x27, 0x01, 0xab, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x2f, 0x12, 0x73, 0x35, 0x02, 0x6a, 0x63, 0x75, 0x2f, 0x99, 0x12, 0x73, 0x35, 0x09, 0xb1, 
+    0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 
+    0x9e, 0x44, 0x28, 0x2d, 0x9d, 0x24, 0x7e, 0x64, 0x01, 0x00, 0x2e, 0x67, 0x01, 0xab, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x6a, 0x63, 0x7e, 0x34, 0x24, 0x2d, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x6a, 0x63, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x24, 0x2d, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x01, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 
+    0x93, 0x12, 0x73, 0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 
+    0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 
+    0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x24, 
+    0x2d, 0x80, 0x28, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0x2a, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0xcf, 0x7e, 
+    0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 
+    0x44, 0x28, 0x2d, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x4b, 0x4b, 0x75, 0x2f, 0x99, 0x12, 0x73, 
+    0x35, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4b, 0x4b, 0xda, 0xb8, 0x02, 0x4c, 0x72, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x73, 0x35, 0xf5, 0x2f, 0x12, 0x73, 0x35, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x59, 
+    0x80, 0x02, 0xc2, 0x59, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x51, 0x80, 0x02, 0xc2, 
+    0x51, 0x12, 0x42, 0xd4, 0x02, 0x61, 0x13, 0x75, 0x2f, 0x91, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 
+    0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x73, 0x35, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 
+    0x61, 0x13, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x61, 0x13, 0xca, 0xb8, 0x5e, 
+    0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x61, 0x36, 
+    0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4b, 0x9f, 0x75, 0x2f, 0x95, 0x12, 0x73, 
+    0x35, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x73, 0x35, 0x22, 0x10, 0x0a, 0x01, 0x22, 0x20, 0x2a, 0x03, 
+    0xd2, 0x0a, 0x22, 0x75, 0x2f, 0xa2, 0x12, 0x73, 0x35, 0x7e, 0x14, 0x82, 0x00, 0x80, 0x06, 0x20, 
+    0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 
+    0x68, 0x03, 0x12, 0x4f, 0x9f, 0x30, 0x32, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0a, 0x22, 0x30, 0xe6, 
+    0x02, 0xd2, 0x62, 0x7e, 0x37, 0x01, 0x7d, 0x7e, 0x27, 0x01, 0x9d, 0x9d, 0x32, 0x40, 0x31, 0x7d, 
+    0x02, 0x2e, 0x05, 0x36, 0x7a, 0x05, 0x36, 0x7a, 0x37, 0x01, 0x7d, 0x7e, 0x37, 0x01, 0x5d, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x10, 0x2c, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x5d, 0x75, 0x2f, 0x94, 
+    0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x12, 0x69, 0xf0, 0x10, 0x62, 0xc4, 0x22, 
+    0xc2, 0x62, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x7d, 0xbe, 0x24, 
+    0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x9d, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x9d, 0x7e, 0x37, 
+    0x01, 0x7d, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x36, 0x7a, 0x05, 0x36, 0x7a, 0x37, 0x01, 0x7d, 
+    0x7e, 0x37, 0x01, 0x5d, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x10, 0x2c, 0x38, 0x13, 0x7a, 0x47, 
+    0x01, 0x5d, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x02, 0x69, 
+    0xf0, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x9e, 0x44, 0x10, 
+    0x2d, 0x9d, 0x24, 0x12, 0x69, 0xf0, 0x7e, 0x34, 0x0c, 0x2d, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 
+    0x01, 0x5d, 0x12, 0x69, 0xf0, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4d, 0x1c, 0x22, 0xd2, 0x0a, 
+    0x7e, 0x04, 0x0c, 0x2d, 0x7a, 0x07, 0x01, 0x5d, 0x7a, 0x07, 0x01, 0x6d, 0x75, 0x2f, 0x94, 0x12, 
+    0x73, 0x35, 0x75, 0x2f, 0x00, 0x12, 0x73, 0x35, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x73, 0x35, 0xd2, 
+    0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x68, 0x7e, 0x37, 0x01, 
+    0xcb, 0x7e, 0x27, 0x01, 0xad, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 
+    0x34, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 
+    0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x28, 0x2c, 0x38, 0x3c, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 
+    0x24, 0x02, 0x00, 0x2e, 0x27, 0x01, 0xad, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 
+    0x73, 0x35, 0x02, 0x6a, 0x63, 0x75, 0x2f, 0x99, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 0x04, 0x54, 
+    0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 
+    0x00, 0x10, 0xd2, 0x12, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x9e, 0x44, 0x28, 
+    0x2d, 0x9d, 0x24, 0x7e, 0x64, 0x02, 0x00, 0x2e, 0x67, 0x01, 0xad, 0x9e, 0x24, 0x00, 0x02, 0x40, 
+    0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x6a, 0x63, 0x7e, 0x34, 0x24, 0x2d, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x6a, 0x63, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x24, 0x2d, 0x7a, 
+    0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 
+    0x23, 0x44, 0x02, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x73, 
+    0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 
+    0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 
+    0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0x28, 
+    0x7e, 0x04, 0x24, 0x2d, 0x80, 0x2a, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 
+    0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x28, 0x2d, 
+    0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 
+    0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 
+    0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x4e, 0x78, 0x75, 0x2f, 0x99, 0x12, 0x73, 0x35, 0x09, 0xb1, 
+    0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 
+    0x07, 0xca, 0xb8, 0x12, 0x4e, 0x78, 0xda, 0xb8, 0x02, 0x4f, 0x9f, 0x09, 0xb1, 0x00, 0x18, 0x7e, 
+    0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x73, 0x35, 0xf5, 0x2f, 0x12, 0x73, 0x35, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 
+    0x5a, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x52, 0x80, 0x02, 0xc2, 0x52, 0x12, 0x42, 
+    0xeb, 0x02, 0x61, 0x13, 0x75, 0x2f, 0x91, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 
+    0x2f, 0x12, 0x73, 0x35, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x61, 0x13, 0xd2, 
+    0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x61, 0x13, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 
+    0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x61, 0x36, 0x09, 0xb1, 0x00, 
+    0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4e, 0xcc, 0x75, 0x2f, 0x95, 0x12, 0x73, 0x35, 0x22, 0x75, 
+    0x2f, 0x96, 0x12, 0x73, 0x35, 0x22, 0x10, 0x0b, 0x01, 0x22, 0x20, 0x2b, 0x03, 0xd2, 0x0b, 0x22, 
+    0x75, 0x2f, 0xa3, 0x12, 0x73, 0x35, 0x7e, 0x14, 0x83, 0x00, 0x80, 0x06, 0x20, 0x2b, 0x03, 0xd2, 
+    0x0b, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 
+    0x52, 0xcc, 0x30, 0x33, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0b, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x63, 
+    0x7e, 0x37, 0x01, 0x7f, 0x7e, 0x27, 0x01, 0x9f, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 
+    0x38, 0x7a, 0x05, 0x38, 0x7a, 0x37, 0x01, 0x7f, 0x7e, 0x37, 0x01, 0x5f, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x14, 0x2c, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x5f, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 
+    0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x12, 0x69, 0xf0, 0x10, 0x63, 0xc4, 0x22, 0xc2, 0x63, 0x2d, 
+    0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x7f, 0xbe, 0x24, 0x00, 0x00, 0x68, 
+    0x6a, 0xbe, 0x27, 0x01, 0x9f, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x9f, 0x7e, 0x37, 0x01, 0x7f, 0x9d, 
+    0x32, 0x7d, 0x02, 0x2e, 0x05, 0x38, 0x7a, 0x05, 0x38, 0x7a, 0x37, 0x01, 0x7f, 0x7e, 0x37, 0x01, 
+    0x5f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x14, 0x2c, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x5f, 0x75, 
+    0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x02, 0x69, 0xf0, 0x75, 0x2f, 
+    0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x9e, 0x44, 0x14, 0x2d, 0x9d, 0x24, 
+    0x12, 0x69, 0xf0, 0x7e, 0x34, 0x10, 0x2d, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5f, 0x12, 
+    0x69, 0xf0, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x50, 0x49, 0x22, 0xd2, 0x0b, 0x7e, 0x04, 0x10, 
+    0x2d, 0x7a, 0x07, 0x01, 0x5f, 0x7a, 0x07, 0x01, 0x6f, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x75, 
+    0x2f, 0x00, 0x12, 0x73, 0x35, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x73, 0x35, 0xd2, 0x04, 0x09, 0xb1, 
+    0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x68, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 
+    0x01, 0xaf, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x34, 0x7d, 0x02, 
+    0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 
+    0x2d, 0x42, 0xbe, 0x44, 0x28, 0x2c, 0x38, 0x3c, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x03, 0x00, 
+    0x2e, 0x27, 0x01, 0xaf, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x02, 
+    0x6a, 0x63, 0x75, 0x2f, 0x99, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 
+    0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 
+    0x13, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x9e, 0x44, 0x28, 0x2d, 0x9d, 0x24, 
+    0x7e, 0x64, 0x03, 0x00, 0x2e, 0x67, 0x01, 0xaf, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 
+    0x60, 0x0b, 0x35, 0x12, 0x6a, 0x63, 0x7e, 0x34, 0x24, 0x2d, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 
+    0x01, 0xc9, 0x02, 0x6a, 0x63, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x24, 0x2d, 0x7a, 0x39, 0xd0, 0x0b, 
+    0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x03, 
+    0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x73, 0x35, 0x7a, 0x71, 
+    0x2f, 0x12, 0x73, 0x35, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 
+    0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 
+    0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0x28, 0x7e, 0x04, 0x24, 
+    0x2d, 0x80, 0x2a, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 
+    0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x28, 0x2d, 0x7d, 0x60, 0x0b, 
+    0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 
+    0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 
+    0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 
+    0x78, 0xe7, 0x02, 0x51, 0xa5, 0x75, 0x2f, 0x99, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 0x04, 0x54, 
+    0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 
+    0x00, 0x10, 0xd2, 0x13, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 
+    0x12, 0x51, 0xa5, 0xda, 0xb8, 0x02, 0x52, 0xcc, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 
+    0x2f, 0x90, 0x12, 0x73, 0x35, 0xf5, 0x2f, 0x12, 0x73, 0x35, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 
+    0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5b, 0x80, 0x02, 0xc2, 0x5b, 0xa5, 0xfd, 
+    0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x53, 0x80, 0x02, 0xc2, 0x53, 0x12, 0x43, 0x02, 0x02, 0x61, 
+    0x13, 0x75, 0x2f, 0x91, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x73, 
+    0x35, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x61, 0x13, 0xd2, 0x04, 0x30, 0xe1, 
+    0x06, 0x7e, 0xa0, 0x80, 0x12, 0x61, 0x13, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 
+    0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x61, 0x36, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 
+    0xdb, 0x22, 0x02, 0x51, 0xf9, 0x75, 0x2f, 0x95, 0x12, 0x73, 0x35, 0x22, 0x75, 0x2f, 0x96, 0x12, 
+    0x73, 0x35, 0x22, 0x10, 0x0c, 0x01, 0x22, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x75, 0x2f, 0xa4, 
+    0x12, 0x73, 0x35, 0x7e, 0x14, 0x84, 0x00, 0x80, 0x06, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x55, 0xf9, 0x30, 
+    0x34, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0c, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x64, 0x7e, 0x37, 0x01, 
+    0x81, 0x7e, 0x27, 0x01, 0xa1, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3a, 0x7a, 0x05, 
+    0x3a, 0x7a, 0x37, 0x01, 0x81, 0x7e, 0x37, 0x01, 0x61, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x18, 
+    0x2c, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x61, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 
+    0x12, 0x73, 0x35, 0x12, 0x69, 0xf0, 0x10, 0x64, 0xc4, 0x22, 0xc2, 0x64, 0x2d, 0x23, 0x68, 0x78, 
+    0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x81, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 
+    0x01, 0xa1, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa1, 0x7e, 0x37, 0x01, 0x81, 0x9d, 0x32, 0x7d, 0x02, 
+    0x2e, 0x05, 0x3a, 0x7a, 0x05, 0x3a, 0x7a, 0x37, 0x01, 0x81, 0x7e, 0x37, 0x01, 0x61, 0x7d, 0x43, 
+    0x2d, 0x42, 0xbe, 0x44, 0x18, 0x2c, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x61, 0x75, 0x2f, 0x94, 0x12, 
+    0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x02, 0x69, 0xf0, 0x75, 0x2f, 0x94, 0x12, 0x73, 
+    0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x9e, 0x44, 0x18, 0x2d, 0x9d, 0x24, 0x12, 0x69, 0xf0, 
+    0x7e, 0x34, 0x14, 0x2d, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x61, 0x12, 0x69, 0xf0, 0xbe, 
+    0x25, 0x20, 0x78, 0x03, 0x02, 0x53, 0x76, 0x22, 0xd2, 0x0c, 0x7e, 0x04, 0x14, 0x2d, 0x7a, 0x07, 
+    0x01, 0x61, 0x7a, 0x07, 0x01, 0x71, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x75, 0x2f, 0x00, 0x12, 
+    0x73, 0x35, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x73, 0x35, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x68, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb1, 0x2e, 
+    0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x34, 0x7d, 0x02, 0x2e, 0x05, 0x30, 
+    0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 
+    0x44, 0x28, 0x2c, 0x38, 0x3c, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x04, 0x00, 0x2e, 0x27, 0x01, 
+    0xb1, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x02, 0x6a, 0x63, 0x75, 
+    0x2f, 0x99, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 
+    0x3c, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x14, 0x22, 0x80, 
+    0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x9e, 0x44, 0x28, 0x2d, 0x9d, 0x24, 0x7e, 0x64, 0x04, 
+    0x00, 0x2e, 0x67, 0x01, 0xb1, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 
+    0x12, 0x6a, 0x63, 0x7e, 0x34, 0x24, 0x2d, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 
+    0x6a, 0x63, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x24, 0x2d, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 
+    0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x04, 0x7a, 0x69, 0xb0, 
+    0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x73, 0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 
+    0x35, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 
+    0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0x28, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0x2a, 
+    0x7e, 0x04, 0x24, 0x2d, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 
+    0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x28, 0x2d, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 
+    0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 
+    0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 
+    0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 
+    0x54, 0xd2, 0x75, 0x2f, 0x99, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 
+    0x00, 0x04, 0x30, 0x3c, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 
+    0x14, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x54, 0xd2, 
+    0xda, 0xb8, 0x02, 0x55, 0xf9, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 
+    0x73, 0x35, 0xf5, 0x2f, 0x12, 0x73, 0x35, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 
+    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
+    0x68, 0x04, 0xd2, 0x54, 0x80, 0x02, 0xc2, 0x54, 0x12, 0x43, 0x19, 0x02, 0x61, 0x13, 0x75, 0x2f, 
+    0x91, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x73, 0x35, 0x20, 0xe0, 
+    0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x61, 0x13, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 
+    0x80, 0x12, 0x61, 0x13, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 
+    0x09, 0x61, 0x00, 0x00, 0x12, 0x61, 0x36, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 
+    0x55, 0x26, 0x75, 0x2f, 0x95, 0x12, 0x73, 0x35, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x73, 0x35, 0x22, 
+    0x10, 0x0d, 0x01, 0x22, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 0x22, 0x75, 0x2f, 0xa5, 0x12, 0x73, 0x35, 
+    0x7e, 0x14, 0x85, 0x00, 0x80, 0x06, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 0x22, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x59, 0x26, 0x30, 0x35, 0x06, 0x20, 
+    0xe6, 0x4f, 0xd2, 0x0d, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x65, 0x7e, 0x37, 0x01, 0x83, 0x7e, 0x27, 
+    0x01, 0xa3, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3c, 0x7a, 0x05, 0x3c, 0x7a, 0x37, 
+    0x01, 0x83, 0x7e, 0x37, 0x01, 0x63, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1c, 0x2c, 0x38, 0x68, 
+    0x7a, 0x47, 0x01, 0x63, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 
+    0x12, 0x69, 0xf0, 0x10, 0x65, 0xc4, 0x22, 0xc2, 0x65, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 
+    0x1a, 0x7e, 0x27, 0x01, 0x83, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa3, 0x28, 
+    0x04, 0x7e, 0x27, 0x01, 0xa3, 0x7e, 0x37, 0x01, 0x83, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x3c, 
+    0x7a, 0x05, 0x3c, 0x7a, 0x37, 0x01, 0x83, 0x7e, 0x37, 0x01, 0x63, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 
+    0x44, 0x1c, 0x2c, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x63, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 
+    0x51, 0x2f, 0x12, 0x73, 0x35, 0x02, 0x69, 0xf0, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 
+    0x2f, 0x12, 0x73, 0x35, 0x9e, 0x44, 0x1c, 0x2d, 0x9d, 0x24, 0x12, 0x69, 0xf0, 0x7e, 0x34, 0x18, 
+    0x2d, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x63, 0x12, 0x69, 0xf0, 0xbe, 0x25, 0x20, 0x78, 
+    0x03, 0x02, 0x56, 0xa3, 0x22, 0xd2, 0x0d, 0x7e, 0x04, 0x18, 0x2d, 0x7a, 0x07, 0x01, 0x63, 0x7a, 
+    0x07, 0x01, 0x73, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x75, 0x2f, 0x00, 0x12, 0x73, 0x35, 0x22, 
+    0x75, 0x2f, 0x92, 0x12, 0x73, 0x35, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 
+    0xda, 0xb8, 0x78, 0x68, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb3, 0x2e, 0x24, 0x00, 0x02, 
+    0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x34, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 
+    0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x28, 0x2c, 
+    0x38, 0x3c, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x05, 0x00, 0x2e, 0x27, 0x01, 0xb3, 0x1b, 0x38, 
+    0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x02, 0x6a, 0x63, 0x75, 0x2f, 0x99, 0x12, 
+    0x73, 0x35, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 
+    0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0x80, 0x7f, 0x7a, 0x51, 
+    0x2f, 0x12, 0x73, 0x35, 0x9e, 0x44, 0x28, 0x2d, 0x9d, 0x24, 0x7e, 0x64, 0x05, 0x00, 0x2e, 0x67, 
+    0x01, 0xb3, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x6a, 0x63, 
+    0x7e, 0x34, 0x24, 0x2d, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x6a, 0x63, 0x7a, 
+    0x39, 0xc0, 0x7e, 0x34, 0x24, 0x2d, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 
+    0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x05, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 
+    0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x73, 0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 0xbd, 0x04, 
+    0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 
+    0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 
+    0x22, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0x28, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0x2a, 0x7e, 0x04, 0x24, 
+    0x2d, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 
+    0x07, 0x01, 0xc9, 0x7e, 0x44, 0x28, 0x2d, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 
+    0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 
+    0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 
+    0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x57, 0xff, 0x75, 
+    0x2f, 0x99, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 
+    0x3d, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0xda, 
+    0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x57, 0xff, 0xda, 0xb8, 0x02, 
+    0x59, 0x26, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x73, 0x35, 0xf5, 
+    0x2f, 0x12, 0x73, 0x35, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 
+    0x68, 0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 
+    0x55, 0x80, 0x02, 0xc2, 0x55, 0x12, 0x43, 0x30, 0x02, 0x61, 0x13, 0x75, 0x2f, 0x91, 0x12, 0x73, 
+    0x35, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x73, 0x35, 0x20, 0xe0, 0x08, 0xd2, 0x04, 
+    0x7e, 0xa0, 0x80, 0x02, 0x61, 0x13, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x61, 
+    0x13, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 
+    0x00, 0x12, 0x61, 0x36, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x58, 0x53, 0x75, 
+    0x2f, 0x95, 0x12, 0x73, 0x35, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x73, 0x35, 0x22, 0x10, 0x0e, 0x01, 
+    0x22, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 0x75, 0x2f, 0xa6, 0x12, 0x73, 0x35, 0x7e, 0x14, 0x86, 
+    0x00, 0x80, 0x06, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 
+    0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5c, 0x53, 0x30, 0x36, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 
+    0x0e, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x66, 0x7e, 0x37, 0x01, 0x85, 0x7e, 0x27, 0x01, 0xa5, 0x9d, 
+    0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3e, 0x7a, 0x05, 0x3e, 0x7a, 0x37, 0x01, 0x85, 0x7e, 
+    0x37, 0x01, 0x65, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x20, 0x2c, 0x38, 0x68, 0x7a, 0x47, 0x01, 
+    0x65, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x12, 0x69, 0xf0, 
+    0x10, 0x66, 0xc4, 0x22, 0xc2, 0x66, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 
+    0x01, 0x85, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa5, 0x28, 0x04, 0x7e, 0x27, 
+    0x01, 0xa5, 0x7e, 0x37, 0x01, 0x85, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x3e, 0x7a, 0x05, 0x3e, 
+    0x7a, 0x37, 0x01, 0x85, 0x7e, 0x37, 0x01, 0x65, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x20, 0x2c, 
+    0x38, 0x13, 0x7a, 0x47, 0x01, 0x65, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 
+    0x73, 0x35, 0x02, 0x69, 0xf0, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 
+    0x35, 0x9e, 0x44, 0x20, 0x2d, 0x9d, 0x24, 0x12, 0x69, 0xf0, 0x7e, 0x34, 0x1c, 0x2d, 0x7d, 0x24, 
+    0x2d, 0x43, 0x7a, 0x47, 0x01, 0x65, 0x12, 0x69, 0xf0, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x59, 
+    0xd0, 0x22, 0xd2, 0x0e, 0x7e, 0x04, 0x1c, 0x2d, 0x7a, 0x07, 0x01, 0x65, 0x7a, 0x07, 0x01, 0x75, 
+    0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x75, 0x2f, 0x00, 0x12, 0x73, 0x35, 0x22, 0x75, 0x2f, 0x92, 
+    0x12, 0x73, 0x35, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 
+    0x68, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb5, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 
+    0x34, 0x04, 0x00, 0x38, 0x34, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 
+    0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x28, 0x2c, 0x38, 0x3c, 0x7a, 
+    0x47, 0x01, 0xc9, 0x7e, 0x24, 0x06, 0x00, 0x2e, 0x27, 0x01, 0xb5, 0x1b, 0x38, 0x20, 0x0b, 0x35, 
+    0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x02, 0x6a, 0x63, 0x75, 0x2f, 0x99, 0x12, 0x73, 0x35, 0x09, 
+    0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 0x10, 
+    0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x73, 
+    0x35, 0x9e, 0x44, 0x28, 0x2d, 0x9d, 0x24, 0x7e, 0x64, 0x06, 0x00, 0x2e, 0x67, 0x01, 0xb5, 0x9e, 
+    0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x6a, 0x63, 0x7e, 0x34, 0x24, 
+    0x2d, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x6a, 0x63, 0x7a, 0x39, 0xc0, 0x7e, 
+    0x34, 0x24, 0x2d, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 
+    0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x06, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 
+    0x2f, 0x93, 0x12, 0x73, 0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 
+    0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 
+    0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 
+    0x24, 0x2d, 0x80, 0x28, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0x2a, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0xcf, 
+    0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 
+    0x7e, 0x44, 0x28, 0x2d, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 
+    0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 
+    0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 
+    0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5b, 0x2c, 0x75, 0x2f, 0x99, 0x12, 
+    0x73, 0x35, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 0x09, 
+    0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 0xda, 0xb8, 0x30, 0xe0, 
+    0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5b, 0x2c, 0xda, 0xb8, 0x02, 0x5c, 0x53, 0x09, 
+    0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x73, 0x35, 0xf5, 0x2f, 0x12, 0x73, 
+    0x35, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 
+    0x5e, 0x80, 0x02, 0xc2, 0x5e, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x56, 0x80, 0x02, 
+    0xc2, 0x56, 0x12, 0x43, 0x47, 0x02, 0x61, 0x13, 0x75, 0x2f, 0x91, 0x12, 0x73, 0x35, 0x09, 0xb1, 
+    0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x73, 0x35, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 
+    0x02, 0x61, 0x13, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x61, 0x13, 0xca, 0xb8, 
+    0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x61, 
+    0x36, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5b, 0x80, 0x75, 0x2f, 0x95, 0x12, 
+    0x73, 0x35, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x73, 0x35, 0x22, 0x10, 0x0f, 0x01, 0x22, 0x20, 0x2f, 
+    0x03, 0xd2, 0x0f, 0x22, 0x75, 0x2f, 0xa7, 0x12, 0x73, 0x35, 0x7e, 0x14, 0x87, 0x00, 0x80, 0x06, 
+    0x20, 0x2f, 0x03, 0xd2, 0x0f, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 
+    0xb8, 0x68, 0x03, 0x12, 0x5f, 0x80, 0x30, 0x37, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0f, 0x22, 0x30, 
+    0xe6, 0x02, 0xd2, 0x67, 0x7e, 0x37, 0x01, 0x87, 0x7e, 0x27, 0x01, 0xa7, 0x9d, 0x32, 0x40, 0x31, 
+    0x7d, 0x02, 0x2e, 0x05, 0x40, 0x7a, 0x05, 0x40, 0x7a, 0x37, 0x01, 0x87, 0x7e, 0x37, 0x01, 0x67, 
+    0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x24, 0x2c, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x67, 0x75, 0x2f, 
+    0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x12, 0x69, 0xf0, 0x10, 0x67, 0xc4, 
+    0x22, 0xc2, 0x67, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x87, 0xbe, 
+    0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa7, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa7, 0x7e, 
+    0x37, 0x01, 0x87, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x40, 0x7a, 0x05, 0x40, 0x7a, 0x37, 0x01, 
+    0x87, 0x7e, 0x37, 0x01, 0x67, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x24, 0x2c, 0x38, 0x13, 0x7a, 
+    0x47, 0x01, 0x67, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x02, 
+    0x69, 0xf0, 0x75, 0x2f, 0x94, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x9e, 0x44, 
+    0x24, 0x2d, 0x9d, 0x24, 0x12, 0x69, 0xf0, 0x7e, 0x34, 0x20, 0x2d, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 
+    0x47, 0x01, 0x67, 0x12, 0x69, 0xf0, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5c, 0xfd, 0x22, 0xd2, 
+    0x0f, 0x7e, 0x04, 0x20, 0x2d, 0x7a, 0x07, 0x01, 0x67, 0x7a, 0x07, 0x01, 0x77, 0x75, 0x2f, 0x94, 
+    0x12, 0x73, 0x35, 0x75, 0x2f, 0x00, 0x12, 0x73, 0x35, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x73, 0x35, 
+    0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x68, 0x7e, 0x37, 
+    0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb7, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 
+    0x38, 0x34, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 
+    0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x28, 0x2c, 0x38, 0x3c, 0x7a, 0x47, 0x01, 0xc9, 
+    0x7e, 0x24, 0x07, 0x00, 0x2e, 0x27, 0x01, 0xb7, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 
+    0x12, 0x73, 0x35, 0x02, 0x6a, 0x63, 0x75, 0x2f, 0x99, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 0x04, 
+    0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 
+    0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x73, 0x35, 0x9e, 0x44, 
+    0x28, 0x2d, 0x9d, 0x24, 0x7e, 0x64, 0x07, 0x00, 0x2e, 0x67, 0x01, 0xb7, 0x9e, 0x24, 0x00, 0x02, 
+    0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x6a, 0x63, 0x7e, 0x34, 0x24, 0x2d, 0x7d, 0x24, 
+    0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x6a, 0x63, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x24, 0x2d, 
+    0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 
+    0x23, 0x23, 0x44, 0x07, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 
+    0x73, 0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 
+    0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 
+    0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x24, 0x2d, 0x80, 
+    0x28, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0x2a, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0xcf, 0x7e, 0x07, 0x01, 
+    0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x28, 
+    0x2d, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 
+    0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 
+    0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 
+    0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5e, 0x59, 0x75, 0x2f, 0x99, 0x12, 0x73, 0x35, 0x09, 
+    0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 
+    0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 
+    0x68, 0x07, 0xca, 0xb8, 0x12, 0x5e, 0x59, 0xda, 0xb8, 0x02, 0x5f, 0x80, 0x09, 0xb1, 0x00, 0x18, 
+    0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x73, 0x35, 0xf5, 0x2f, 0x12, 0x73, 0x35, 0xa5, 0xfd, 
+    0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 
+    0xc2, 0x5f, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x57, 0x80, 0x02, 0xc2, 0x57, 0x12, 
+    0x43, 0x5e, 0x02, 0x61, 0x13, 0x75, 0x2f, 0x91, 0x12, 0x73, 0x35, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x2f, 0x12, 0x73, 0x35, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x61, 0x13, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x61, 0x13, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x61, 0x36, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5e, 0xad, 0x75, 0x2f, 0x95, 0x12, 0x73, 0x35, 0x22, 
+    0x75, 0x2f, 0x96, 0x12, 0x73, 0x35, 0x22, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 
+    0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x50, 0x80, 0x02, 0xc2, 0x50, 0x02, 0x60, 0xff, 
+    0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 
+    0x20, 0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 
+    0xd2, 0x51, 0x80, 0x02, 0xc2, 0x51, 0x02, 0x60, 0xff, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 
+    0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 
+    0xc2, 0x5a, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x52, 0x80, 0x02, 0xc2, 0x52, 0x02, 
+    0x60, 0xff, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 
+    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5b, 0x80, 0x02, 0xc2, 0x5b, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
+    0x68, 0x04, 0xd2, 0x53, 0x80, 0x02, 0xc2, 0x53, 0x02, 0x60, 0xff, 0x7c, 0x02, 0x7e, 0x14, 0x80, 
+    0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5c, 
+    0x80, 0x02, 0xc2, 0x5c, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x54, 0x80, 0x02, 0xc2, 
+    0x54, 0x02, 0x60, 0xff, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x80, 0x68, 0x04, 0xd2, 0x55, 0x80, 0x02, 0xc2, 0x55, 0x02, 0x60, 0xff, 0x7c, 0x02, 0x7e, 
+    0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 
+    0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x56, 0x80, 
+    0x02, 0xc2, 0x56, 0x02, 0x60, 0xff, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 
+    0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0xa5, 
+    0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x57, 0x80, 0x02, 0xc2, 0x57, 0x02, 0x60, 0xff, 0x54, 
+    0xf0, 0xc4, 0xa5, 0xff, 0xc4, 0xa5, 0x4f, 0x75, 0x2f, 0x90, 0x12, 0x73, 0x35, 0xf5, 0x2f, 0x12, 
+    0x73, 0x35, 0x22, 0xca, 0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x2c, 0x2d, 0xca, 0x79, 
+    0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x02, 0x7e, 
+    0x64, 0x00, 0x02, 0x02, 0x61, 0x5e, 0xca, 0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x2c, 
+    0x2d, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0x7a, 0x79, 0x60, 
+    0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x03, 0x7e, 0x64, 0x00, 0x03, 0x02, 0x61, 0x5e, 0xd2, 0x04, 
+    0x7e, 0x27, 0x01, 0xcb, 0x2d, 0x26, 0xbe, 0x24, 0x04, 0x00, 0x38, 0x2e, 0x7e, 0x07, 0x01, 0xc9, 
+    0x7e, 0x44, 0x28, 0x2d, 0x7e, 0x79, 0xa0, 0x7a, 0x09, 0xa0, 0x0b, 0x04, 0x0b, 0x74, 0xbd, 0x04, 
+    0x68, 0x23, 0xa5, 0xdb, 0xef, 0x7a, 0x27, 0x01, 0xcb, 0x7e, 0x25, 0x30, 0x2d, 0x26, 0x7a, 0x25, 
+    0x30, 0x7a, 0x07, 0x01, 0xc9, 0xda, 0x19, 0xc2, 0xd7, 0x22, 0x75, 0x2f, 0x9a, 0x12, 0x73, 0x35, 
+    0xda, 0x19, 0xd2, 0xd7, 0x22, 0x7e, 0x04, 0x24, 0x2d, 0x80, 0xd7, 0x48, 0xf1, 0x46, 0x65, 0x47, 
+    0x5f, 0x49, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x48, 0x56, 0x45, 0x2a, 0x49, 0x6e, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x49, 0x75, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x4c, 0x1e, 0x49, 0x92, 0x4a, 
+    0x8c, 0x4c, 0x57, 0x45, 0x2a, 0x45, 0x2a, 0x4b, 0x83, 0x45, 0x2a, 0x4c, 0x9b, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x4c, 0xa2, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x4f, 0x4b, 0x4c, 0xbf, 0x4d, 
+    0xb9, 0x4f, 0x84, 0x45, 0x2a, 0x45, 0x2a, 0x4e, 0xb0, 0x45, 0x2a, 0x4f, 0xc8, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x4f, 0xcf, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x52, 0x78, 0x4f, 0xec, 0x50, 
+    0xe6, 0x52, 0xb1, 0x45, 0x2a, 0x45, 0x2a, 0x51, 0xdd, 0x45, 0x2a, 0x52, 0xf5, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x52, 0xfc, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x55, 0xa5, 0x53, 0x19, 0x54, 
+    0x13, 0x55, 0xde, 0x45, 0x2a, 0x45, 0x2a, 0x55, 0x0a, 0x45, 0x2a, 0x56, 0x22, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x56, 0x29, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x58, 0xd2, 0x56, 0x46, 0x57, 
+    0x40, 0x59, 0x0b, 0x45, 0x2a, 0x45, 0x2a, 0x58, 0x37, 0x45, 0x2a, 0x59, 0x4f, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x59, 0x56, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x5b, 0xff, 0x59, 0x73, 0x5a, 
+    0x6d, 0x5c, 0x38, 0x45, 0x2a, 0x45, 0x2a, 0x5b, 0x64, 0x45, 0x2a, 0x5c, 0x7c, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x5c, 0x83, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x5f, 0x2c, 0x5c, 0xa0, 0x5d, 
+    0x9a, 0x5f, 0x65, 0x45, 0x2a, 0x45, 0x2a, 0x5e, 0x91, 0x45, 0x2a, 0x5f, 0xa9, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x5f, 0xb0, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 
+    0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0x45, 0x2a, 0xca, 0xb8, 0x75, 0x2f, 0x02, 
+    0x12, 0x73, 0x35, 0x7e, 0xb3, 0x91, 0x03, 0x20, 0xe5, 0x20, 0x30, 0xe0, 0x05, 0x12, 0x6b, 0x05, 
+    0x80, 0x30, 0x30, 0xe1, 0x05, 0x12, 0x64, 0x86, 0x80, 0x28, 0x30, 0xe2, 0x05, 0x12, 0x63, 0xf5, 
+    0x80, 0x20, 0x30, 0xe3, 0x1d, 0x12, 0x65, 0x61, 0x80, 0x18, 0x7e, 0xb3, 0x91, 0x04, 0x30, 0xe1, 
+    0x03, 0x02, 0x67, 0x5f, 0x30, 0xe6, 0x05, 0x12, 0x6c, 0x6a, 0x80, 0x06, 0x20, 0xe2, 0x03, 0x02, 
+    0x00, 0x80, 0xda, 0xb8, 0x32, 0x75, 0x2f, 0x10, 0x12, 0x73, 0x35, 0xca, 0x0b, 0xca, 0x39, 0xca, 
+    0x59, 0x74, 0x40, 0x7a, 0xb3, 0x91, 0x00, 0x7e, 0xb3, 0x91, 0x1a, 0x6c, 0xaa, 0xbe, 0xb0, 0x40, 
+    0x28, 0x0a, 0x12, 0x64, 0x24, 0xda, 0x59, 0xda, 0x39, 0xda, 0x0b, 0x22, 0x74, 0x20, 0x7a, 0xb3, 
+    0x91, 0x14, 0x80, 0xf1, 0x7e, 0x37, 0x01, 0xc5, 0x2d, 0x35, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x2f, 
+    0x7a, 0x37, 0x01, 0xc5, 0x7e, 0x37, 0x01, 0xc3, 0x7d, 0x43, 0x2d, 0x45, 0xbe, 0x44, 0x2c, 0x2c, 
+    0x38, 0x25, 0x7a, 0x47, 0x01, 0xc3, 0x75, 0x2f, 0x11, 0x12, 0x73, 0x35, 0x7a, 0xb1, 0x2f, 0x12, 
+    0x73, 0x35, 0x12, 0x67, 0x9f, 0x74, 0x20, 0x7a, 0xb3, 0x91, 0x14, 0x12, 0x66, 0x30, 0x22, 0x75, 
+    0x2f, 0x16, 0x12, 0x73, 0x35, 0x80, 0xf4, 0x75, 0x2f, 0x12, 0x12, 0x73, 0x35, 0x7a, 0xb1, 0x2f, 
+    0x12, 0x73, 0x35, 0x9e, 0x44, 0x2c, 0x2d, 0x9d, 0x54, 0x12, 0x67, 0x9f, 0x7e, 0x34, 0x28, 0x2d, 
+    0x7d, 0x54, 0x2d, 0x43, 0x80, 0xbc, 0x75, 0x2f, 0x18, 0x12, 0x73, 0x35, 0xca, 0x09, 0xca, 0x39, 
+    0xca, 0x2b, 0x74, 0x20, 0x7a, 0xb3, 0x91, 0x00, 0x7e, 0x63, 0x91, 0x1a, 0x74, 0x10, 0x7a, 0xb3, 
+    0x91, 0x14, 0x7e, 0xb0, 0x80, 0x9c, 0xb6, 0x60, 0x38, 0x6c, 0xaa, 0x7e, 0x37, 0x01, 0xcb, 0x9d, 
+    0x35, 0x40, 0x37, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc7, 0x7d, 0x43, 0x2d, 0x45, 0xbe, 
+    0x44, 0x28, 0x2c, 0x38, 0x3b, 0x7a, 0x47, 0x01, 0xc7, 0x7d, 0x45, 0x12, 0x68, 0xd4, 0x7e, 0xb3, 
+    0x91, 0x1e, 0x20, 0xe5, 0x13, 0x75, 0x2f, 0x19, 0x12, 0x73, 0x35, 0x7a, 0x91, 0x2f, 0x12, 0x73, 
+    0x35, 0xda, 0x2b, 0xda, 0x39, 0xda, 0x09, 0x22, 0x80, 0x34, 0x2d, 0x53, 0x6d, 0x33, 0x60, 0x02, 
+    0x80, 0xc1, 0x7e, 0x04, 0x24, 0x2d, 0x7a, 0x07, 0x01, 0xc9, 0x7a, 0x07, 0x01, 0xc7, 0x80, 0xe1, 
+    0xca, 0x59, 0x9e, 0x44, 0x28, 0x2d, 0x9d, 0x54, 0x12, 0x68, 0xd4, 0x7e, 0x34, 0x24, 0x2d, 0x7d, 
+    0x54, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc7, 0x12, 0x68, 0xd4, 0xda, 0x49, 0x80, 0xb0, 0x7e, 0x0f, 
+    0x2c, 0x3e, 0x0b, 0x0c, 0x7a, 0x0f, 0x2c, 0x3e, 0x74, 0x20, 0x7a, 0xb3, 0x91, 0x1e, 0x74, 0x60, 
+    0x7a, 0xb3, 0x91, 0x1c, 0x74, 0x02, 0x7a, 0xb3, 0x91, 0x12, 0x80, 0xa5, 0x7e, 0x2f, 0x2c, 0x5e, 
+    0x0b, 0x2c, 0x7a, 0x2f, 0x2c, 0x5e, 0x74, 0x20, 0x7a, 0xb3, 0x91, 0x1e, 0x74, 0x60, 0x7a, 0xb3, 
+    0x91, 0x1c, 0x74, 0x02, 0x7a, 0xb3, 0x91, 0x12, 0x80, 0x1f, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 
+    0x22, 0x75, 0x2f, 0x28, 0x12, 0x73, 0x35, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0x74, 0x60, 0x7a, 
+    0xb3, 0x91, 0x00, 0x74, 0x10, 0x7a, 0xb3, 0x91, 0x14, 0x7e, 0xb3, 0x91, 0x1a, 0x70, 0xdb, 0x7e, 
+    0x0d, 0x30, 0x7e, 0x1d, 0x34, 0x7e, 0x2d, 0x38, 0x7e, 0x3d, 0x3c, 0x7e, 0x85, 0x40, 0x7d, 0x90, 
+    0x4d, 0x91, 0x4d, 0x92, 0x4d, 0x93, 0x4d, 0x94, 0x4d, 0x95, 0x4d, 0x96, 0x4d, 0x97, 0x4d, 0x98, 
+    0x68, 0xb8, 0x7a, 0x13, 0x91, 0x17, 0x7a, 0x03, 0x91, 0x17, 0x7a, 0x33, 0x91, 0x17, 0x7a, 0x23, 
+    0x91, 0x17, 0x7a, 0x53, 0x91, 0x17, 0x7a, 0x43, 0x91, 0x17, 0x7a, 0x73, 0x91, 0x17, 0x7a, 0x63, 
+    0x91, 0x17, 0x7a, 0x93, 0x91, 0x17, 0x7a, 0x83, 0x91, 0x17, 0x30, 0x73, 0x22, 0x7a, 0xb3, 0x91, 
+    0x17, 0x7a, 0xa3, 0x91, 0x17, 0x7a, 0xd3, 0x91, 0x17, 0x7a, 0xc3, 0x91, 0x17, 0x7a, 0xf3, 0x91, 
+    0x17, 0x7a, 0xe3, 0x91, 0x17, 0x7d, 0x78, 0x7a, 0xf3, 0x91, 0x17, 0x7a, 0xe3, 0x91, 0x17, 0x7e, 
+    0xb3, 0x91, 0x1e, 0x30, 0xe5, 0x03, 0x02, 0x65, 0x3c, 0x75, 0x2f, 0x29, 0x12, 0x73, 0x35, 0x20, 
+    0x73, 0x08, 0x75, 0x2f, 0x0a, 0x12, 0x73, 0x35, 0x80, 0x06, 0x75, 0x2f, 0x12, 0x12, 0x73, 0x35, 
+    0x74, 0x80, 0x7a, 0xb3, 0x91, 0x1e, 0x6d, 0x00, 0x7d, 0x10, 0x7a, 0x0d, 0x30, 0x7a, 0x0d, 0x34, 
+    0x7a, 0x0d, 0x38, 0x7a, 0x0d, 0x3c, 0x7a, 0x05, 0x40, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 
+    0x7e, 0x37, 0x01, 0xc5, 0x4d, 0x33, 0x68, 0x3b, 0x7e, 0x07, 0x01, 0xc1, 0x7e, 0x54, 0x2c, 0x2d, 
+    0x9d, 0x50, 0xbd, 0x35, 0x40, 0x02, 0x7d, 0x35, 0xca, 0x39, 0x7e, 0x65, 0x4b, 0x99, 0x64, 0xda, 
+    0x39, 0x7e, 0x07, 0x01, 0xc5, 0x9d, 0x03, 0x7a, 0x07, 0x01, 0xc5, 0x2e, 0x37, 0x01, 0xc1, 0x7a, 
+    0x37, 0x01, 0xc1, 0xbe, 0x34, 0x2c, 0x2c, 0x28, 0xc7, 0x7e, 0x34, 0x28, 0x2d, 0x7a, 0x37, 0x01, 
+    0xc1, 0x80, 0xbd, 0x22, 0x75, 0x2f, 0x53, 0x12, 0x73, 0x35, 0x7e, 0x15, 0x4d, 0x80, 0x11, 0x75, 
+    0x2f, 0x51, 0x12, 0x73, 0x35, 0x0b, 0x08, 0x10, 0x0b, 0x05, 0x9e, 0x34, 0x00, 0x02, 0x28, 0x4d, 
+    0x7c, 0xb2, 0x20, 0xe7, 0x27, 0x54, 0x07, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x39, 0x1e, 0x7c, 0xb2, 
+    0x54, 0x78, 0x03, 0x03, 0x03, 0x7c, 0x2b, 0x9d, 0x13, 0x40, 0x1a, 0x68, 0x12, 0x7a, 0x15, 0x4d, 
+    0x7a, 0x25, 0x4f, 0x7e, 0x64, 0x67, 0x09, 0x7a, 0x65, 0x4b, 0x89, 0x24, 0x02, 0x67, 0x17, 0x7e, 
+    0x64, 0x66, 0x7f, 0x80, 0xf2, 0x2d, 0x13, 0x9d, 0x31, 0xca, 0x39, 0x7d, 0x31, 0x2d, 0x10, 0xca, 
+    0x19, 0xca, 0x29, 0x99, 0x24, 0xda, 0x29, 0xda, 0x09, 0xda, 0x39, 0x80, 0xa2, 0x7a, 0x15, 0x4d, 
+    0x7e, 0x64, 0x66, 0xf5, 0x4d, 0x33, 0x78, 0x09, 0x7c, 0xb2, 0x20, 0xe7, 0x2a, 0x7e, 0x64, 0x66, 
+    0x74, 0x7a, 0x65, 0x4b, 0x22, 0x75, 0x2f, 0x52, 0x12, 0x73, 0x35, 0x7e, 0x21, 0x4d, 0x7e, 0x09, 
+    0x30, 0x0b, 0x04, 0x1b, 0x34, 0x78, 0x89, 0x80, 0xd4, 0x75, 0x2f, 0x54, 0x12, 0x73, 0x35, 0x7e, 
+    0x15, 0x4d, 0x7e, 0x25, 0x4f, 0x80, 0x90, 0x5e, 0x20, 0x07, 0x54, 0x78, 0x7e, 0x44, 0x67, 0x7d, 
+    0x30, 0xe6, 0x16, 0x4d, 0x33, 0x68, 0x26, 0x1b, 0x34, 0x7e, 0x09, 0x40, 0x0b, 0x04, 0x7e, 0x44, 
+    0x34, 0xfa, 0x20, 0xe3, 0x04, 0x7e, 0x44, 0x67, 0x85, 0xca, 0x09, 0xca, 0x39, 0x99, 0x44, 0xda, 
+    0x39, 0xda, 0x09, 0x7e, 0x64, 0x66, 0x7f, 0x4d, 0x33, 0x68, 0xa6, 0x89, 0x64, 0x7a, 0x15, 0x4d, 
+    0xf5, 0x4f, 0x7e, 0x64, 0x67, 0x58, 0x80, 0x99, 0x7e, 0x15, 0x4d, 0xe5, 0x4f, 0x80, 0xc4, 0xc0, 
+    0xd0, 0xc0, 0xd1, 0xc0, 0xe0, 0xca, 0x19, 0x75, 0x2f, 0xfe, 0x12, 0x73, 0x35, 0x7e, 0x14, 0x00, 
+    0x53, 0x02, 0x40, 0x52, 0xda, 0x19, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 0x32, 0x03, 0xa5, 0xcb, 
+    0x19, 0xb1, 0x80, 0x00, 0x22, 0x22, 0x7e, 0x24, 0x00, 0x00, 0x7f, 0xe1, 0x7e, 0xa0, 0x02, 0xa4, 
+    0x7e, 0x04, 0x68, 0xb1, 0x9d, 0x05, 0x7e, 0xb0, 0x28, 0x7a, 0xb3, 0x95, 0x00, 0x89, 0x04, 0xca, 
+    0x29, 0xb4, 0x80, 0xe2, 0x7e, 0x24, 0x00, 0x00, 0x7f, 0xe1, 0x7e, 0x00, 0x28, 0x7a, 0x03, 0x95, 
+    0x00, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x95, 0x00, 0xda, 0x29, 0x22, 0x7e, 0x24, 0x00, 0x00, 0x7f, 
+    0xe1, 0x7e, 0xa0, 0x02, 0xa4, 0x7e, 0x04, 0x69, 0xe6, 0x9d, 0x05, 0x7e, 0xb0, 0x38, 0x7a, 0xb3, 
+    0x95, 0x00, 0x89, 0x04, 0xca, 0x29, 0xb4, 0x80, 0xe2, 0x7e, 0x24, 0x00, 0x00, 0x7f, 0xe1, 0x7e, 
+    0x00, 0x38, 0x7a, 0x03, 0x95, 0x00, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x95, 0x00, 0xda, 0x29, 0x22, 
+    0xca, 0x29, 0xca, 0x19, 0xca, 0x58, 0x7e, 0x24, 0x00, 0x00, 0x7f, 0xe1, 0xda, 0x58, 0x7e, 0x54, 
+    0x02, 0x20, 0x9c, 0xb5, 0xa4, 0x7e, 0x50, 0x30, 0x5e, 0x20, 0x07, 0x2c, 0x52, 0x7a, 0x53, 0x95, 
+    0x00, 0x2e, 0x54, 0x6a, 0x17, 0x89, 0x54, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 
+    0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x95, 0x00, 0xda, 0x19, 
+    0xda, 0x29, 0x22, 0xca, 0x19, 0xca, 0x58, 0x7e, 0x24, 0x00, 0x00, 0x7f, 0xe1, 0xda, 0x58, 0x7e, 
+    0x54, 0x02, 0x38, 0x9c, 0xb5, 0xa4, 0x7e, 0x50, 0x20, 0x5e, 0x20, 0x07, 0x2c, 0x52, 0x7a, 0x53, 
+    0x95, 0x00, 0x2e, 0x54, 0x6a, 0x88, 0x89, 0x54, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 
+    0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0xe0, 0xa3, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x95, 0x00, 0xda, 
+    0x19, 0x22, 0x02, 0x6b, 0xa8, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xca, 0x3b, 0xca, 0x4b, 0xca, 
+    0x5b, 0xca, 0x6b, 0xca, 0x7b, 0xca, 0xeb, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x7e, 0xb3, 0x2c, 
+    0x7f, 0xb4, 0x00, 0x02, 0x80, 0x1c, 0xb4, 0x01, 0x19, 0x7e, 0xb3, 0x91, 0x14, 0x54, 0x14, 0x68, 
+    0x05, 0x12, 0x6b, 0x6c, 0x80, 0x23, 0x7e, 0xb3, 0x91, 0x14, 0x30, 0xe5, 0x1c, 0x12, 0x6c, 0xaa, 
+    0x80, 0x17, 0x7e, 0xb3, 0x91, 0x14, 0x30, 0xe5, 0x05, 0x12, 0x6c, 0xaa, 0x80, 0x0b, 0x7e, 0xb3, 
+    0x91, 0x14, 0x54, 0x14, 0x68, 0x03, 0x12, 0x6b, 0x6c, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 0xda, 
+    0x5b, 0xda, 0x4b, 0xda, 0x3b, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x20, 0xe4, 0x19, 0x75, 
+    0x2f, 0x0a, 0x12, 0x73, 0x35, 0x7e, 0xb3, 0x2c, 0x7e, 0x70, 0x0a, 0x7e, 0xb3, 0x2c, 0x7f, 0xb4, 
+    0x01, 0x1f, 0x02, 0x6c, 0x04, 0x02, 0x71, 0xf2, 0x75, 0x2f, 0x0b, 0x12, 0x73, 0x35, 0x74, 0x14, 
+    0x7a, 0xb3, 0x91, 0x14, 0x7e, 0xb3, 0x2c, 0x7f, 0xb4, 0x02, 0x0c, 0x12, 0x6b, 0xb4, 0x02, 0x6b, 
+    0xa8, 0x74, 0x04, 0x7a, 0xb3, 0x91, 0x14, 0x22, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x2c, 0x7f, 0x7a, 
+    0x03, 0x2c, 0x80, 0x22, 0x7e, 0xb3, 0x2c, 0x76, 0x54, 0x60, 0x60, 0x05, 0xb4, 0x40, 0x1e, 0x80, 
+    0x1c, 0x7e, 0xb3, 0x2c, 0x77, 0xb4, 0x05, 0x15, 0x75, 0x2f, 0x71, 0x12, 0x73, 0x35, 0x7e, 0xb3, 
+    0x2c, 0x79, 0x7e, 0xa0, 0x01, 0x7a, 0xa3, 0x91, 0x06, 0x7a, 0xb3, 0x91, 0x07, 0x22, 0x74, 0x00, 
+    0x7a, 0xb3, 0x91, 0x00, 0x74, 0x10, 0x7a, 0xb3, 0x91, 0x12, 0x22, 0xbe, 0x57, 0x2c, 0x7c, 0x28, 
+    0x04, 0x7e, 0x57, 0x2c, 0x7c, 0x7a, 0x0f, 0x2c, 0x82, 0x7a, 0x57, 0x2c, 0x86, 0x74, 0x10, 0x7a, 
+    0xb3, 0x91, 0x12, 0x22, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x7e, 0xb3, 0x91, 0x1a, 0x70, 0x53, 
+    0x7e, 0xb3, 0x91, 0x14, 0x20, 0xe4, 0x4c, 0x7e, 0xef, 0x2c, 0x82, 0x7e, 0xf7, 0x2c, 0x86, 0x7e, 
+    0x07, 0x2c, 0x86, 0x4d, 0x00, 0x68, 0x21, 0x7e, 0x00, 0x00, 0xe0, 0x7a, 0xb3, 0x91, 0x17, 0xa3, 
+    0xa5, 0x08, 0x1b, 0xf4, 0x68, 0x06, 0xa5, 0xb8, 0x10, 0xf0, 0x80, 0x19, 0x7e, 0xb0, 0x00, 0x7a, 
+    0xb3, 0x2c, 0x7f, 0xbe, 0x00, 0x10, 0x68, 0x0d, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x2c, 0x7f, 0x74, 
+    0x80, 0x7a, 0xb3, 0x91, 0x1e, 0x7a, 0xef, 0x2c, 0x82, 0x7a, 0xf7, 0x2c, 0x86, 0x75, 0x2f, 0x06, 
+    0x12, 0x73, 0x35, 0x74, 0x04, 0x7a, 0xb3, 0x91, 0x14, 0x22, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 
+    0xca, 0x3b, 0xca, 0x4b, 0xca, 0x5b, 0xca, 0x6b, 0xca, 0x7b, 0xca, 0xeb, 0x75, 0x2f, 0x03, 0x12, 
+    0x73, 0x35, 0x74, 0x00, 0x7a, 0xb3, 0x2c, 0x7e, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x01, 
+    0x7a, 0xb3, 0x91, 0x12, 0x12, 0x6d, 0x19, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 0xda, 0x5b, 0xda, 
+    0x4b, 0xda, 0x3b, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x75, 0x2f, 0x03, 0x12, 0x73, 0x35, 
+    0x7e, 0xb3, 0x2c, 0x80, 0xb4, 0x02, 0x11, 0x74, 0x00, 0x7a, 0xb3, 0x2c, 0x80, 0x7a, 0xb3, 0x2c, 
+    0x7f, 0x74, 0x20, 0x7a, 0xb3, 0x91, 0x14, 0x22, 0xb4, 0x01, 0x46, 0x7e, 0xb3, 0x91, 0x04, 0x20, 
+    0xe6, 0x42, 0x7e, 0x23, 0x91, 0x1a, 0x7c, 0x32, 0x7e, 0x13, 0x2c, 0x81, 0x2c, 0x21, 0x7a, 0x23, 
+    0x2c, 0x81, 0x7e, 0x00, 0x00, 0x2e, 0x04, 0x2c, 0x88, 0x7e, 0xb3, 0x91, 0x16, 0x7a, 0x09, 0xb0, 
+    0x0b, 0x04, 0xa5, 0xdb, 0xf4, 0x74, 0x20, 0x7a, 0xb3, 0x91, 0x14, 0x75, 0x2f, 0x70, 0x12, 0x73, 
+    0x35, 0x7e, 0xb3, 0x2c, 0x81, 0x7e, 0xa3, 0x2c, 0x7d, 0xbc, 0xab, 0x78, 0x03, 0x12, 0x6d, 0xb9, 
+    0x22, 0x02, 0x71, 0xf2, 0xda, 0x59, 0x02, 0x6c, 0x7c, 0x74, 0xe0, 0x7a, 0xb3, 0x91, 0x00, 0x7e, 
+    0x03, 0x91, 0x10, 0x7e, 0x13, 0x91, 0x11, 0x7e, 0x33, 0x91, 0x12, 0x7e, 0x23, 0x91, 0x13, 0x7e, 
+    0x53, 0x91, 0x14, 0x7e, 0x43, 0x91, 0x15, 0x7e, 0x73, 0x91, 0x16, 0x7e, 0x63, 0x91, 0x17, 0x7a, 
+    0x0f, 0x2c, 0x76, 0x7a, 0x1f, 0x2c, 0x7a, 0x75, 0x2f, 0x04, 0x12, 0x73, 0x35, 0x7a, 0x01, 0x2f, 
+    0x12, 0x73, 0x35, 0x7a, 0x11, 0x2f, 0x12, 0x73, 0x35, 0x7a, 0x21, 0x2f, 0x12, 0x73, 0x35, 0x7a, 
+    0x31, 0x2f, 0x12, 0x73, 0x35, 0x7a, 0x41, 0x2f, 0x12, 0x73, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x73, 
+    0x35, 0x7a, 0x61, 0x2f, 0x12, 0x73, 0x35, 0x7a, 0x71, 0x2f, 0x12, 0x73, 0x35, 0x74, 0x00, 0x7a, 
+    0xb3, 0x91, 0x00, 0x74, 0x40, 0x7a, 0xb3, 0x91, 0x04, 0x12, 0x6d, 0x8d, 0x22, 0x6d, 0x00, 0x7e, 
+    0x14, 0x01, 0x02, 0x7a, 0x07, 0x2c, 0x86, 0x7a, 0x03, 0x2c, 0x81, 0x7e, 0xb3, 0x2c, 0x76, 0x20, 
+    0xe7, 0x0f, 0x7a, 0x23, 0x2c, 0x80, 0x7a, 0x33, 0x2c, 0x7f, 0xbe, 0x07, 0x2c, 0x7c, 0x68, 0x09, 
+    0x22, 0x7a, 0x33, 0x2c, 0x80, 0x7a, 0x23, 0x2c, 0x7f, 0x7e, 0xb3, 0x2c, 0x76, 0x54, 0xe3, 0x23, 
+    0x23, 0x30, 0xe0, 0x02, 0xd2, 0xe5, 0x30, 0xe7, 0x02, 0xd2, 0xe4, 0x30, 0xe5, 0x06, 0x30, 0xe4, 
+    0x03, 0x02, 0x71, 0xf2, 0x54, 0x3e, 0xf5, 0xf0, 0x03, 0x54, 0x1f, 0xc3, 0x25, 0xf0, 0x90, 0x6d, 
+    0xe5, 0x75, 0x84, 0xff, 0x73, 0x02, 0x6f, 0xa0, 0x02, 0x6e, 0x2d, 0x02, 0x70, 0x39, 0x02, 0x70, 
+    0x54, 0x02, 0x6f, 0x37, 0x02, 0x6e, 0xc2, 0x02, 0x70, 0x85, 0x02, 0x70, 0x85, 0x02, 0x70, 0x88, 
+    0x02, 0x70, 0x88, 0x02, 0x70, 0x88, 0x02, 0x70, 0x88, 0x02, 0x70, 0x88, 0x02, 0x70, 0x88, 0x02, 
+    0x70, 0x88, 0x02, 0x70, 0x88, 0x02, 0x70, 0x8e, 0x02, 0x71, 0x60, 0x02, 0x70, 0x8b, 0x02, 0x70, 
+    0x8b, 0x02, 0x70, 0x8b, 0x02, 0x70, 0x8b, 0x02, 0x70, 0x8b, 0x02, 0x70, 0x8b, 0x74, 0x00, 0x7a, 
+    0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 0xb3, 0x91, 0x1c, 0x7e, 0xb3, 0x2c, 0x77, 0xb4, 0x06, 0x2a, 
+    0x7e, 0xb3, 0x2c, 0x78, 0x60, 0x79, 0x7c, 0x0b, 0x7e, 0x13, 0x2c, 0x79, 0x7e, 0x17, 0x2c, 0x7a, 
+    0x75, 0x2f, 0x72, 0x12, 0x73, 0x35, 0x7a, 0x01, 0x2f, 0x12, 0x73, 0x35, 0x7a, 0x11, 0x2f, 0x12, 
+    0x73, 0x35, 0x12, 0x72, 0x37, 0x40, 0x58, 0x02, 0x6b, 0xeb, 0xb4, 0x08, 0x1c, 0x75, 0x2f, 0x74, 
+    0x12, 0x73, 0x35, 0x7e, 0xb3, 0x3f, 0xf1, 0x7e, 0x08, 0x2c, 0x88, 0x7a, 0x0c, 0x00, 0x00, 0x7a, 
+    0x0b, 0xb0, 0x7e, 0x54, 0x00, 0x01, 0x02, 0x6b, 0xeb, 0xb4, 0x00, 0x33, 0x75, 0x2f, 0x75, 0x12, 
+    0x73, 0x35, 0x7e, 0x08, 0x2c, 0x88, 0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0x7e, 0xb3, 0x3f, 0xf2, 
+    0x30, 0xe0, 0x07, 0x74, 0x02, 0x7a, 0x0b, 0xb0, 0x80, 0x05, 0x74, 0x00, 0x7a, 0x0b, 0xb0, 0x0b, 
+    0x14, 0x74, 0x00, 0x7a, 0x0b, 0xb0, 0x7e, 0x54, 0x00, 0x02, 0xda, 0x0b, 0x02, 0x6b, 0xeb, 0x02, 
+    0x71, 0xf2, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 0xb3, 0x91, 0x1c, 0x7e, 0xb3, 
+    0x2c, 0x77, 0xb4, 0x00, 0x5f, 0x75, 0x2f, 0x76, 0x12, 0x73, 0x35, 0x7e, 0xb3, 0x2c, 0x7b, 0x54, 
+    0x0f, 0xb4, 0x02, 0x05, 0x7e, 0xb0, 0x60, 0x80, 0x17, 0xb4, 0x00, 0x05, 0x7e, 0xb0, 0x00, 0x80, 
+    0x0f, 0x7e, 0xb3, 0x2c, 0x7b, 0x20, 0xe7, 0x05, 0x7e, 0xb0, 0x40, 0x80, 0x03, 0x7e, 0xb0, 0x20, 
+    0x7a, 0xb3, 0x91, 0x00, 0x7e, 0xb3, 0x91, 0x11, 0x30, 0xe0, 0x04, 0x74, 0x01, 0x80, 0x02, 0x74, 
+    0x00, 0x7e, 0x08, 0x2c, 0x88, 0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0x7a, 0x0b, 0xb0, 0x0b, 0x14, 
+    0x74, 0x00, 0x7a, 0x0b, 0xb0, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x7e, 0x54, 0x00, 0x02, 0xda, 
+    0x0b, 0x02, 0x6b, 0xeb, 0x02, 0x71, 0xf2, 0x7e, 0xb3, 0x2c, 0x7b, 0x54, 0x0f, 0xb4, 0x02, 0x05, 
+    0x7e, 0xb0, 0x60, 0x80, 0x17, 0xb4, 0x00, 0x05, 0x7e, 0xb0, 0x00, 0x80, 0x0f, 0x7e, 0xb3, 0x2c, 
+    0x7b, 0x20, 0xe7, 0x05, 0x7e, 0xb0, 0x40, 0x80, 0x03, 0x7e, 0xb0, 0x20, 0x7a, 0xb3, 0x91, 0x00, 
+    0x7e, 0xb3, 0x2c, 0x79, 0xb4, 0x00, 0x26, 0x7e, 0xb3, 0x2c, 0x77, 0xb4, 0x01, 0x0e, 0x75, 0x2f, 
+    0x77, 0x12, 0x73, 0x35, 0x74, 0x01, 0x7a, 0xb3, 0x91, 0x12, 0x80, 0x1b, 0xb4, 0x03, 0x0e, 0x75, 
+    0x2f, 0x78, 0x12, 0x73, 0x35, 0x74, 0x01, 0x7a, 0xb3, 0x91, 0x11, 0x80, 0x0a, 0x74, 0x00, 0x7a, 
+    0xb3, 0x91, 0x00, 0x12, 0x71, 0xf2, 0x22, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x02, 0x6b, 0xde, 
+    0x7e, 0xb3, 0x2c, 0x77, 0xb4, 0x09, 0x1f, 0x75, 0x2f, 0x79, 0x12, 0x73, 0x35, 0x7e, 0xb3, 0x2c, 
+    0x79, 0xbe, 0xb3, 0x3f, 0xf1, 0x68, 0x0d, 0xca, 0xb8, 0x12, 0x43, 0x79, 0xda, 0xb8, 0x50, 0x76, 
+    0x7a, 0xb3, 0x3f, 0xf1, 0x80, 0x6d, 0xb4, 0x05, 0x08, 0x75, 0x2f, 0x7a, 0x12, 0x73, 0x35, 0x80, 
+    0x62, 0xb4, 0x03, 0x19, 0x75, 0x2f, 0x7b, 0x12, 0x73, 0x35, 0x7e, 0xb3, 0x2c, 0x79, 0xb4, 0x01, 
+    0x55, 0x7e, 0xb3, 0x3f, 0xf2, 0x44, 0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x46, 0xb4, 0x01, 0x19, 
+    0x75, 0x2f, 0x7c, 0x12, 0x73, 0x35, 0x7e, 0xb3, 0x2c, 0x79, 0xb4, 0x01, 0x39, 0x7e, 0xb3, 0x3f, 
+    0xf2, 0x54, 0xfe, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x2a, 0xb4, 0x07, 0x2a, 0x7e, 0xb3, 0x2c, 0x78, 
+    0x60, 0x24, 0x7c, 0x0b, 0x7e, 0x13, 0x2c, 0x79, 0x7e, 0x17, 0x2c, 0x7a, 0x75, 0x2f, 0x73, 0x12, 
+    0x73, 0x35, 0x7a, 0x01, 0x2f, 0x12, 0x73, 0x35, 0x7a, 0x11, 0x2f, 0x12, 0x73, 0x35, 0x12, 0x72, 
+    0x71, 0x40, 0x03, 0x02, 0x6b, 0xde, 0x02, 0x71, 0xf2, 0x7e, 0xb3, 0x2c, 0x77, 0xb4, 0x0b, 0xf6, 
+    0x75, 0x2f, 0x7d, 0x12, 0x73, 0x35, 0x7e, 0xb3, 0x2c, 0x79, 0x7e, 0xa3, 0x2c, 0x7b, 0x4c, 0xab, 
+    0x78, 0xe4, 0x80, 0xdf, 0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 0xb3, 0x91, 0x1c, 
+    0x7e, 0xb3, 0x2c, 0x77, 0xb4, 0x0a, 0xcf, 0x75, 0x2f, 0x7e, 0x12, 0x73, 0x35, 0x7e, 0xb3, 0x2c, 
+    0x79, 0x70, 0xc3, 0x7e, 0x08, 0x2c, 0x88, 0x7a, 0x0c, 0x00, 0x00, 0x7a, 0x0b, 0xb0, 0x7e, 0x54, 
+    0x00, 0x01, 0x02, 0x6b, 0xeb, 0x02, 0x71, 0xf2, 0x02, 0x71, 0xf2, 0x02, 0x71, 0xf2, 0x7e, 0xb3, 
+    0x2c, 0x77, 0xb4, 0x04, 0x20, 0x75, 0x2f, 0xc3, 0x12, 0x73, 0x35, 0x7e, 0x04, 0x00, 0x01, 0x7e, 
+    0x17, 0x2c, 0x78, 0x7e, 0x18, 0x2c, 0x88, 0x7a, 0x1c, 0x00, 0x00, 0x7e, 0x47, 0x2c, 0x7c, 0x12, 
+    0x73, 0x41, 0x02, 0x71, 0x5a, 0xb4, 0x06, 0x42, 0x75, 0x2f, 0xc1, 0x12, 0x73, 0x35, 0x7e, 0x58, 
+    0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7d, 0xca, 0x7e, 0xd7, 0x2c, 0x78, 0x7e, 0x78, 0x2c, 0x88, 
+    0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x2c, 0x7c, 0x75, 0x2f, 0xc1, 0x12, 0x73, 0x35, 0xc0, 0xa8, 
+    0xc2, 0xaf, 0x7e, 0x40, 0x01, 0x7a, 0x43, 0x94, 0x00, 0x12, 0x73, 0x7a, 0x7e, 0x43, 0x2c, 0x35, 
+    0x7a, 0x43, 0x94, 0x00, 0xd0, 0xa8, 0x40, 0x65, 0x80, 0x60, 0xb4, 0x00, 0x24, 0xc2, 0xaf, 0x7e, 
+    0xb0, 0x01, 0x7a, 0xb3, 0x94, 0x00, 0x7a, 0xb3, 0x2c, 0x35, 0x12, 0x6b, 0xde, 0xe4, 0x8d, 0xef, 
+    0x8d, 0xef, 0x8d, 0xef, 0xd5, 0xe0, 0xf7, 0xc0, 0xd1, 0xca, 0x02, 0xff, 0xca, 0x06, 0x00, 0x00, 
+    0x32, 0xb4, 0x09, 0x20, 0x74, 0x03, 0x7a, 0xb3, 0x91, 0x06, 0x7e, 0x23, 0x91, 0x07, 0x7e, 0x57, 
+    0x2c, 0x78, 0x4d, 0x55, 0x68, 0x05, 0x4e, 0x20, 0x02, 0x80, 0x03, 0x5e, 0x20, 0xfd, 0x7a, 0x23, 
+    0x91, 0x07, 0x80, 0x16, 0xb4, 0x07, 0x16, 0xc2, 0xaf, 0x7e, 0x07, 0x2c, 0x7a, 0x7e, 0x17, 0x2c, 
+    0x78, 0xc0, 0xd1, 0xca, 0x18, 0xca, 0x38, 0xca, 0x28, 0x32, 0x02, 0x6b, 0xde, 0x02, 0x71, 0xf2, 
+    0x74, 0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x60, 0x7a, 0xb3, 0x91, 0x1c, 0x7e, 0xb3, 0x2c, 0x77, 
+    0xb4, 0x03, 0x15, 0x75, 0x2f, 0xc2, 0x12, 0x73, 0x35, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2c, 
+    0x78, 0x7e, 0x57, 0x2c, 0x7c, 0x02, 0x6b, 0xeb, 0xb4, 0x05, 0x41, 0x75, 0x2f, 0xc0, 0x12, 0x73, 
+    0x35, 0xc0, 0xa8, 0xc2, 0xaf, 0x7e, 0x40, 0x01, 0x7a, 0x43, 0x94, 0x00, 0x7e, 0x08, 0x2c, 0x88, 
+    0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x37, 0x2c, 0x78, 0x7e, 0x47, 0x2c, 0x7c, 
+    0x12, 0x73, 0x41, 0x7e, 0x43, 0x2c, 0x35, 0x7a, 0x43, 0x94, 0x00, 0xd0, 0xa8, 0x7e, 0x08, 0x2c, 
+    0x88, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x57, 0x2c, 0x7c, 0x02, 0x6b, 0xeb, 0xb4, 0x01, 0x20, 0x7e, 
+    0x00, 0x00, 0x7e, 0x10, 0x01, 0x75, 0x2f, 0x72, 0x12, 0x73, 0x35, 0x7a, 0x01, 0x2f, 0x12, 0x73, 
+    0x35, 0x7a, 0x11, 0x2f, 0x12, 0x73, 0x35, 0x12, 0x72, 0x37, 0x40, 0x03, 0x02, 0x6b, 0xeb, 0x02, 
+    0x71, 0xf2, 0x75, 0x2f, 0x07, 0x12, 0x73, 0x35, 0x7e, 0xb0, 0x02, 0x7a, 0xb3, 0x90, 0x00, 0x74, 
+    0x00, 0x7a, 0xb3, 0x91, 0x00, 0x74, 0x40, 0x7a, 0xb3, 0x91, 0x15, 0x74, 0x01, 0x7a, 0xb3, 0x91, 
+    0x11, 0x7e, 0xb3, 0x91, 0x15, 0x54, 0x60, 0xbe, 0xb0, 0x40, 0x68, 0x08, 0x74, 0x20, 0x7a, 0xb3, 
+    0x91, 0x15, 0x80, 0xed, 0x74, 0x01, 0x7a, 0xb3, 0x91, 0x12, 0x74, 0x04, 0x7a, 0xb3, 0x91, 0x14, 
+    0x74, 0xff, 0x7a, 0xb3, 0x2c, 0x7e, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0x7e, 0x40, 0x01, 0x7a, 0x43, 
+    0x94, 0x00, 0x12, 0x72, 0xbe, 0x40, 0x1f, 0x7e, 0x08, 0x2c, 0x88, 0x7a, 0x0c, 0x00, 0x00, 0xca, 
+    0x0b, 0xca, 0x49, 0x12, 0x73, 0x41, 0xda, 0x59, 0xda, 0x0b, 0x7e, 0x43, 0x2c, 0x35, 0x7a, 0x43, 
+    0x94, 0x00, 0xd0, 0xa8, 0xc3, 0x22, 0x7e, 0x43, 0x2c, 0x35, 0x7a, 0x43, 0x94, 0x00, 0xd0, 0xa8, 
+    0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0x7e, 0x40, 0x01, 0x7a, 0x43, 0x94, 0x00, 0x12, 0x72, 0xbe, 0x40, 
+    0x31, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7f, 0x61, 0x7e, 0x78, 0x2c, 0x88, 0x7a, 
+    0x7c, 0x00, 0x00, 0x7e, 0x77, 0x2c, 0x7c, 0xbd, 0x74, 0x78, 0x17, 0x75, 0x2f, 0xc1, 0x12, 0x73, 
+    0x35, 0x12, 0x73, 0x7a, 0x40, 0x0c, 0x7e, 0x43, 0x2c, 0x35, 0x7a, 0x43, 0x94, 0x00, 0xd0, 0xa8, 
+    0xc3, 0x22, 0x7e, 0x43, 0x2c, 0x35, 0x7a, 0x43, 0x94, 0x00, 0xd0, 0xa8, 0xd3, 0x22, 0x7e, 0x24, 
+    0x00, 0xfe, 0x7e, 0x34, 0x7f, 0xca, 0x0b, 0x1a, 0x50, 0xc5, 0xf0, 0x7d, 0x62, 0x7d, 0x75, 0x7d, 
+    0x87, 0x7e, 0x34, 0x7f, 0xc2, 0x7e, 0x1b, 0xb0, 0x7e, 0x34, 0x7f, 0x03, 0xb4, 0x01, 0x04, 0x7e, 
+    0x34, 0x7f, 0xcc, 0x7e, 0x1b, 0xb0, 0xbc, 0x0b, 0x50, 0x49, 0x3e, 0x00, 0x3e, 0x00, 0x0a, 0x50, 
+    0x2d, 0x75, 0x0b, 0x3a, 0x30, 0x69, 0x53, 0x00, 0x02, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbc, 
+    0x1b, 0x50, 0x30, 0x3e, 0x10, 0x3e, 0x10, 0x0a, 0x51, 0x2d, 0x35, 0x69, 0x41, 0x00, 0x02, 0x0b, 
+    0x1a, 0x30, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbe, 0x44, 0xff, 0xff, 0x78, 0x05, 0x7e, 0x1b, 
+    0x90, 0x0a, 0x49, 0x4d, 0x44, 0x68, 0x0c, 0xbe, 0x44, 0x00, 0xff, 0x28, 0x04, 0x7e, 0x44, 0x00, 
+    0xff, 0xc3, 0x22, 0xd3, 0x22, 
+
+// Segment #16, Start Address 00ff7fc6, Length 4
+0xff,0x00,0xc6,0x7f,0x04,0x00,
+    0x02, 0x00, 0x03, 0x00, 
+
+// Segment #17, Start Address 00ff7335, Length 328
+0xff,0x00,0x35,0x73,0x48,0x01,
+    0xca, 0x08, 0x7e, 0x01, 0x2f, 0x7a, 0x03, 0x3f, 0xf0, 0xda, 0x08, 0x22, 0x7e, 0x1b, 0xc0, 0x7a, 
+    0x0b, 0xc0, 0x0b, 0x14, 0x0b, 0x34, 0x1b, 0x44, 0x78, 0xf2, 0x22, 0x7f, 0x6f, 0x7f, 0xf0, 0x1b, 
+    0xfc, 0x7c, 0x54, 0x7d, 0x32, 0x80, 0x08, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0x9e, 
+    0x44, 0x00, 0x10, 0x50, 0xf2, 0x2e, 0x44, 0x00, 0x10, 0x68, 0x06, 0xca, 0x48, 0x1b, 0x44, 0x78, 
+    0xfa, 0x7f, 0xf6, 0x89, 0xe4, 0xca, 0x6b, 0x5e, 0xd4, 0x00, 0x3f, 0x68, 0x20, 0x7e, 0x84, 0x00, 
+    0x40, 0x9d, 0x8d, 0xda, 0x6b, 0xbd, 0x87, 0x38, 0x16, 0xca, 0x79, 0x7d, 0x78, 0x12, 0x73, 0xa4, 
+    0xda, 0x79, 0x40, 0x08, 0x9d, 0x78, 0x68, 0x02, 0x80, 0x05, 0xc2, 0xd7, 0x22, 0xda, 0x6b, 0x7e, 
+    0xc0, 0x03, 0x7e, 0xd0, 0x00, 0x7a, 0xd3, 0x90, 0x00, 0x74, 0xaa, 0x39, 0xb5, 0x55, 0x55, 0x74, 
+    0x55, 0x39, 0xb5, 0x2a, 0xaa, 0x74, 0xa0, 0x39, 0xb5, 0x55, 0x55, 0x7e, 0x04, 0x00, 0x40, 0x9d, 
+    0x70, 0x50, 0x06, 0x2d, 0x70, 0x7d, 0x07, 0x6d, 0x77, 0x7c, 0x31, 0x7e, 0x7b, 0x00, 0x7a, 0x6b, 
+    0x00, 0x0b, 0x7c, 0x0b, 0x6c, 0xa5, 0xd9, 0xf3, 0x7f, 0x16, 0x1b, 0x1c, 0x7e, 0x54, 0x27, 0x10, 
+    0x7e, 0x1b, 0x10, 0xbc, 0x10, 0x68, 0x06, 0x1b, 0x54, 0x78, 0xf5, 0x80, 0x2f, 0x6d, 0x00, 0x7c, 
+    0x20, 0x7f, 0x16, 0x9f, 0x10, 0x7f, 0x27, 0x9f, 0x20, 0x7e, 0x2b, 0x00, 0x7e, 0x1b, 0x10, 0xbc, 
+    0x01, 0x78, 0x19, 0x0b, 0x2c, 0x0b, 0x1c, 0xa5, 0xdb, 0xef, 0x7c, 0xb6, 0x20, 0xe0, 0x06, 0x6c, 
+    0xdc, 0x7a, 0xd3, 0x90, 0x00, 0x4d, 0x77, 0x78, 0x90, 0xc2, 0xd7, 0x22, 0xd2, 0xd7, 0x22, 0x00, 
+    0x04, 0x00, 0x04, 0x00, 0x00, 0x06, 0x04, 0x02, 0x04, 0x00, 0x02, 0x01, 0x04, 0x01, 0x02, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x00, 0x08, 0x10, 
+    0x02, 0x10, 0x04, 0x02, 0x08, 0x00, 0x01, 0x01, 0x08, 0x7e, 0x18, 0x7f, 0xbd, 0x7a, 0x1c, 0x00, 
+    0xfe, 0x0b, 0x1a, 0x00, 0x5e, 0x10, 0x1f, 0xbe, 0x10, 0x14, 0x38, 0x1a, 0x0a, 0x51, 0x23, 0x7e, 
+    0x18, 0x74, 0x24, 0x7a, 0x1c, 0x00, 0xff, 0x2d, 0x35, 0x0b, 0x1a, 0x50, 0x60, 0x08, 0xa5, 0xb8, 
+    0x02, 0x03, 0x4e, 0xa0, 0x08, 0x22, 0x80, 0xfe, 
+};
+
+static EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME = {
+       2, 0, 3 };              // Major, Minor, Build
+
+#undef IMAGE_VERSION_NAME
+
+#undef IMAGE_ARRAY_NAME
+
diff --git a/drivers/usb/serial/io_ionsp.h b/drivers/usb/serial/io_ionsp.h
new file mode 100644 (file)
index 0000000..c9255ca
--- /dev/null
@@ -0,0 +1,454 @@
+/************************************************************************
+ *
+ *     IONSP.H         Definitions for I/O Networks Serial Protocol
+ *
+ *     Copyright (c) 1997-1998 Inside Out Networks, Inc.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     These definitions are used by both kernel-mode driver and the
+ *     peripheral firmware and MUST be kept in sync.
+ *
+ ************************************************************************/
+
+/************************************************************************
+
+The data to and from all ports on the peripheral is multiplexed
+through a single endpoint pair (EP1 since it supports 64-byte
+MaxPacketSize). Therefore, the data, commands, and status for
+each port must be preceeded by a short header identifying the
+destination port. The header also identifies the bytes that follow
+as data or as command/status info.
+
+Header format, first byte:
+
+    CLLLLPPP
+    --------
+    | |         |------ Port Number:   0-7
+    | |--------- Length:       MSB bits of length
+    |----------- Data/Command: 0 = Data header
+                               1 = Cmd / Status (Cmd if OUT, Status if IN)
+
+This gives 2 possible formats:
+
+
+    Data header:               0LLLLPPP        LLLLLLLL
+    ============
+
+    Where (LLLL,LLLLLLL) is 12-bit length of data that follows for
+    port number (PPP). The length is 0-based (0-FFF means 0-4095
+    bytes). The ~4K limit allows the host driver (which deals in
+    transfer requests instead of individual packets) to write a
+    large chunk of data in a single request. Note, however, that
+    the length must always be <= the current TxCredits for a given
+    port due to buffering limitations on the peripheral.
+
+
+    Cmd/Status header:         1ccccPPP        [ CCCCCCCC,      Params ]...
+    ==================
+
+    Where (cccc) or (cccc,CCCCCCCC) is the cmd or status identifier.
+    Frequently-used values are encoded as (cccc), longer ones using
+    (cccc,CCCCCCCC). Subsequent bytes are optional parameters and are
+    specific to the cmd or status code. This may include a length
+    for command and status codes that need variable-length parameters.
+
+
+In addition, we use another interrupt pipe (endpoint) which the host polls
+periodically for flow control information. The peripheral, when there has
+been a change, sends the following 10-byte packet:
+
+       RRRRRRRRRRRRRRRR
+       T0T0T0T0T0T0T0T0
+       T1T1T1T1T1T1T1T1
+       T2T2T2T2T2T2T2T2
+       T3T3T3T3T3T3T3T3
+
+The first field is the 16-bit RxBytesAvail field, which indicates the
+number of bytes which may be read by the host from EP1. This is necessary:
+(a) because OSR2.1 has a bug which causes data loss if the peripheral returns
+fewer bytes than the host expects to read, and (b) because, on Microsoft
+platforms at least, an outstanding read posted on EP1 consumes about 35% of
+the CPU just polling the device for data.
+
+The next 4 fields are the 16-bit TxCredits for each port, which indicate how
+many bytes the host is allowed to send on EP1 for transmit to a given port.
+After an OPEN_PORT command, the Edgeport sends the initial TxCredits for that
+port.
+
+All 16-bit fields are sent in little-endian (Intel) format.
+
+************************************************************************/
+
+//
+// Define format of InterruptStatus packet returned from the
+// Interrupt pipe
+//
+
+typedef struct _INT_STATUS_PKT {
+       __u16      RxBytesAvail;                    // Additional bytes available to
+                                                   // be read from Bulk IN pipe
+       __u16      TxCredits[ MAX_RS232_PORTS ];   // Additional space available in
+                                                   // given port's TxBuffer
+} INT_STATUS_PKT, *PINT_STATUS_PKT;
+
+
+#define GET_INT_STATUS_SIZE(NumPorts) (sizeof(__u16) + (sizeof(__u16) * (NumPorts)))
+
+
+
+//
+// Define cmd/status header values and macros to extract them.
+//
+//     Data:           0LLLLPPP LLLLLLLL
+//     Cmd/Stat:       1ccccPPP CCCCCCCC
+
+#define        IOSP_DATA_HDR_SIZE              2
+#define        IOSP_CMD_HDR_SIZE               2
+
+#define        IOSP_MAX_DATA_LENGTH            0x0FFF          // 12 bits -> 4K
+
+#define        IOSP_PORT_MASK                  0x07            // Mask to isolate port number
+#define        IOSP_CMD_STAT_BIT               0x80            // If set, this is command/status header
+
+#define IS_CMD_STAT_HDR(Byte1)         ((Byte1) & IOSP_CMD_STAT_BIT)
+#define IS_DATA_HDR(Byte1)             (! IS_CMD_STAT_HDR(Byte1))
+
+#define        IOSP_GET_HDR_PORT(Byte1)                ((__u8) ((Byte1) & IOSP_PORT_MASK))
+#define        IOSP_GET_HDR_DATA_LEN(Byte1, Byte2)     ((__u16) ( ((__u16)((Byte1) & 0x78)) << 5) | (Byte2))
+#define        IOSP_GET_STATUS_CODE(Byte1)             ((__u8) (((Byte1) &  0x78) >> 3))
+
+
+//
+// These macros build the 1st and 2nd bytes for a data header
+//
+#define        IOSP_BUILD_DATA_HDR1(Port, Len)         ((__u8) (((Port) | ((__u8) (((__u16) (Len)) >> 5) & 0x78 ))))
+#define        IOSP_BUILD_DATA_HDR2(Port, Len)         ((__u8) (Len))
+
+
+//
+// These macros build the 1st and 2nd bytes for a command header
+//
+#define        IOSP_BUILD_CMD_HDR1(Port, Cmd)          ((__u8) ( IOSP_CMD_STAT_BIT | (Port) |  ((__u8) ((Cmd) << 3)) ))
+
+
+//--------------------------------------------------------------
+//
+//     Define values for commands and command parameters
+//     (sent from Host to Edgeport)
+//
+//     1ccccPPP P1P1P1P1 [ P2P2P2P2P2 ]...
+//
+//     cccc:   00-07   2-byte commands. Write UART register 0-7 with
+//                                     value in P1. See 16650.H for definitions of
+//                                     UART register numbers and contents.
+//
+//             08-0B   3-byte commands:                                        ==== P1 ====    ==== P2 ====
+//                                     08      available for expansion
+//                                     09      1-param commands                Command Code    Param
+//                                     0A      available for expansion
+//                                     0B      available for expansion
+//
+//             0C-0D   4-byte commands.        P1 = extended cmd and P2,P3 = params
+//                                             Currently unimplemented.
+//
+//             0E-0F   N-byte commands:        P1 = num bytes after P1 (ie, TotalLen - 2)
+//                                             P2 = extended cmd, P3..Pn = parameters.
+//                                             Currently unimplemented.
+//
+
+#define        IOSP_WRITE_UART_REG(n)  ((n) & 0x07)    // UartReg[ n ] := P1
+
+// Register numbers and contents
+// defined in 16554.H.
+
+//                                     0x08            // Available for expansion.
+#define        IOSP_EXT_CMD                    0x09            // P1 = Command code (defined below)
+
+// P2 = Parameter
+
+//
+// Extended Command values, used with IOSP_EXT_CMD, may
+// or may not use parameter P2.
+//
+
+#define        IOSP_CMD_OPEN_PORT              0x00            // Enable ints, init UART. (NO PARAM)
+#define        IOSP_CMD_CLOSE_PORT             0x01            // Disable ints, flush buffers. (NO PARAM)
+#define        IOSP_CMD_CHASE_PORT             0x02            // Wait for Edgeport TX buffers to empty. (NO PARAM)
+#define IOSP_CMD_SET_RX_FLOW           0x03            // Set Rx Flow Control in Edgeport
+#define IOSP_CMD_SET_TX_FLOW           0x04            // Set Tx Flow Control in Edgeport
+#define IOSP_CMD_SET_XON_CHAR          0x05            // Set XON Character in Edgeport
+#define IOSP_CMD_SET_XOFF_CHAR         0x06            // Set XOFF Character in Edgeport
+#define IOSP_CMD_RX_CHECK_REQ          0x07            // Request Edgeport to insert a Checkpoint into
+
+// the receive data stream (Parameter = 1 byte sequence number)
+
+#define IOSP_CMD_SET_BREAK             0x08            // Turn on the BREAK (LCR bit 6)
+#define IOSP_CMD_CLEAR_BREAK           0x09            // Turn off the BREAK (LCR bit 6)
+
+
+//
+// Define macros to simplify building of IOSP cmds
+//
+
+#define        MAKE_CMD_WRITE_REG(ppBuf, pLen, Port, Reg, Val)                                         \
+       do {                                                                                    \
+               (*(ppBuf))[0] = IOSP_BUILD_CMD_HDR1( (Port), IOSP_WRITE_UART_REG(Reg) );        \
+               (*(ppBuf))[1] = (Val);                                                          \
+                                                                                               \
+               *ppBuf += 2;                                                                    \
+               *pLen  += 2;                                                                    \
+       } while (0)
+
+#define        MAKE_CMD_EXT_CMD(ppBuf, pLen, Port, ExtCmd, Param)                                      \
+       do {                                                                                    \
+               (*(ppBuf))[0] = IOSP_BUILD_CMD_HDR1( (Port), IOSP_EXT_CMD );                    \
+               (*(ppBuf))[1] = (ExtCmd);                                                       \
+               (*(ppBuf))[2] = (Param);                                                        \
+                                                                                               \
+               *ppBuf += 3;                                                                    \
+               *pLen  += 3;                                                                    \
+       } while (0)
+
+
+
+//--------------------------------------------------------------
+//
+//     Define format of flow control commands
+//     (sent from Host to Edgeport)
+//
+//     11001PPP FlowCmd FlowTypes
+//
+//     Note that the 'FlowTypes' parameter is a bit mask; that is,
+//     more than one flow control type can be active at the same time.
+//     FlowTypes = 0 means 'no flow control'.
+//
+
+//
+//     IOSP_CMD_SET_RX_FLOW
+//
+//     Tells Edgeport how it can stop incoming UART data
+//
+//  Example for Port 0
+//     P0 = 11001000
+//  P1 = IOSP_CMD_SET_RX_FLOW
+//  P2 = Bit mask as follows:
+
+#define IOSP_RX_FLOW_RTS               0x01    // Edgeport drops RTS to stop incoming data
+#define IOSP_RX_FLOW_DTR               0x02    // Edgeport drops DTR to stop incoming data
+#define IOSP_RX_FLOW_DSR_SENSITIVITY   0x04    // Ignores Rx data unless DSR high
+
+// Not currently implemented by firmware.
+#define IOSP_RX_FLOW_XON_XOFF          0x08    // Edgeport sends XOFF char to stop incoming data.
+
+// Host must have previously programmed the
+// XON/XOFF values with SET_XON/SET_XOFF
+// before enabling this bit.
+
+//
+//     IOSP_CMD_SET_TX_FLOW
+//
+//     Tells Edgeport what signal(s) will stop it from transmitting UART data
+//
+//  Example for Port 0
+//     P0 = 11001000
+//  P1 = IOSP_CMD_SET_TX_FLOW
+//  P2 = Bit mask as follows:
+
+#define IOSP_TX_FLOW_CTS               0x01    // Edgeport stops Tx if CTS low
+#define IOSP_TX_FLOW_DSR               0x02    // Edgeport stops Tx if DSR low
+#define IOSP_TX_FLOW_DCD               0x04    // Edgeport stops Tx if DCD low
+#define IOSP_TX_FLOW_XON_XOFF          0x08    // Edgeport stops Tx upon receiving XOFF char.
+
+// Host must have previously programmed the
+// XON/XOFF values with SET_XON/SET_XOFF
+// before enabling this bit.
+#define IOSP_TX_FLOW_XOFF_CONTINUE     0x10    // If not set, Edgeport stops Tx when
+
+// sending XOFF in order to fix broken
+// systems that interpret the next
+// received char as XON.
+// If set, Edgeport continues Tx
+// normally after transmitting XOFF.
+// Not currently implemented by firmware.
+#define IOSP_TX_TOGGLE_RTS             0x20    // Edgeport drives RTS as a true half-duplex
+
+// Request-to-Send signal: it is raised before
+// beginning transmission and lowered after
+// the last Tx char leaves the UART.
+// Not currently implemented by firmware.
+
+//
+//     IOSP_CMD_SET_XON_CHAR
+//
+//     Sets the character which Edgeport transmits/interprets as XON.
+//     Note: This command MUST be sent before sending a SET_RX_FLOW or
+//     SET_TX_FLOW with the XON_XOFF bit set.
+//
+//  Example for Port 0
+//     P0 = 11001000
+//  P1 = IOSP_CMD_SET_XON_CHAR
+//  P2 = 0x11
+
+
+//
+//     IOSP_CMD_SET_XOFF_CHAR
+//
+//     Sets the character which Edgeport transmits/interprets as XOFF.
+//     Note: This command must be sent before sending a SET_RX_FLOW or
+//     SET_TX_FLOW with the XON_XOFF bit set.
+//
+//  Example for Port 0
+//     P0 = 11001000
+//  P1 = IOSP_CMD_SET_XOFF_CHAR
+//  P2 = 0x13
+
+
+//
+//     IOSP_CMD_RX_CHECK_REQ
+//
+//  This command is used to assist in the implementation of the 
+//  IOCTL_SERIAL_PURGE Windows IOCTL.  
+//  This IOSP command tries to place a marker at the end of the RX 
+//  queue in the Edgeport. If the Edgeport RX queue is full then 
+//  the Check will be discarded.  
+//  It is up to the device driver to timeout waiting for the 
+//  RX_CHECK_RSP.  If a RX_CHECK_RSP is received, the driver is 
+//     sure that all data has been received from the edgeport and 
+//     may now purge any internal RX buffers.
+//  Note tat the sequence numbers may be used to detect lost 
+//  CHECK_REQs.
+
+//  Example for Port 0
+//     P0 = 11001000
+//  P1 = IOSP_CMD_RX_CHECK_REQ
+//  P2 = Sequence number
+
+
+//  Response will be:
+//  P1 = IOSP_EXT_RX_CHECK_RSP
+//  P2 = Request Sequence number
+
+
+
+//--------------------------------------------------------------
+//
+//     Define values for status and status parameters
+//     (received by Host from Edgeport)
+//
+//     1ssssPPP P1P1P1P1 [ P2P2P2P2P2 ]...
+//
+//     ssss:   00-07   2-byte status.  ssss identifies which UART register
+//                                     has changed value, and the new value is in P1.
+//                                     Note that the ssss values do not correspond to the
+//                                     16554 register numbers given in 16554.H. Instead,
+//                                     see below for definitions of the ssss numbers
+//                                     used in this status message.
+//
+//             08-0B   3-byte status:                                  ==== P1 ====    ==== P2 ====
+//                                     08      LSR_DATA:               New LSR         Errored byte
+//                                     09      1-param responses       Response Code   Param
+//                                     0A      OPEN_RSP:               InitialMsr      TxBufferSize
+//                                     0B      available for expansion
+//
+//             0C-0D   4-byte status.  P1 = extended status code and P2,P3 = params
+//                                     Not currently implemented.
+//
+//             0E-0F   N-byte status:  P1 = num bytes after P1 (ie, TotalLen - 2)
+//                                     P2 = extended status, P3..Pn = parameters.
+//                                     Not currently implemented.
+//
+
+/****************************************************
+ *     SSSS values for 2-byte status messages (0-8)
+ ****************************************************/
+
+#define        IOSP_STATUS_LSR                 0x00    // P1 is new value of LSR register.
+
+// Bits defined in 16554.H. Edgeport
+// returns this in order to report
+// line status errors (overrun,
+// parity, framing, break). This form
+// is used when a errored receive data
+// character was NOT present in the
+// UART when the LSR error occurred
+// (ie, when LSR bit 0 = 0).
+
+#define        IOSP_STATUS_MSR                 0x01    // P1 is new value of MSR register.
+
+// Bits defined in 16554.H. Edgeport
+// returns this in order to report
+// changes in modem status lines
+// (CTS, DSR, RI, CD)
+// 
+
+//                                     0x02    // Available for future expansion
+//                                     0x03    // 
+//                                     0x04    // 
+//                                     0x05    // 
+//                                     0x06    // 
+//                                     0x07    // 
+
+
+/****************************************************
+ *     SSSS values for 3-byte status messages (8-A)
+ ****************************************************/
+
+#define        IOSP_STATUS_LSR_DATA            0x08    // P1 is new value of LSR register (same as STATUS_LSR)
+
+// P2 is errored character read from
+//    RxFIFO after LSR reported an error.                                                                                                      
+
+#define        IOSP_EXT_STATUS                 0x09    // P1 is status/response code, param in P2.
+
+
+// Response Codes (P1 values) for 3-byte status messages
+
+#define        IOSP_EXT_STATUS_CHASE_RSP       0       // Reply to CHASE_PORT cmd. P2 is outcome:
+#define        IOSP_EXT_STATUS_CHASE_PASS      0       //      P2 = 0: All Tx data drained successfully
+#define        IOSP_EXT_STATUS_CHASE_FAIL      1       //      P2 = 1: Timed out (stuck due to flow
+
+//                     control from remote device).
+
+#define        IOSP_EXT_STATUS_RX_CHECK_RSP    1       // Reply to RX_CHECK cmd. P2 is sequence number
+
+
+#define IOSP_STATUS_OPEN_RSP           0x0A    // Reply to OPEN_PORT cmd.
+
+// P1 is Initial MSR value
+// P2 is encoded TxBuffer Size:
+//     TxBufferSize = (P2 + 1) * 64
+
+//                                     0x0B    // Available for future expansion
+
+#define GET_TX_BUFFER_SIZE(P2) (((P2) + 1) * 64)
+
+
+
+
+/****************************************************
+ *     SSSS values for 4-byte status messages
+ ****************************************************/
+
+#define IOSP_EXT4_STATUS               0x0C    // Extended status code in P1,
+
+// Params in P2, P3
+// Currently unimplemented.
+
+//                                     0x0D    // Currently unused, available.
+
+
+
+//
+// Macros to parse status messages
+//
+
+#define        IOSP_GET_STATUS_LEN(code)       ( (code) < 8 ? 2 : ((code) < 0x0A ? 3 : 4) )
+
+#define        IOSP_STATUS_IS_2BYTE(code)      ( (code) < 0x08 )
+#define        IOSP_STATUS_IS_3BYTE(code)      ( ((code) >= 0x08) && ((code) <= 0x0B) )
+#define        IOSP_STATUS_IS_4BYTE(code)      ( ((code) >= 0x0C) && ((code) <= 0x0D) )
+
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
new file mode 100644 (file)
index 0000000..fae51de
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * IO Edgeport Driver tables
+ *
+ *     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.
+ * 
+ */
+
+/* Devices that this driver supports */
+static __u16   ionetworks_vendor_id    = USB_VENDOR_ID_ION;
+static __u16   edgeport_4_id           = ION_DEVICE_ID_EDGEPORT_4;
+static __u16   rapidport_4_id          = ION_DEVICE_ID_RAPIDPORT_4;
+static __u16   edgeport_4t_id          = ION_DEVICE_ID_EDGEPORT_4T;
+static __u16   edgeport_2_id           = ION_DEVICE_ID_EDGEPORT_2;
+static __u16   edgeport_4i_id          = ION_DEVICE_ID_EDGEPORT_4I;
+static __u16   edgeport_2i_id          = ION_DEVICE_ID_EDGEPORT_2I;
+static __u16   edgeport_prl_id         = ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT;
+static __u16   edgeport_421_id         = ION_DEVICE_ID_EDGEPORT_421;
+static __u16   edgeport_21_id          = ION_DEVICE_ID_EDGEPORT_21;
+static __u16   edgeport_8dual_id       = ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU;
+static __u16   edgeport_8_id           = ION_DEVICE_ID_EDGEPORT_8;
+static __u16   edgeport_2din_id        = ION_DEVICE_ID_EDGEPORT_2_DIN;
+static __u16   edgeport_4din_id        = ION_DEVICE_ID_EDGEPORT_4_DIN;
+static __u16   edgeport_16dual_id      = ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU;
+static __u16   edgeport_compat_id      = ION_DEVICE_ID_EDGEPORT_COMPATIBLE;
+static __u16   edgeport_8i_id          = ION_DEVICE_ID_EDGEPORT_8I;
+
+
+/* build up the list of devices that this driver supports */
+struct usb_serial_device_type edgeport_4_device = {
+       name:                   "Edgeport 4",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_4_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              4,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type rapidport_4_device = {
+       name:                   "Rapidport 4",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &rapidport_4_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              4,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_4t_device = {
+       name:                   "Edgeport 4t",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_4t_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              4,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_2_device = {
+       name:                   "Edgeport 2",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_2_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              2,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_4i_device = {
+       name:                   "Edgeport 4i",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_4i_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              4,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_2i_device = {
+       name:                   "Edgeport 2i",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_2i_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              2,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_prl_device = {
+       name:                   "Edgeport Parallel",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_prl_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              1,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_421_device = {
+       name:                   "Edgeport 421",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_421_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              2,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_21_device = {
+       name:                   "Edgeport 21",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_21_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              2,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_8dual_device = {
+       name:                   "Edgeport 8 dual cpu",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_8dual_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              4,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_8_device = {
+       name:                   "Edgeport 8",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_8_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              8,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_2din_device = {
+       name:                   "Edgeport 2din",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_2din_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              2,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_4din_device = {
+       name:                   "Edgeport 4din",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_4din_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              4,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_16dual_device = {
+       name:                   "Edgeport 16 dual cpu",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_16dual_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              8,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_compat_id_device = {
+       name:                   "Edgeport Compatible",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_compat_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              4,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+struct usb_serial_device_type edgeport_8i_device = {
+       name:                   "Edgeport 8i",
+       idVendor:               &ionetworks_vendor_id,
+       idProduct:              &edgeport_8i_id,
+       needs_interrupt_in:     MUST_HAVE,
+       needs_bulk_in:          MUST_HAVE,
+       needs_bulk_out:         MUST_HAVE,
+       num_interrupt_in:       1,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              8,
+       open:                   edge_open,
+       close:                  edge_close,
+       throttle:               edge_throttle,
+       unthrottle:             edge_unthrottle,
+       startup:                edge_startup,
+       shutdown:               edge_shutdown,
+       ioctl:                  edge_ioctl,
+       set_termios:            edge_set_termios,
+       write:                  edge_write,
+       write_room:             edge_write_room,
+       chars_in_buffer:        edge_chars_in_buffer,
+       break_ctl:              edge_break,
+};
+
+
+
+
diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h
new file mode 100644 (file)
index 0000000..9a0f751
--- /dev/null
@@ -0,0 +1,374 @@
+/************************************************************************
+ *
+ *     USBVEND.H               Vendor-specific USB definitions
+ *
+ *     NOTE: This must be kept in sync with the Edgeport firmware and
+ *     must be kept backward-compatible with older firmware.
+ *
+ ************************************************************************
+ *
+ *     Copyright (c) 1998 Inside Out Networks, Inc.
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ ************************************************************************/
+
+#if !defined(_USBVEND_H)
+#define        _USBVEND_H
+
+#ifndef __KERNEL__
+#include "ionprag.h"   /* Extra I/O Networks pragmas */
+
+#include <usbdi.h>
+
+#include "iondef.h"    /* Standard I/O Networks definitions */
+#endif
+
+/************************************************************************
+ *
+ *             D e f i n e s   /   T y p e d e f s
+ *
+ ************************************************************************/
+
+//
+// Definitions of USB product IDs
+// 
+
+#define        USB_VENDOR_ID_ION       0x1608          // Our VID
+
+//
+// Definitions of USB product IDs (PID)
+// We break the USB-defined PID into an OEM Id field (upper 6 bits)
+// and a Device Id (bottom 10 bits). The Device Id defines what
+// device this actually is regardless of what the OEM wants to
+// call it.
+//
+
+// ION-device OEM IDs
+#define        ION_OEM_ID_ION          0               // 00h Inside Out Networks
+#define        ION_OEM_ID_NLYNX        1               // 01h NLynx Systems      
+#define        ION_OEM_ID_GENERIC      2               // 02h Generic OEM
+#define        ION_OEM_ID_MAC          3               // 03h Mac Version
+#define        ION_OEM_ID_MEGAWOLF     4               // 04h Lupusb OEM Mac version (MegaWolf)
+#define        ION_OEM_ID_MULTITECH    5               // 05h Multitech Rapidports
+
+       
+// ION-device Device IDs
+// Product IDs - assigned to match middle digit of serial number
+
+
+// The ION_DEVICE_ID_GENERATION_2 bit (0x20) will be ORed into the existing edgeport
+// PIDs to identify 80251+Netchip hardware.  This will guarantee that if a second
+// generation edgeport device is plugged into a PC with an older (pre 2.0) driver,
+// it will not enumerate.
+
+#define ION_DEVICE_ID_GENERATION_2     0x020   // This bit is set in the PID if this edgeport hardware
+                                                                                                                       // is based on the 80251+Netchip.  
+
+#define EDGEPORT_DEVICE_ID_MASK                        0x3df   // Not including GEN_2 bit
+
+#define        ION_DEVICE_ID_UNCONFIGURED_EDGE_DEVICE  0x000   // In manufacturing only
+#define ION_DEVICE_ID_EDGEPORT_4               0x001   // Edgeport/4 RS232
+//     ION_DEVICE_ID_HUBPORT_7                 0x002   // Hubport/7 (Placeholder, not used by software)
+#define ION_DEVICE_ID_RAPIDPORT_4              0x003   // Rapidport/4
+#define ION_DEVICE_ID_EDGEPORT_4T              0x004   // Edgeport/4 RS232 for Telxon (aka "Fleetport")
+#define ION_DEVICE_ID_EDGEPORT_2               0x005   // Edgeport/2 RS232
+#define ION_DEVICE_ID_EDGEPORT_4I              0x006   // Edgeport/4 RS422
+#define ION_DEVICE_ID_EDGEPORT_2I              0x007   // Edgeport/2 RS422/RS485
+//     ION_DEVICE_ID_HUBPORT_4                 0x008   // Hubport/4 (Placeholder, not used by software)
+//     ION_DEVICE_ID_EDGEPORT_8_HANDBUILT      0x009   // Hand-built Edgeport/8 (Placeholder, used in middle digit of serial number only!)
+//     ION_DEVICE_ID_MULTIMODEM_4X56           0x00A   // MultiTech version of RP/4 (Placeholder, used in middle digit of serial number only!)
+#define        ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT    0x00B   // Edgeport/(4)21 Parallel port (USS720)
+#define        ION_DEVICE_ID_EDGEPORT_421              0x00C   // Edgeport/421 Hub+RS232+Parallel
+#define        ION_DEVICE_ID_EDGEPORT_21               0x00D   // Edgeport/21  RS232+Parallel
+#define ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU      0x00E   // Half of an Edgeport/8 (the kind with 2 EP/4s on 1 PCB)
+#define ION_DEVICE_ID_EDGEPORT_8               0x00F   // Edgeport/8 (single-CPU)
+#define ION_DEVICE_ID_EDGEPORT_2_DIN           0x010   // Edgeport/2 RS232 with Apple DIN connector
+#define ION_DEVICE_ID_EDGEPORT_4_DIN           0x011   // Edgeport/4 RS232 with Apple DIN connector
+#define ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU     0x012   // Half of an Edgeport/16 (the kind with 2 EP/8s)
+#define ION_DEVICE_ID_EDGEPORT_COMPATIBLE      0x013   // Edgeport Compatible, for NCR, Axiohm etc. testing
+#define ION_DEVICE_ID_EDGEPORT_8I              0x014   // Edgeport/8 RS422 (single-CPU)
+
+// These IDs are used by the Edgeport.exe program for uninstalling.
+// 
+#define EDGEPORT_DEVICE_IDS    {0x001, 0x003, 0x004, 0x005, 0x006, 0x007, 0x00B, \
+                                0x00C, 0x00D, 0x00E, 0x00F, 0x010, 0x011, 0x012, \
+                                0x013, 0x014 }
+
+
+#define        MAKE_USB_PRODUCT_ID( OemId, DeviceId )                                  \
+                       ( (__u16) (((OemId) << 10) || (DeviceId)) )
+
+#define        DEVICE_ID_FROM_USB_PRODUCT_ID( ProductId )                              \
+                       ( (__u16) ((ProductId) & (EDGEPORT_DEVICE_ID_MASK)) )
+
+#define        OEM_ID_FROM_USB_PRODUCT_ID( ProductId )                                 \
+                       ( (__u16) (((ProductId) >> 10) & 0x3F) )
+
+//
+// Definitions of parameters for download code. Note that these are
+// specific to a given version of download code and must change if the
+// corresponding download code changes.
+//
+
+// TxCredits value below which driver won't bother sending (to prevent too many small writes).
+// Send only if above 25%
+#define EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(InitialCredit)   (max( ((InitialCredit) / 4), EDGE_FW_BULK_MAX_PACKET_SIZE ))
+
+#define        EDGE_FW_BULK_MAX_PACKET_SIZE            64      // Max Packet Size for Bulk In Endpoint (EP1)
+#define EDGE_FW_BULK_READ_BUFFER_SIZE          1024    // Size to use for Bulk reads
+
+#define        EDGE_FW_INT_MAX_PACKET_SIZE             32      // Max Packet Size for Interrupt In Endpoint
+                                                       // Note that many units were shipped with MPS=16, we
+                                                       // force an upgrade to this value).
+#define EDGE_FW_INT_INTERVAL                   2       // 2ms polling on IntPipe
+
+
+//
+// Definitions of I/O Networks vendor-specific requests
+// for default endpoint
+//
+//     bmRequestType = 00100000        Set vendor-specific, to device
+//     bmRequestType = 10100000        Get vendor-specific, to device
+//
+// These are the definitions for the bRequest field for the
+// above bmRequestTypes.
+//
+// For the read/write Edgeport memory commands, the parameters
+// are as follows:
+//             wValue = 16-bit address
+//             wIndex = unused (though we could put segment 00: or FF: here)
+//             wLength = # bytes to read/write (max 64)
+//                                                     
+
+#define USB_REQUEST_ION_RESET_DEVICE   0       // Warm reboot Edgeport, retaining USB address
+#define USB_REQUEST_ION_GET_EPIC_DESC  1       // Get Edgeport Compatibility Descriptor
+// unused                              2       // Unused, available
+#define USB_REQUEST_ION_READ_RAM       3       // Read  EdgePort RAM at specified addr
+#define USB_REQUEST_ION_WRITE_RAM      4       // Write EdgePort RAM at specified addr
+#define USB_REQUEST_ION_READ_ROM       5       // Read  EdgePort ROM at specified addr
+#define USB_REQUEST_ION_WRITE_ROM      6       // Write EdgePort ROM at specified addr
+#define USB_REQUEST_ION_EXEC_DL_CODE   7       // Begin execution of RAM-based download
+                                               // code by jumping to address in wIndex:wValue
+//                                     8       // Unused, available
+#define USB_REQUEST_ION_ENABLE_SUSPEND 9       // Enable/Disable suspend feature
+                                               // (wValue != 0: Enable; wValue = 0: Disable)
+
+
+//
+// Define parameter values for our vendor-specific commands
+//
+
+
+// Values for iDownloadFile
+#define        EDGE_DOWNLOAD_FILE_NONE         0       // No download requested
+#define        EDGE_DOWNLOAD_FILE_INTERNAL     0xFF    // Download the file compiled into driver (930 version)
+#define        EDGE_DOWNLOAD_FILE_I930         0xFF    // Download the file compiled into driver (930 version)
+#define        EDGE_DOWNLOAD_FILE_80251        0xFE    // Download the file compiled into driver (80251 version)
+
+
+
+/*
+ *     Special addresses for READ/WRITE_RAM/ROM
+ */
+
+// Version 1 (original) format of DeviceParams
+#define        EDGE_MANUF_DESC_ADDR_V1         0x00FF7F00
+#define        EDGE_MANUF_DESC_LEN_V1          sizeof(EDGE_MANUF_DESCRIPTOR_V1)
+
+// Version 2 format of DeviceParams. This format is longer (3C0h)
+// and starts lower in memory, at the uppermost 1K in ROM.
+#define        EDGE_MANUF_DESC_ADDR            0x00FF7C00
+#define        EDGE_MANUF_DESC_LEN             sizeof(EDGE_MANUF_DESCRIPTOR)
+
+// Boot params descriptor
+#define        EDGE_BOOT_DESC_ADDR             0x00FF7FC0
+#define        EDGE_BOOT_DESC_LEN              sizeof(EDGE_BOOT_DESCRIPTOR)
+
+// Define the max block size that may be read or written
+// in a read/write RAM/ROM command.
+#define        MAX_SIZE_REQ_ION_READ_MEM       ( (__u16) 64 )
+#define        MAX_SIZE_REQ_ION_WRITE_MEM      ( (__u16) 64 )
+
+
+//
+// Notes for the following two ION vendor-specific param descriptors:
+//
+//     1.      These have a standard USB descriptor header so they look like a
+//             normal descriptor.
+//     2.      Any strings in the structures are in USB-defined string
+//             descriptor format, so that they may be separately retrieved,
+//             if necessary, with a minimum of work on the 930. This also
+//             requires them to be in UNICODE format, which, for English at
+//             least, simply means extending each UCHAR into a USHORT.
+//     3.      For all fields, 00 means 'uninitialized'.
+//     4.      All unused areas should be set to 00 for future expansion.
+//
+
+// This structure is ver 2 format. It contains ALL USB descriptors as
+// well as the configuration parameters that were in the original V1
+// structure. It is NOT modified when new boot code is downloaded; rather,
+// these values are set or modified by manufacturing. It is located at
+// xC00-xFBF (length 3C0h) in the ROM.
+// This structure is a superset of the v1 structure and is arranged so
+// that all of the v1 fields remain at the same address. We are just
+// adding more room to the front of the structure to hold the descriptors.
+//
+// The actual contents of this structure are defined in a 930 assembly
+// file, converted to a binary image, and then written by the serialization
+// program. The C definition of this structure just defines a dummy
+// area for general USB descriptors and the descriptor tables (the root
+// descriptor starts at xC00). At the bottom of the structure are the
+// fields inherited from the v1 structure.
+
+#define MAX_SERIALNUMBER_LEN   12
+#define MAX_ASSEMBLYNUMBER_LEN 14
+
+typedef struct _EDGE_MANUF_DESCRIPTOR {
+
+       __u16   RootDescTable[0x10];                    // C00 Root of descriptor tables (just a placeholder)
+       __u8    DescriptorArea[0x2E0];                  // C20 Descriptors go here, up to 2E0h (just a placeholder)
+
+                                                       //     Start of v1-compatible section
+       __u8    Length;                                 // F00 Desc length for what follows, per USB (= C0h )
+       __u8    DescType;                               // F01 Desc type, per USB (=DEVICE type)
+       __u8    DescVer;                                // F02 Desc version/format (currently 2)
+       __u8    NumRootDescEntries;                     // F03 # entries in RootDescTable
+
+       __u8    RomSize;                                // F04 Size of ROM/E2PROM in K
+       __u8    RamSize;                                // F05 Size of external RAM in K
+       __u8    CpuRev;                                 // F06 CPU revision level (chg only if s/w visible)
+       __u8    BoardRev;                               // F07 PCB revision level (chg only if s/w visible)
+
+       __u8    NumPorts;                               // F08 Number of ports
+       __u8    DescDate[3];                            // F09 MM/DD/YY when descriptor template was compiler,
+                                                       //         so host can track changes to USB-only descriptors.
+
+       __u8    SerNumLength;                           // F0C USB string descriptor len
+       __u8    SerNumDescType;                         // F0D USB descriptor type (=STRING type)
+       __u16   SerialNumber[MAX_SERIALNUMBER_LEN];     // F0E "01-01-000100" Unicode Serial Number
+
+       __u8    AssemblyNumLength;                      // F26 USB string descriptor len
+       __u8    AssemblyNumDescType;                    // F27 USB descriptor type (=STRING type)
+       __u16   AssemblyNumber[MAX_ASSEMBLYNUMBER_LEN]; // F28 "350-1000-01-A " assembly number
+
+       __u8    OemAssyNumLength;                       // F44 USB string descriptor len
+       __u8    OemAssyNumDescType;                     // F45 USB descriptor type (=STRING type)
+       __u16   OemAssyNumber[MAX_ASSEMBLYNUMBER_LEN];  // F46 "xxxxxxxxxxxxxx" OEM assembly number
+
+       __u8    ManufDateLength;                        // F62 USB string descriptor len
+       __u8    ManufDateDescType;                      // F63 USB descriptor type (=STRING type)
+       __u16   ManufDate[6];                           // F64 "MMDDYY" manufacturing date
+
+       __u8    Reserved3[0x4D];                        // F70 -- unused, set to 0 --
+
+       __u8    UartType;                               // FBD Uart Type
+       __u8    IonPid;                                 // FBE Product ID, == LSB of USB DevDesc.PID
+                                                       //     (Note: Edgeport/4s before 11/98 will have
+                                                       //              00 here instead of 01)
+       __u8    IonConfig;                              // FBF Config byte for ION manufacturing use
+                                                       // FBF end of structure, total len = 3C0h
+
+} EDGE_MANUF_DESCRIPTOR, *PEDGE_MANUF_DESCRIPTOR;
+
+
+#define MANUF_DESC_VER_1       1       // Original definition of MANUF_DESC
+#define MANUF_DESC_VER_2       2       // Ver 2, starts at xC00h len 3C0h
+
+
+// Uart Types
+// Note: Since this field was added only recently, all Edgeport/4 units
+// shipped before 11/98 will have 00 in this field. Therefore,
+// both 00 and 01 values mean '654.
+#define MANUF_UART_EXAR_654_EARLY      0       // Exar 16C654 in Edgeport/4s before 11/98
+#define MANUF_UART_EXAR_654            1       // Exar 16C654
+#define MANUF_UART_EXAR_2852           2       // Exar 16C2852 
+
+//
+// Note: The CpuRev and BoardRev values do not conform to manufacturing
+// revisions; they are to be incremented only when the CPU or hardware
+// changes in a software-visible way, such that the 930 software or
+// the host driver needs to handle the hardware differently.
+//
+
+// Values of bottom 5 bits of CpuRev & BoardRev for
+// Implementation 0 (ie, 930-based)
+#define        MANUF_CPU_REV_AD4               1       // 930 AD4, with EP1 Rx bug (needs RXSPM)
+#define        MANUF_CPU_REV_AD5               2       // 930 AD5, with above bug (supposedly) fixed
+#define        MANUF_CPU_80251                 0x20    // Intel 80251
+
+
+#define MANUF_BOARD_REV_A              1       // Original version, == Manuf Rev A
+#define MANUF_BOARD_REV_B              2       // Manuf Rev B, wakeup interrupt works
+#define MANUF_BOARD_REV_C              3       // Manuf Rev C, 2/4 ports, rs232/rs422
+#define MANUF_BOARD_REV_GENERATION_2   0x20    // Second generaiton edgeport
+
+
+
+
+// Values of bottom 5 bits of CpuRev & BoardRev for
+// Implementation 1 (ie, 251+Netchip-based)
+#define        MANUF_CPU_REV_1                 1       // C251TB Rev 1 (Need actual Intel rev here)
+
+#define MANUF_BOARD_REV_A              1       // First rev of 251+Netchip design
+
+
+
+#define        MANUF_SERNUM_LENGTH             sizeof(((PEDGE_MANUF_DESCRIPTOR)0)->SerialNumber)
+#define        MANUF_ASSYNUM_LENGTH            sizeof(((PEDGE_MANUF_DESCRIPTOR)0)->AssemblyNumber)
+#define        MANUF_OEMASSYNUM_LENGTH         sizeof(((PEDGE_MANUF_DESCRIPTOR)0)->OemAssyNumber)
+#define        MANUF_MANUFDATE_LENGTH          sizeof(((PEDGE_MANUF_DESCRIPTOR)0)->ManufDate)
+
+#define        MANUF_ION_CONFIG_MASTER         0x80    // 1=Master mode, 0=Normal
+#define        MANUF_ION_CONFIG_DIAG           0x40    // 1=Run h/w diags, 0=norm
+#define        MANUF_ION_CONFIG_DIAG_NO_LOOP   0x20    // As above but no ext loopback test
+
+
+//
+// This structure describes parameters for the boot code, and
+// is programmed along with new boot code. These are values
+// which are specific to a given build of the boot code. It
+// is exactly 64 bytes long and is fixed at address FF:xFC0
+// - FF:xFFF. Note that the 930-mandated UCONFIG bytes are
+// included in this structure.
+//
+typedef struct _EDGE_BOOT_DESCRIPTOR {
+       __u8            Length;                 // C0 Desc length, per USB (= 40h)
+       __u8            DescType;               // C1 Desc type, per USB (= DEVICE type)
+       __u8            DescVer;                // C2 Desc version/format
+       __u8            Reserved1;              // C3 -- unused, set to 0 --
+
+       __u16           BootCodeLength;         // C4 Boot code goes from FF:0000 to FF:(len-1)
+                                               //        (LE format)
+
+       __u8            MajorVersion;           // C6 Firmware version: xx.
+       __u8            MinorVersion;           // C7                   yy.
+       __u16           BuildNumber;            // C8                   zzzz (LE format)
+       
+       __u16           EnumRootDescTable;      // CA Root of ROM-based descriptor table
+       __u8            NumDescTypes;           // CC Number of supported descriptor types
+
+       __u8            Reserved4;              // CD Fix Compiler Packing
+
+       __u16           Capabilities;           // CE-CF Capabilities flags (LE format)
+       __u8            Reserved2[0x28];        // D0 -- unused, set to 0 --
+       __u8            UConfig0;               // F8 930-defined CPU configuration byte 0
+       __u8            UConfig1;               // F9 930-defined CPU configuration byte 1
+       __u8            Reserved3[6];           // FA -- unused, set to 0 --
+                                               // FF end of structure, total len = 80
+
+} EDGE_BOOT_DESCRIPTOR, *PEDGE_BOOT_DESCRIPTOR;
+
+
+#define BOOT_DESC_VER_1                1       // Original definition of BOOT_PARAMS
+#define BOOT_DESC_VER_2                2       // 2nd definition, descriptors not included in boot
+
+
+       // Capabilities flags
+
+#define        BOOT_CAP_RESET_CMD      0x0001  // If set, boot correctly supports ION_RESET_DEVICE
+
+#endif // if !defined()
+
index ba9bd4d6662a7387ae5e144a727ecd079a1baa78..786c37db6811a173cd8d2071e682090c74ef38e2 100644 (file)
@@ -28,6 +28,9 @@
   open source projects.
 
   Change History
+   (04/08/2001) gb
+       Identify version on module load.
+   
     Tue Oct 10 23:15:33 EST 2000 Hugh
       Merged Paul's changes with my USA-49W mods.  Work in progress
       still...
@@ -46,6 +49,7 @@
 */
 
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-
-#define DEBUG
-/*  #ifdef CONFIG_USB_SERIAL_DEBUG */
-       #define DEBUG
-/*  #endif */
 #include <linux/usb.h>
 
+#ifdef CONFIG_USB_SERIAL_DEBUG
+       static int debug = 1;
+#else
+       static int debug;
+#endif
+
 #include "usb-serial.h"
 #include "keyspan.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Hugh Blemings <hugh@linuxcare.com>"
+#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
+
 #define INSTAT_BUFLEN  32
 #define GLOCONT_BUFLEN 64
 
@@ -161,6 +173,10 @@ int keyspan_init (void)
        usb_serial_register (&keyspan_usa28_device);
        usb_serial_register (&keyspan_usa28x_device);
        usb_serial_register (&keyspan_usa49w_device);
+
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
+
        return 0;
 }
 
@@ -1282,7 +1298,21 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
                msg.setPrescaler = 0xff;
        }
 
-       msg.lcr = USA_DATABITS_8 | STOPBITS_5678_1;
+       msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
+       switch (p_priv->cflag & CSIZE) {
+       case CS5:
+               msg.lcr |= USA_DATABITS_5;
+               break;
+       case CS6:
+               msg.lcr |= USA_DATABITS_6;
+               break;
+       case CS7:
+               msg.lcr |= USA_DATABITS_7;
+               break;
+       case CS8:
+               msg.lcr |= USA_DATABITS_8;
+               break;
+       }
        if (p_priv->cflag & PARENB) {
                /* note USA_PARITY_NONE == 0 */
                msg.lcr |= (p_priv->cflag & PARODD)?
@@ -1475,7 +1505,21 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
                //msg.setPrescaler = 0xff;
        }
 
-       msg.lcr = USA_DATABITS_8 | STOPBITS_5678_1;
+       msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
+       switch (p_priv->cflag & CSIZE) {
+       case CS5:
+               msg.lcr |= USA_DATABITS_5;
+               break;
+       case CS6:
+               msg.lcr |= USA_DATABITS_6;
+               break;
+       case CS7:
+               msg.lcr |= USA_DATABITS_7;
+               break;
+       case CS8:
+               msg.lcr |= USA_DATABITS_8;
+               break;
+       }
        if (p_priv->cflag & PARENB) {
                /* note USA_PARITY_NONE == 0 */
                msg.lcr |= (p_priv->cflag & PARODD)?
@@ -1668,3 +1712,10 @@ static void keyspan_shutdown (struct usb_serial *serial)
                kfree(port->private);
        }
 }
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
index 537ad80c929b03aca39640e0aa558b73ab413f6e..8e0b14144d864da18db0b9e0f4f0d06dc05d73d2 100644 (file)
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (04/08/2001) gb
+ *     Identify version on module load.
+ * 
+ * (10/05/2000) gkh
+ *     Fixed bug with urb->dev not being set properly, now that the usb
+ *     core needs it.
+ * 
  * (08/28/2000) gkh
  *     Added locks for SMP safeness.
  *     Fixed MOD_INC and MOD_DEC logic and the ability to open a port more 
 #include <linux/init.h>
 #include <linux/malloc.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/tqueue.h>
+#include <linux/usb.h>
 
 #ifdef CONFIG_USB_SERIAL_DEBUG
-       #define DEBUG
+       static int debug = 1;
 #else
-       #undef DEBUG
+       static int debug;
 #endif
-#include <linux/usb.h>
+
 
 struct ezusb_hex_record {
        __u16 address;
@@ -75,9 +83,15 @@ struct ezusb_hex_record {
 };
 
 #include "keyspan_pda_fw.h"
-
 #include "usb-serial.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>"
+#define DRIVER_DESC "USB Keyspan PDA Converter driver"
+
 struct keyspan_pda_private {
        int                     tx_room;
        int                     tx_throttled;
@@ -112,7 +126,7 @@ static void keyspan_pda_wakeup_write( struct usb_serial_port *port )
        /* wake up other tty processes */
        wake_up_interruptible( &tty->write_wait );
        /* For 2.2.16 backport -- wake_up_interruptible( &tty->poll_wait ); */
-
+       MOD_DEC_USE_COUNT;
 }
 
 static void keyspan_pda_request_unthrottle( struct usb_serial *serial )
@@ -131,7 +145,7 @@ static void keyspan_pda_request_unthrottle( struct usb_serial *serial )
                             NULL,
                             0,
                             2*HZ);
-
+       MOD_DEC_USE_COUNT;
 }
 
 
@@ -180,7 +194,9 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
                        tty = serial->port[0].tty;
                        priv->tx_throttled = 0;
                        /* queue up a wakeup at scheduler time */
-                       queue_task( &priv->wakeup_task, &tq_scheduler );
+                       MOD_INC_USE_COUNT;
+                       if (schedule_task(&priv->wakeup_task) == 0)
+                               MOD_DEC_USE_COUNT;
                        break;
                default:
                        break;
@@ -212,6 +228,7 @@ static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port)
 {
        /* just restart the receive interrupt URB */
        dbg("keyspan_pda_rx_unthrottle port %d", port->number);
+       port->interrupt_in_urb->dev = port->serial->dev;
        if (usb_submit_urb(port->interrupt_in_urb))
                dbg(" usb_submit_urb(read urb) failed");
        return;
@@ -506,6 +523,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user,
                
                priv->tx_room -= count;
 
+               port->write_urb->dev = port->serial->dev;
                if (usb_submit_urb(port->write_urb)) {
                        dbg(" usb_submit_urb(write bulk) failed");
                        spin_unlock_irqrestore (&port->port_lock, flags);
@@ -520,7 +538,9 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user,
 
        if (request_unthrottle) {
                priv->tx_throttled = 1; /* block writers */
-               queue_task( &priv->unthrottle_task, &tq_scheduler );
+               MOD_INC_USE_COUNT;
+               if (schedule_task(&priv->unthrottle_task) == 0)
+                       MOD_DEC_USE_COUNT;
        }
 
        spin_unlock_irqrestore (&port->port_lock, flags);
@@ -546,8 +566,9 @@ static void keyspan_pda_write_bulk_callback (struct urb *urb)
        }
        
        /* queue up a wakeup at scheduler time */
-       queue_task( &priv->wakeup_task, &tq_scheduler );
-
+       MOD_INC_USE_COUNT;
+       if (schedule_task(&priv->wakeup_task) == 0)
+               MOD_DEC_USE_COUNT;
 }
 
 
@@ -627,6 +648,7 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
                        keyspan_pda_set_modem_info(serial, 0);
 
                /*Start reading from the device*/
+               port->interrupt_in_urb->dev = serial->dev;
                if (usb_submit_urb(port->interrupt_in_urb))
                        dbg(__FUNCTION__" - usb_submit_urb(read int) failed");
        } else {
@@ -783,6 +805,8 @@ static int __init keyspan_pda_init (void)
 {
        usb_serial_register (&keyspan_pda_fake_device);
        usb_serial_register (&keyspan_pda_device);
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
        return 0;
 }
 
@@ -797,5 +821,9 @@ static void __exit keyspan_pda_exit (void)
 module_init(keyspan_pda_init);
 module_exit(keyspan_pda_exit);
 
-MODULE_AUTHOR("Brian Warner <warner@lothar.com>");
-MODULE_DESCRIPTION("USB Keyspan PDA Converter driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
index 5366c0a28f9898fa2f368acfb32e72122742e682..d73c548c3286673030633fcb1d28243ffdbb6362 100644 (file)
@@ -1,9 +1,15 @@
 /*
- * keyspan_pda_fw.h
+ * USB Keyspan PDA Firmware
+ *
+ * Copyright (c) 1999, 2000 Brian Warner       <warner@lothar.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.
  *
  * Generated from keyspan_pda.s by ezusb_convert.pl
- * This file is presumed to be under the same copyright as the source file
- * from which it was derived.
+ *
  */
 
 static const struct ezusb_hex_record keyspan_pda_firmware[] = {
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
new file mode 100644 (file)
index 0000000..4ee6237
--- /dev/null
@@ -0,0 +1,884 @@
+/*
+ * MCT (Magic Control Technology Corp.) USB RS232 Converter Driver
+ *
+ *   Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.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 largely derived from the Belkin USB Serial Adapter Driver
+ * (see belkin_sa.[ch]). All of the information about the device was acquired
+ * by using SniffUSB on Windows98. For technical details see mct_u232.h.
+ *
+ * William G. Greathouse and Greg Kroah-Hartman provided great help on how to
+ * do the reverse engineering and how to write a USB serial device driver.
+ *
+ * TO BE DONE, TO BE CHECKED:
+ *   DTR/RTS signal handling may be incomplete or incorrect. I have mainly
+ *   implemented what I have seen with SniffUSB or found in belkin_sa.c.
+ *   For further TODOs check also belkin_sa.c.
+ *
+ * TEST STATUS:
+ *   Basic tests have been performed with minicom/zmodem transfers and
+ *   modem dialing under Linux 2.4.0-test10 (for me it works fine).
+ *
+ * 04-May-2001 Stelian Pop
+ *   - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes
+ *     instead of the device reported 32 (using 32 bytes causes many data
+ *     loss, Windows driver uses 16 too).
+ *
+ * 02-May-2001 Stelian Pop
+ *   - Fixed the baud calculation for Sitecom U232-P25 model
+ *
+ * 08-Apr-2001 gb
+ *   - Identify version on module load.
+ *
+ * 06-Jan-2001 Cornel Ciocirlan 
+ *   - Added support for Sitecom U232-P25 model (Product Id 0x0230)
+ *   - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200)
+ *
+ * 29-Nov-2000 Greg Kroah-Hartman
+ *   - Added device id table to fit with 2.4.0-test11 structure.
+ *   - took out DEAL_WITH_TWO_INT_IN_ENDPOINTS #define as it's not needed
+ *     (lots of things will change if/when the usb-serial core changes to
+ *     handle these issues.
+ *
+ * 27-Nov-2000 Wolfgang Grandegger
+ *   A version for kernel 2.4.0-test10 released to the Linux community 
+ *   (via linux-usb-devel).
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+
+#ifdef CONFIG_USB_SERIAL_DEBUG
+       static int debug = 1;
+#else
+       static int debug;
+#endif
+
+#include "usb-serial.h"
+#include "mct_u232.h"
+
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
+#define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
+
+/*
+ * Some not properly written applications do not handle the return code of
+ * write() correctly. This can result in character losses. A work-a-round
+ * can be compiled in with the following definition. This work-a-round
+ * should _NOT_ be part of an 'official' kernel release, of course!
+ */
+#undef FIX_WRITE_RETURN_CODE_PROBLEM
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+static int write_blocking = 0; /* disabled by default */
+#endif
+
+/*
+ * Function prototypes
+ */
+static int  mct_u232_startup            (struct usb_serial *serial);
+static void mct_u232_shutdown           (struct usb_serial *serial);
+static int  mct_u232_open               (struct usb_serial_port *port,
+                                         struct file *filp);
+static void mct_u232_close              (struct usb_serial_port *port,
+                                         struct file *filp);
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+static int  mct_u232_write              (struct usb_serial_port *port,
+                                         int from_user,
+                                         const unsigned char *buf,
+                                         int count);
+static void mct_u232_write_bulk_callback (struct urb *urb);
+#endif
+static void mct_u232_read_int_callback   (struct urb *urb);
+static void mct_u232_set_termios         (struct usb_serial_port *port,
+                                         struct termios * old);
+static int  mct_u232_ioctl              (struct usb_serial_port *port,
+                                         struct file * file,
+                                         unsigned int cmd,
+                                         unsigned long arg);
+static void mct_u232_break_ctl          (struct usb_serial_port *port,
+                                         int break_state );
+
+/*
+ * All of the device info needed for the MCT USB-RS232 converter.
+ */
+static __u16   mct_u232_vendor_id      = MCT_U232_VID;
+static __u16   mct_u232_product_id     = MCT_U232_PID;
+static __u16   mct_u232_sitecom_id     = MCT_U232_SITECOM_PID;
+static __u16   mct_u232_du_h3sp_id     = MCT_U232_DU_H3SP_PID;
+
+struct usb_serial_device_type mct_u232_device = {
+       name:                "Magic Control Technology USB-RS232",
+       idVendor:            &mct_u232_vendor_id,
+       idProduct:           &mct_u232_product_id,
+       needs_interrupt_in:  MUST_HAVE,  /* 2 interrupt-in endpoints */
+       needs_bulk_in:       MUST_HAVE_NOT,   /* no bulk-in endpoint */
+       needs_bulk_out:      MUST_HAVE,       /* 1 bulk-out endpoint */
+       num_interrupt_in:    2,
+       num_bulk_in:         0,
+       num_bulk_out:        1,
+       num_ports:           1,
+       open:                mct_u232_open,
+       close:               mct_u232_close,
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+       write:               mct_u232_write,
+       write_bulk_callback: mct_u232_write_bulk_callback,
+#endif
+       read_int_callback:   mct_u232_read_int_callback,
+       ioctl:               mct_u232_ioctl,
+       set_termios:         mct_u232_set_termios,
+       break_ctl:           mct_u232_break_ctl,
+       startup:             mct_u232_startup,
+       shutdown:            mct_u232_shutdown,
+};
+
+struct usb_serial_device_type mct_u232_sitecom_device = {
+       name:                "MCT/Sitecom USB-RS232",
+       idVendor:            &mct_u232_vendor_id,
+       idProduct:           &mct_u232_sitecom_id,
+       needs_interrupt_in:  MUST_HAVE,  /* 2 interrupt-in endpoints */
+       needs_bulk_in:       MUST_HAVE_NOT,   /* no bulk-in endpoint */
+       needs_bulk_out:      MUST_HAVE,       /* 1 bulk-out endpoint */
+       num_interrupt_in:    2,
+       num_bulk_in:         0,
+       num_bulk_out:        1,
+       num_ports:           1,
+       open:                mct_u232_open,
+       close:               mct_u232_close,
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+       write:               mct_u232_write,
+       write_bulk_callback: mct_u232_write_bulk_callback,
+#endif
+       read_int_callback:   mct_u232_read_int_callback,
+       ioctl:               mct_u232_ioctl,
+       set_termios:         mct_u232_set_termios,
+       break_ctl:           mct_u232_break_ctl,
+       startup:             mct_u232_startup,
+       shutdown:            mct_u232_shutdown,
+};
+
+struct usb_serial_device_type mct_u232_du_h3sp_device = {
+        name:                "MCT/D-Link DU-H3SP USB BAY",
+       idVendor:            &mct_u232_vendor_id,
+       idProduct:           &mct_u232_du_h3sp_id,
+        needs_interrupt_in:  MUST_HAVE,  /* 2 interrupt-in endpoints */
+        needs_bulk_in:       MUST_HAVE_NOT,   /* no bulk-in endpoint */
+        needs_bulk_out:      MUST_HAVE,       /* 1 bulk-out endpoint */
+        num_interrupt_in:    2,
+        num_bulk_in:         0,
+        num_bulk_out:        1,
+        num_ports:           1,
+        open:                mct_u232_open,
+        close:               mct_u232_close,
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+        write:               mct_u232_write,
+        write_bulk_callback: mct_u232_write_bulk_callback,
+#endif
+        read_int_callback:   mct_u232_read_int_callback,
+        ioctl:               mct_u232_ioctl,
+        set_termios:         mct_u232_set_termios,
+        break_ctl:           mct_u232_break_ctl,
+        startup:             mct_u232_startup,
+        shutdown:            mct_u232_shutdown,
+};
+
+
+
+
+struct mct_u232_private {
+       unsigned long        control_state; /* Modem Line Setting (TIOCM) */
+       unsigned char        last_lcr;      /* Line Control Register */
+       unsigned char        last_lsr;      /* Line Status Register */
+       unsigned char        last_msr;      /* Modem Status Register */
+};
+
+/*
+ * Handle vendor specific USB requests
+ */
+
+#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+
+static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
+       if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID) {
+               switch (value) {
+                       case    300: return 0x01;
+                       case    600: return 0x02; /* this one not tested */
+                       case   1200: return 0x03;
+                       case   2400: return 0x04;
+                       case   4800: return 0x06;
+                       case   9600: return 0x08;
+                       case  19200: return 0x09;
+                       case  38400: return 0x0a;
+                       case  57600: return 0x0b;
+                       case 115200: return 0x0c;
+                       default:     return -1; /* normally not reached */
+               }
+       }
+       else
+               return MCT_U232_BAUD_RATE(value);
+}
+
+static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
+{
+       unsigned int divisor;
+        int rc;
+       divisor = mct_u232_calculate_baud_rate(serial, value);
+        rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                             MCT_U232_SET_BAUD_RATE_REQUEST,
+                            MCT_U232_SET_REQUEST_TYPE,
+                             0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
+                            WDR_TIMEOUT);
+       if (rc < 0)
+               err("Set BAUD RATE %d failed (error = %d)", value, rc);
+       dbg("set_baud_rate: value: %d, divisor: 0x%x", value, divisor);
+        return rc;
+} /* mct_u232_set_baud_rate */
+
+static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
+{
+        int rc;
+        rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                             MCT_U232_SET_LINE_CTRL_REQUEST,
+                            MCT_U232_SET_REQUEST_TYPE,
+                             0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
+                            WDR_TIMEOUT);
+       if (rc < 0)
+               err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
+       dbg("set_line_ctrl: 0x%x", lcr);
+        return rc;
+} /* mct_u232_set_line_ctrl */
+
+static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
+                                  unsigned long control_state)
+{
+        int rc;
+       unsigned char mcr = MCT_U232_MCR_NONE;
+
+       if (control_state & TIOCM_DTR)
+               mcr |= MCT_U232_MCR_DTR;
+       if (control_state & TIOCM_RTS)
+               mcr |= MCT_U232_MCR_RTS;
+
+        rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                             MCT_U232_SET_MODEM_CTRL_REQUEST,
+                            MCT_U232_SET_REQUEST_TYPE,
+                             0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
+                            WDR_TIMEOUT);
+       if (rc < 0)
+               err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
+       dbg("set_modem_ctrl: state=0x%lx ==> mcr=0x%x", control_state, mcr);
+
+        return rc;
+} /* mct_u232_set_modem_ctrl */
+
+static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
+{
+        int rc;
+        rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+                             MCT_U232_GET_MODEM_STAT_REQUEST,
+                            MCT_U232_GET_REQUEST_TYPE,
+                             0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
+                            WDR_TIMEOUT);
+       if (rc < 0) {
+               err("Get MODEM STATus failed (error = %d)", rc);
+               *msr = 0;
+       }
+       dbg("get_modem_stat: 0x%x", *msr);
+        return rc;
+} /* mct_u232_get_modem_stat */
+
+static void mct_u232_msr_to_state(unsigned long *control_state, unsigned char msr)
+{
+       /* Translate Control Line states */
+       if (msr & MCT_U232_MSR_DSR)
+               *control_state |=  TIOCM_DSR;
+       else
+               *control_state &= ~TIOCM_DSR;
+       if (msr & MCT_U232_MSR_CTS)
+               *control_state |=  TIOCM_CTS;
+       else
+               *control_state &= ~TIOCM_CTS;
+       if (msr & MCT_U232_MSR_RI)
+               *control_state |=  TIOCM_RI;
+       else
+               *control_state &= ~TIOCM_RI;
+       if (msr & MCT_U232_MSR_CD)
+               *control_state |=  TIOCM_CD;
+       else
+               *control_state &= ~TIOCM_CD;
+       dbg("msr_to_state: msr=0x%x ==> state=0x%lx", msr, *control_state);
+} /* mct_u232_msr_to_state */
+
+/*
+ * Driver's tty interface functions
+ */
+
+static int mct_u232_startup (struct usb_serial *serial)
+{
+       struct mct_u232_private *priv;
+
+       /* allocate the private data structure */
+       serial->port->private = kmalloc(sizeof(struct mct_u232_private),
+                                       GFP_KERNEL);
+       if (!serial->port->private)
+               return (-1); /* error */
+       priv = (struct mct_u232_private *)serial->port->private;
+       /* set initial values for control structures */
+       priv->control_state = 0;
+       priv->last_lsr = 0;
+       priv->last_msr = 0;
+
+       init_waitqueue_head(&serial->port->write_wait);
+       
+       return (0);
+} /* mct_u232_startup */
+
+
+static void mct_u232_shutdown (struct usb_serial *serial)
+{
+       int i;
+       
+       dbg (__FUNCTION__);
+
+       /* stop reads and writes on all ports */
+       for (i=0; i < serial->num_ports; ++i) {
+               while (serial->port[i].open_count > 0) {
+                       mct_u232_close (&serial->port[i], NULL);
+               }
+               /* My special items, the standard routines free my urbs */
+               if (serial->port[i].private)
+                       kfree(serial->port[i].private);
+       }
+} /* mct_u232_shutdown */
+
+static int  mct_u232_open (struct usb_serial_port *port, struct file *filp)
+{
+       unsigned long flags;
+       struct usb_serial *serial = port->serial;
+       struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+
+       dbg(__FUNCTION__" port %d", port->number);
+
+       spin_lock_irqsave (&port->port_lock, flags);
+       
+       ++port->open_count;
+       MOD_INC_USE_COUNT;
+
+       if (!port->active) {
+               port->active = 1;
+
+               /* Compensate for a hardware bug: although the Sitecom U232-P25
+                * device reports a maximum output packet size of 32 bytes,
+                * it seems to be able to accept only 16 bytes (and that's what
+                * SniffUSB says too...)
+                */
+               if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID)
+                       port->bulk_out_size = 16;
+
+               /* Do a defined restart: the normal serial device seems to 
+                * always turn on DTR and RTS here, so do the same. I'm not
+                * sure if this is really necessary. But it should not harm
+                * either.
+                */
+               if (port->tty->termios->c_cflag & CBAUD)
+                       priv->control_state = TIOCM_DTR | TIOCM_RTS;
+               else
+                       priv->control_state = 0;
+               mct_u232_set_modem_ctrl(serial, priv->control_state);
+               
+               priv->last_lcr = (MCT_U232_DATA_BITS_8 | 
+                                 MCT_U232_PARITY_NONE |
+                                 MCT_U232_STOP_BITS_1);
+               mct_u232_set_line_ctrl(serial, priv->last_lcr);
+
+               /* Read modem status and update control state */
+               mct_u232_get_modem_stat(serial, &priv->last_msr);
+               mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
+
+               {
+                       /* Puh, that's dirty */
+                       struct usb_serial_port *rport;  
+                       rport = &serial->port[1];
+                       rport->tty = port->tty;
+                       rport->private = port->private;
+                       port->read_urb = rport->interrupt_in_urb;
+               }
+
+               port->read_urb->dev = port->serial->dev;
+               if (usb_submit_urb(port->read_urb))
+                       err("usb_submit_urb(read bulk) failed");
+
+               port->interrupt_in_urb->dev = port->serial->dev;
+               if (usb_submit_urb(port->interrupt_in_urb))
+                       err(" usb_submit_urb(read int) failed");
+
+       }
+
+       spin_unlock_irqrestore (&port->port_lock, flags);
+       
+       return 0;
+} /* mct_u232_open */
+
+
+static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
+{
+       unsigned long flags;
+
+       dbg(__FUNCTION__" port %d", port->number);
+
+       spin_lock_irqsave (&port->port_lock, flags);
+
+       --port->open_count;
+       MOD_DEC_USE_COUNT;
+
+       if (port->open_count <= 0) {
+               /* shutdown our bulk reads and writes */
+               usb_unlink_urb (port->write_urb);
+               usb_unlink_urb (port->read_urb);
+               /* wgg - do I need this? I think so. */
+               usb_unlink_urb (port->interrupt_in_urb);
+               port->active = 0;
+       }
+       
+       spin_unlock_irqrestore (&port->port_lock, flags);
+
+} /* mct_u232_close */
+
+
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+/* The generic routines work fine otherwise */
+
+static int mct_u232_write (struct usb_serial_port *port, int from_user,
+                          const unsigned char *buf, int count)
+{
+       struct usb_serial *serial = port->serial;
+       unsigned long flags;
+       int result, bytes_sent, size;
+
+       dbg(__FUNCTION__ " - port %d", port->number);
+
+       if (count == 0) {
+               dbg(__FUNCTION__ " - write request of 0 bytes");
+               return (0);
+       }
+
+       /* only do something if we have a bulk out endpoint */
+       if (!serial->num_bulk_out)
+               return(0);;
+       
+       /* another write is still pending? */
+       if (port->write_urb->status == -EINPROGRESS) {
+               dbg (__FUNCTION__ " - already writing");
+               return (0);
+       }
+               
+       bytes_sent = 0;
+       while (count > 0) {
+               
+               spin_lock_irqsave (&port->port_lock, flags);
+               
+               size = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+               
+               usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf);
+               
+               if (from_user) {
+                       copy_from_user(port->write_urb->transfer_buffer, buf, size);
+               }
+               else {
+                       memcpy (port->write_urb->transfer_buffer, buf, size);
+               }
+               
+               /* set up our urb */
+               FILL_BULK_URB(port->write_urb, serial->dev,
+                             usb_sndbulkpipe(serial->dev,
+                                             port->bulk_out_endpointAddress),
+                             port->write_urb->transfer_buffer, size,
+                             ((serial->type->write_bulk_callback) ?
+                              serial->type->write_bulk_callback :
+                              mct_u232_write_bulk_callback),
+                             port);
+               
+               /* send the data out the bulk port */
+               result = usb_submit_urb(port->write_urb);
+               if (result) {
+                       err(__FUNCTION__
+                           " - failed submitting write urb, error %d", result);
+                       spin_unlock_irqrestore (&port->port_lock, flags);
+                       return bytes_sent;
+               }
+
+               spin_unlock_irqrestore (&port->port_lock, flags);
+
+               bytes_sent += size;
+               if (write_blocking)
+                       interruptible_sleep_on(&port->write_wait);
+               else
+                       break;
+
+               buf += size;
+               count -= size;
+       }
+       
+       return bytes_sent;
+} /* mct_u232_write */
+
+static void mct_u232_write_bulk_callback (struct urb *urb)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial *serial = port->serial;
+               struct tty_struct *tty = port->tty;
+
+       dbg(__FUNCTION__ " - port %d", port->number);
+       
+       if (!serial) {
+               dbg(__FUNCTION__ " - bad serial pointer, exiting");
+               return;
+       }
+
+       if (urb->status) {
+               dbg(__FUNCTION__ " - nonzero write bulk status received: %d",
+                   urb->status);
+               return;
+       }
+
+       if (write_blocking) {
+               wake_up_interruptible(&port->write_wait);
+               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+                   tty->ldisc.write_wakeup)
+                       (tty->ldisc.write_wakeup)(tty);
+               wake_up_interruptible(&tty->write_wait);
+               
+       } else {
+               /* from generic_write_bulk_callback */
+               queue_task(&port->tqueue, &tq_immediate);
+               mark_bh(IMMEDIATE_BH);
+       }
+
+       return;
+} /* mct_u232_write_bulk_callback */
+#endif
+
+static void mct_u232_read_int_callback (struct urb *urb)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+       struct usb_serial *serial = port->serial;
+       struct tty_struct *tty;
+       unsigned char *data = urb->transfer_buffer;
+
+        dbg(__FUNCTION__ " - port %d", port->number);
+
+       /* The urb might have been killed. */
+        if (urb->status) {
+                dbg(__FUNCTION__ " - nonzero read bulk status received: %d",
+                   urb->status);
+                return;
+        }
+       if (!serial) {
+               dbg(__FUNCTION__ " - bad serial pointer, exiting");
+               return;
+       }
+       
+       usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+
+       /*
+        * Work-a-round: handle the 'usual' bulk-in pipe here
+        */
+       if (urb->transfer_buffer_length > 2) {
+               int i;
+               tty = port->tty;
+               if (urb->actual_length) {
+                       for (i = 0; i < urb->actual_length ; ++i) {
+                               tty_insert_flip_char(tty, data[i], 0);
+                       }
+                       tty_flip_buffer_push(tty);
+               }
+               /* INT urbs are automatically re-submitted */
+               return;
+       }
+       
+       /*
+        * The interrupt-in pipe signals exceptional conditions (modem line
+        * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
+        */
+       priv->last_msr = data[MCT_U232_MSR_INDEX];
+       
+       /* Record Control Line states */
+       mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
+
+#if 0
+       /* Not yet handled. See belin_sa.c for further information */
+       /* Now to report any errors */
+       priv->last_lsr = data[MCT_U232_LSR_INDEX];
+       /*
+        * fill in the flip buffer here, but I do not know the relation
+        * to the current/next receive buffer or characters.  I need
+        * to look in to this before committing any code.
+        */
+       if (priv->last_lsr & MCT_U232_LSR_ERR) {
+               tty = port->tty;
+               /* Overrun Error */
+               if (priv->last_lsr & MCT_U232_LSR_OE) {
+               }
+               /* Parity Error */
+               if (priv->last_lsr & MCT_U232_LSR_PE) {
+               }
+               /* Framing Error */
+               if (priv->last_lsr & MCT_U232_LSR_FE) {
+               }
+               /* Break Indicator */
+               if (priv->last_lsr & MCT_U232_LSR_BI) {
+               }
+       }
+#endif
+
+       /* INT urbs are automatically re-submitted */
+} /* mct_u232_read_int_callback */
+
+
+static void mct_u232_set_termios (struct usb_serial_port *port,
+                                 struct termios *old_termios)
+{
+       struct usb_serial *serial = port->serial;
+       struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+       unsigned int iflag = port->tty->termios->c_iflag;
+       unsigned int old_iflag = old_termios->c_iflag;
+       unsigned int cflag = port->tty->termios->c_cflag;
+       unsigned int old_cflag = old_termios->c_cflag;
+       
+       /*
+        * Update baud rate
+        */
+       if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
+               /* reassert DTR and (maybe) RTS on transition from B0 */
+               if( (old_cflag & CBAUD) == B0 ) {
+                       dbg(__FUNCTION__ ": baud was B0");
+                       priv->control_state |= TIOCM_DTR;
+                       /* don't set RTS if using hardware flow control */
+                       if (!(old_cflag & CRTSCTS)) {
+                               priv->control_state |= TIOCM_RTS;
+                       }
+                       mct_u232_set_modem_ctrl(serial, priv->control_state);
+               }
+               
+               switch(cflag & CBAUD) {
+               case B0: /* handled below */
+                       break;
+               case B300: mct_u232_set_baud_rate(serial, 300);
+                       break;
+               case B600: mct_u232_set_baud_rate(serial, 600);
+                       break;
+               case B1200: mct_u232_set_baud_rate(serial, 1200);
+                       break;
+               case B2400: mct_u232_set_baud_rate(serial, 2400);
+                       break;
+               case B4800: mct_u232_set_baud_rate(serial, 4800);
+                       break;
+               case B9600: mct_u232_set_baud_rate(serial, 9600);
+                       break;
+               case B19200: mct_u232_set_baud_rate(serial, 19200);
+                       break;
+               case B38400: mct_u232_set_baud_rate(serial, 38400);
+                       break;
+               case B57600: mct_u232_set_baud_rate(serial, 57600);
+                       break;
+               case B115200: mct_u232_set_baud_rate(serial, 115200);
+                       break;
+               default: err("MCT USB-RS232 converter: unsupported baudrate request, using default of 9600");
+                       mct_u232_set_baud_rate(serial, 9600); break;
+               }
+               if ((cflag & CBAUD) == B0 ) {
+                       dbg(__FUNCTION__ ": baud is B0");
+                       /* Drop RTS and DTR */
+                       priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+                       mct_u232_set_modem_ctrl(serial, priv->control_state);
+               }
+       }
+
+       /*
+        * Update line control register (LCR)
+        */
+       if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
+           || (cflag & CSIZE) != (old_cflag & CSIZE)
+           || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
+               
+
+               priv->last_lcr = 0;
+
+               /* set the parity */
+               if (cflag & PARENB)
+                       priv->last_lcr |= (cflag & PARODD) ?
+                               MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
+               else
+                       priv->last_lcr |= MCT_U232_PARITY_NONE;
+
+               /* set the number of data bits */
+               switch (cflag & CSIZE) {
+               case CS5:
+                       priv->last_lcr |= MCT_U232_DATA_BITS_5; break;
+               case CS6:
+                       priv->last_lcr |= MCT_U232_DATA_BITS_6; break;
+               case CS7:
+                       priv->last_lcr |= MCT_U232_DATA_BITS_7; break;
+               case CS8:
+                       priv->last_lcr |= MCT_U232_DATA_BITS_8; break;
+               default:
+                       err("CSIZE was not CS5-CS8, using default of 8");
+                       priv->last_lcr |= MCT_U232_DATA_BITS_8;
+                       break;
+               }
+
+               /* set the number of stop bits */
+               priv->last_lcr |= (cflag & CSTOPB) ?
+                       MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
+
+               mct_u232_set_line_ctrl(serial, priv->last_lcr);
+       }
+       
+       /*
+        * Set flow control: well, I do not really now how to handle DTR/RTS.
+        * Just do what we have seen with SniffUSB on Win98.
+        */
+       if( (iflag & IXOFF) != (old_iflag & IXOFF)
+           || (iflag & IXON) != (old_iflag & IXON)
+           ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
+               
+               /* Drop DTR/RTS if no flow control otherwise assert */
+               if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
+                       priv->control_state |= TIOCM_DTR | TIOCM_RTS;
+               else
+                       priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+               mct_u232_set_modem_ctrl(serial, priv->control_state);
+       }
+} /* mct_u232_set_termios */
+
+
+static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
+{
+       struct usb_serial *serial = port->serial;
+       struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+       unsigned char lcr = priv->last_lcr;
+
+       dbg (__FUNCTION__ "state=%d", break_state);
+
+       if (break_state)
+               lcr |= MCT_U232_SET_BREAK;
+
+       mct_u232_set_line_ctrl(serial, lcr);
+} /* mct_u232_break_ctl */
+
+
+static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
+                          unsigned int cmd, unsigned long arg)
+{
+       struct usb_serial *serial = port->serial;
+       struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+       int ret, mask;
+       
+       dbg (__FUNCTION__ "cmd=0x%x", cmd);
+
+       /* Based on code from acm.c and others */
+       switch (cmd) {
+       case TIOCMGET:
+               return put_user(priv->control_state, (unsigned long *) arg);
+               break;
+
+       case TIOCMSET: /* Turns on and off the lines as specified by the mask */
+       case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
+       case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
+               if ((ret = get_user(mask, (unsigned long *) arg))) return ret;
+
+               if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
+                       /* RTS needs set */
+                       if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
+                           (cmd == TIOCMBIS) )
+                               priv->control_state |=  TIOCM_RTS;
+                       else
+                               priv->control_state &= ~TIOCM_RTS;
+               }
+
+               if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
+                       /* DTR needs set */
+                       if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||
+                           (cmd == TIOCMBIS) )
+                               priv->control_state |=  TIOCM_DTR;
+                       else
+                               priv->control_state &= ~TIOCM_DTR;
+               }
+               mct_u232_set_modem_ctrl(serial, priv->control_state);
+               break;
+                                       
+       case TIOCMIWAIT:
+               /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
+               /* TODO */
+               return( 0 );
+
+       case TIOCGICOUNT:
+               /* return count of modemline transitions */
+               /* TODO */
+               return 0;
+
+       default:
+               dbg(__FUNCTION__ ": arg not supported - 0x%04x",cmd);
+               return(-ENOIOCTLCMD);
+               break;
+       }
+       return 0;
+} /* mct_u232_ioctl */
+
+
+static int __init mct_u232_init (void)
+{
+       usb_serial_register (&mct_u232_device);
+       usb_serial_register (&mct_u232_sitecom_device);
+       usb_serial_register (&mct_u232_du_h3sp_device);
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
+       return 0;
+}
+
+
+static void __exit mct_u232_exit (void)
+{
+       usb_serial_deregister (&mct_u232_device);
+       usb_serial_deregister (&mct_u232_sitecom_device);
+       usb_serial_deregister (&mct_u232_du_h3sp_device);
+}
+
+
+module_init (mct_u232_init);
+module_exit(mct_u232_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+MODULE_PARM(write_blocking, "i");
+MODULE_PARM_DESC(write_blocking, 
+                "The write function will block to write out all data");
+#endif
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
diff --git a/drivers/usb/serial/mct_u232.h b/drivers/usb/serial/mct_u232.h
new file mode 100644 (file)
index 0000000..84e79dd
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * Definitions for MCT (Magic Control Technology) USB-RS232 Converter Driver
+ *
+ *   Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.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 driver is for the device MCT USB-RS232 Converter (25 pin, Model No.
+ * U232-P25) from Magic Control Technology Corp. (there is also a 9 pin
+ * Model No. U232-P9). See http://www.mct.com.tw/p_u232.html for further
+ * information. The properties of this device are listed at the end of this
+ * file. This device is available from various distributors. I know Hana,
+ * http://www.hana.de and D-Link, http://www.dlink.com/products/usb/dsbs25.
+ *
+ * All of the information about the device was acquired by using SniffUSB
+ * on Windows98. The technical details of the reverse engineering are
+ * summarized at the end of this file.
+ */
+
+#ifndef __LINUX_USB_SERIAL_MCT_U232_H
+#define __LINUX_USB_SERIAL_MCT_U232_H
+
+#define MCT_U232_VID                   0x0711  /* Vendor Id */
+#define MCT_U232_PID                   0x0210  /* Original MCT Product Id */
+
+/* U232-P25, Sitecom */
+#define MCT_U232_SITECOM_PID           0x0230  /* Sitecom Product Id */
+
+/* DU-H3SP USB BAY hub */
+
+#define MCT_U232_DU_H3SP_PID           0x0200  /* D-Link DU-H3SP USB BAY */
+
+/*
+ * Vendor Request Interface
+ */
+#define MCT_U232_SET_REQUEST_TYPE      0x40
+#define MCT_U232_GET_REQUEST_TYPE      0xc0
+
+#define MCT_U232_GET_MODEM_STAT_REQUEST 2  /* Get Modem Status Register (MSR) */
+#define MCT_U232_GET_MODEM_STAT_SIZE    1
+
+#define MCT_U232_GET_LINE_CTRL_REQUEST  6  /* Get Line Control Register (LCR) */
+#define MCT_U232_GET_LINE_CTRL_SIZE     1  /* ... not used by this driver */
+
+#define MCT_U232_SET_BAUD_RATE_REQUEST 5  /* Set Baud Rate Divisor */
+#define MCT_U232_SET_BAUD_RATE_SIZE     4
+
+#define MCT_U232_SET_LINE_CTRL_REQUEST 7  /* Set Line Control Register (LCR) */
+#define MCT_U232_SET_LINE_CTRL_SIZE     1
+
+#define MCT_U232_SET_MODEM_CTRL_REQUEST        10 /* Set Modem Control Register (MCR) */
+#define MCT_U232_SET_MODEM_CTRL_SIZE    1
+
+/*
+ * Baud rate (divisor)
+ */
+#define MCT_U232_BAUD_RATE(b)          (115200/b)
+
+/*
+ * Line Control Register (LCR)
+ */
+#define MCT_U232_SET_BREAK              0x40
+
+#define MCT_U232_PARITY_SPACE          0x38
+#define MCT_U232_PARITY_MARK           0x28
+#define MCT_U232_PARITY_EVEN           0x18
+#define MCT_U232_PARITY_ODD            0x08
+#define MCT_U232_PARITY_NONE           0x00
+
+#define MCT_U232_DATA_BITS_5            0x00
+#define MCT_U232_DATA_BITS_6            0x01
+#define MCT_U232_DATA_BITS_7            0x02
+#define MCT_U232_DATA_BITS_8            0x03
+
+#define MCT_U232_STOP_BITS_2            0x04
+#define MCT_U232_STOP_BITS_1            0x00
+
+/*
+ * Modem Control Register (MCR)
+ */
+#define MCT_U232_MCR_NONE               0x8     /* Deactivate DTR and RTS */
+#define MCT_U232_MCR_RTS                0xa     /* Activate RTS */
+#define MCT_U232_MCR_DTR                0x9     /* Activate DTR */
+
+/*
+ * Modem Status Register (MSR)
+ */
+#define MCT_U232_MSR_INDEX              0x0     /* data[index] */
+#define MCT_U232_MSR_CD                 0x80    /* Current CD */
+#define MCT_U232_MSR_RI                 0x40    /* Current RI */
+#define MCT_U232_MSR_DSR                0x20    /* Current DSR */
+#define MCT_U232_MSR_CTS                0x10    /* Current CTS */
+#define MCT_U232_MSR_DCD                0x08    /* Delta CD */
+#define MCT_U232_MSR_DRI                0x04    /* Delta RI */
+#define MCT_U232_MSR_DDSR               0x02    /* Delta DSR */
+#define MCT_U232_MSR_DCTS               0x01    /* Delta CTS */
+
+/*
+ * Line Status Register (LSR)
+ */
+#define MCT_U232_LSR_INDEX              1       /* data[index] */
+#define MCT_U232_LSR_ERR                0x80    /* OE | PE | FE | BI */
+#define MCT_U232_LSR_TEMT               0x40    /* transmit register empty */
+#define MCT_U232_LSR_THRE               0x20    /* transmit holding register empty */
+#define MCT_U232_LSR_BI                 0x10    /* break indicator */
+#define MCT_U232_LSR_FE                 0x08    /* framing error */
+#define MCT_U232_LSR_OE                 0x02    /* overrun error */
+#define MCT_U232_LSR_PE                 0x04    /* parity error */
+#define MCT_U232_LSR_OE                 0x02    /* overrun error */
+#define MCT_U232_LSR_DR                 0x01    /* receive data ready */
+
+
+/* -----------------------------------------------------------------------------
+ * Technical Specification reverse engineered with SniffUSB on Windows98
+ * =====================================================================
+ *
+ *  The technical details of the device have been acquired be using "SniffUSB"
+ *  and the vendor-supplied device driver (version 2.3A) under Windows98. To
+ *  identify the USB vendor-specific requests and to assign them to terminal 
+ *  settings (flow control, baud rate, etc.) the program "SerialSettings" from
+ *  William G. Greathouse has been proven to be very useful. I also used the
+ *  Win98 "HyperTerminal" and "usb-robot" on Linux for testing. The results and 
+ *  observations are summarized below:
+ *
+ *  The USB requests seem to be directly mapped to the registers of a 8250,
+ *  16450 or 16550 UART. The FreeBSD handbook (appendix F.4 "Input/Output
+ *  devices") contains a comprehensive description of UARTs and its registers.
+ *  The bit descriptions are actually taken from there.
+ *
+ *
+ * Baud rate (divisor)
+ * -------------------
+ *
+ *   BmRequestType:  0x4 (0100 0000B)
+ *   bRequest:       0x5
+ *   wValue:         0x0
+ *   wIndex:         0x0
+ *   wLength:        0x4
+ *   Data:           divisor = 115200 / baud_rate
+ *
+ *
+ * Line Control Register (LCR)
+ * ---------------------------
+ *
+ *  BmRequestType:  0x4 (0100 0000B)    0xc (1100 0000B)
+ *  bRequest:       0x7                 0x6
+ *  wValue:         0x0
+ *  wIndex:         0x0
+ *  wLength:        0x1
+ *  Data:           LCR (see below)
+ *
+ *  Bit 7: Divisor Latch Access Bit (DLAB). When set, access to the data
+ *        transmit/receive register (THR/RBR) and the Interrupt Enable Register
+ *        (IER) is disabled. Any access to these ports is now redirected to the
+ *        Divisor Latch Registers. Setting this bit, loading the Divisor
+ *        Registers, and clearing DLAB should be done with interrupts disabled.
+ *  Bit 6: Set Break. When set to "1", the transmitter begins to transmit
+ *        continuous Spacing until this bit is set to "0". This overrides any
+ *        bits of characters that are being transmitted.
+ *  Bit 5: Stick Parity. When parity is enabled, setting this bit causes parity
+ *        to always be "1" or "0", based on the value of Bit 4.
+ *  Bit 4: Even Parity Select (EPS). When parity is enabled and Bit 5 is "0",
+ *        setting this bit causes even parity to be transmitted and expected.
+ *        Otherwise, odd parity is used.
+ *  Bit 3: Parity Enable (PEN). When set to "1", a parity bit is inserted
+ *        between the last bit of the data and the Stop Bit. The UART will also
+ *        expect parity to be present in the received data.
+ *  Bit 2: Number of Stop Bits (STB). If set to "1" and using 5-bit data words,
+ *        1.5 Stop Bits are transmitted and expected in each data word. For
+ *        6, 7 and 8-bit data words, 2 Stop Bits are transmitted and expected.
+ *        When this bit is set to "0", one Stop Bit is used on each data word.
+ *  Bit 1: Word Length Select Bit #1 (WLSB1)
+ *  Bit 0: Word Length Select Bit #0 (WLSB0)
+ *        Together these bits specify the number of bits in each data word.
+ *          1 0  Word Length
+ *          0 0  5 Data Bits
+ *          0 1  6 Data Bits
+ *          1 0  7 Data Bits
+ *          1 1  8 Data Bits
+ *
+ *  SniffUSB observations: Bit 7 seems not to be used. There seem to be two bugs
+ *  in the Win98 driver: the break does not work (bit 6 is not asserted) and the
+ *  sticky parity bit is not cleared when set once. The LCR can also be read
+ *  back with USB request 6 but this has never been observed with SniffUSB.
+ *
+ *
+ * Modem Control Register (MCR)
+ * ----------------------------
+ *
+ *  BmRequestType:  0x4  (0100 0000B)
+ *  bRequest:       0xa
+ *  wValue:         0x0
+ *  wIndex:         0x0
+ *  wLength:        0x1
+ *  Data:           MCR (Bit 4..7, see below)
+ *
+ *  Bit 7: Reserved, always 0.
+ *  Bit 6: Reserved, always 0.
+ *  Bit 5: Reserved, always 0.
+ *  Bit 4: Loop-Back Enable. When set to "1", the UART transmitter and receiver
+ *        are internally connected together to allow diagnostic operations. In
+ *        addition, the UART modem control outputs are connected to the UART
+ *        modem control inputs. CTS is connected to RTS, DTR is connected to
+ *        DSR, OUT1 is connected to RI, and OUT 2 is connected to DCD.
+ *  Bit 3: OUT 2. An auxiliary output that the host processor may set high or
+ *        low. In the IBM PC serial adapter (and most clones), OUT 2 is used
+ *        to tri-state (disable) the interrupt signal from the
+ *        8250/16450/16550 UART.
+ *  Bit 2: OUT 1. An auxiliary output that the host processor may set high or
+ *        low. This output is not used on the IBM PC serial adapter.
+ *  Bit 1: Request to Send (RTS). When set to "1", the output of the UART -RTS
+ *        line is Low (Active).
+ *  Bit 0: Data Terminal Ready (DTR). When set to "1", the output of the UART
+ *        -DTR line is Low (Active).
+ *
+ *  SniffUSB observations: Bit 2 and 4 seem not to be used but bit 3 has been
+ *  seen _always_ set.
+ *
+ *
+ * Modem Status Register (MSR)
+ * ---------------------------
+ *
+ *  BmRequestType:  0xc  (1100 0000B)
+ *  bRequest:       0x2
+ *  wValue:         0x0
+ *  wIndex:         0x0
+ *  wLength:        0x1
+ *  Data:           MSR (see below)
+ *
+ *  Bit 7: Data Carrier Detect (CD). Reflects the state of the DCD line on the
+ *        UART.
+ *  Bit 6: Ring Indicator (RI). Reflects the state of the RI line on the UART.
+ *  Bit 5: Data Set Ready (DSR). Reflects the state of the DSR line on the UART.
+ *  Bit 4: Clear To Send (CTS). Reflects the state of the CTS line on the UART.
+ *  Bit 3: Delta Data Carrier Detect (DDCD). Set to "1" if the -DCD line has
+ *        changed state one more more times since the last time the MSR was
+ *        read by the host.
+ *  Bit 2: Trailing Edge Ring Indicator (TERI). Set to "1" if the -RI line has
+ *        had a low to high transition since the last time the MSR was read by
+ *        the host.
+ *  Bit 1: Delta Data Set Ready (DDSR). Set to "1" if the -DSR line has changed
+ *        state one more more times since the last time the MSR was read by the
+ *        host.
+ *  Bit 0: Delta Clear To Send (DCTS). Set to "1" if the -CTS line has changed
+ *        state one more times since the last time the MSR was read by the
+ *        host.
+ *
+ *  SniffUSB observations: the MSR is also returned as first byte on the
+ *  interrupt-in endpoint 0x83 to signal changes of modem status lines. The USB
+ *  request to read MSR cannot be applied during normal device operation.
+ *
+ *
+ * Line Status Register (LSR)
+ * --------------------------
+ *
+ *  Bit 7   Error in Receiver FIFO. On the 8250/16450 UART, this bit is zero.
+ *         This bit is set to "1" when any of the bytes in the FIFO have one or
+ *         more of the following error conditions: PE, FE, or BI.
+ *  Bit 6   Transmitter Empty (TEMT). When set to "1", there are no words
+ *         remaining in the transmit FIFO or the transmit shift register. The
+ *         transmitter is completely idle.
+ *  Bit 5   Transmitter Holding Register Empty (THRE). When set to "1", the FIFO
+ *         (or holding register) now has room for at least one additional word
+ *         to transmit. The transmitter may still be transmitting when this bit
+ *         is set to "1".
+ *  Bit 4   Break Interrupt (BI). The receiver has detected a Break signal.
+ *  Bit 3   Framing Error (FE). A Start Bit was detected but the Stop Bit did not
+ *         appear at the expected time. The received word is probably garbled.
+ *  Bit 2   Parity Error (PE). The parity bit was incorrect for the word received.
+ *  Bit 1   Overrun Error (OE). A new word was received and there was no room in
+ *         the receive buffer. The newly-arrived word in the shift register is
+ *         discarded. On 8250/16450 UARTs, the word in the holding register is
+ *         discarded and the newly- arrived word is put in the holding register.
+ *  Bit 0   Data Ready (DR). One or more words are in the receive FIFO that the
+ *         host may read. A word must be completely received and moved from the
+ *         shift register into the FIFO (or holding register for 8250/16450
+ *         designs) before this bit is set.
+ *
+ *  SniffUSB observations: the LSR is returned as second byte on the interrupt-in
+ *  endpoint 0x83 to signal error conditions. Such errors have been seen with
+ *  minicom/zmodem transfers (CRC errors).
+ *
+ *
+ * Flow control
+ * ------------
+ *
+ *  SniffUSB observations: no flow control specific requests have been realized
+ *  apart from DTR/RTS settings. Both signals are dropped for no flow control
+ *  but asserted for hardware or software flow control.
+ *
+ *
+ * Endpoint usage
+ * --------------
+ *
+ *  SniffUSB observations: the bulk-out endpoint 0x1 and interrupt-in endpoint
+ *  0x81 is used to transmit and receive characters. The second interrupt-in 
+ *  endpoint 0x83 signals exceptional conditions like modem line changes and 
+ *  errors. The first byte returned is the MSR and the second byte the LSR.
+ *
+ *
+ * Other observations
+ * ------------------
+ *
+ *  Queued bulk transfers like used in visor.c did not work. 
+ *  
+ *
+ * Properties of the USB device used (as found in /var/log/messages)
+ * -----------------------------------------------------------------
+ *
+ *  Manufacturer: MCT Corporation.
+ *  Product: USB-232 Interfact Controller
+ *  SerialNumber: U2S22050
+ *
+ *    Length              = 18
+ *    DescriptorType      = 01
+ *    USB version         = 1.00
+ *    Vendor:Product      = 0711:0210
+ *    MaxPacketSize0      = 8
+ *    NumConfigurations   = 1
+ *    Device version      = 1.02
+ *    Device Class:SubClass:Protocol = 00:00:00
+ *      Per-interface classes
+ *  Configuration:
+ *    bLength             =    9
+ *    bDescriptorType     =   02
+ *    wTotalLength        = 0027
+ *    bNumInterfaces      =   01
+ *    bConfigurationValue =   01
+ *    iConfiguration      =   00
+ *    bmAttributes        =   c0
+ *    MaxPower            =  100mA
+ *
+ *    Interface: 0
+ *    Alternate Setting:  0
+ *      bLength             =    9
+ *      bDescriptorType     =   04
+ *      bInterfaceNumber    =   00
+ *      bAlternateSetting   =   00
+ *      bNumEndpoints       =   03
+ *      bInterface Class:SubClass:Protocol =   00:00:00
+ *      iInterface          =   00
+ *      Endpoint:
+ *       bLength             =    7
+ *       bDescriptorType     =   05
+ *       bEndpointAddress    =   81 (in)
+ *       bmAttributes        =   03 (Interrupt)
+ *       wMaxPacketSize      = 0040
+ *       bInterval           =   02
+ *      Endpoint:
+ *       bLength             =    7
+ *       bDescriptorType     =   05
+ *       bEndpointAddress    =   01 (out)
+ *       bmAttributes        =   02 (Bulk)
+ *       wMaxPacketSize      = 0040
+ *       bInterval           =   00
+ *      Endpoint:
+ *       bLength             =    7
+ *       bDescriptorType     =   05
+ *       bEndpointAddress    =   83 (in)
+ *       bmAttributes        =   03 (Interrupt)
+ *       wMaxPacketSize      = 0002
+ *       bInterval           =   02
+ */
+
+#endif /* __LINUX_USB_SERIAL_MCT_U232_H */
+
index 1d1bd088c6222f4296c46085616e9c3cd2f0d8c4..226ffa557a66a31d3dd84490f3c2f7ba5ef7a41e 100644 (file)
@@ -9,7 +9,14 @@
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
  * Please report both successes and troubles to the author at omninet@kroah.com
+ * 
+ * (04/08/2001) gb
+ *     Identify version on module load.
  *
+ * (10/05/2000) gkh
+ *     Fixed bug with urb->dev not being set properly, now that the usb
+ *     core needs it.
+ * 
  * (08/28/2000) gkh
  *     Added locks for SMP safeness.
  *     Fixed MOD_INC and MOD_DEC logic and the ability to open a port more 
 #include <linux/init.h>
 #include <linux/malloc.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-
+#include <linux/usb.h>
 
 #ifdef CONFIG_USB_SERIAL_DEBUG
-       #define isalpha(x) ( ( x > 96 && x < 123) || ( x > 64 && x < 91) || (x > 47 && x < 58) )
-       #define DEBUG
+       static int debug = 1;
 #else
-       #undef DEBUG
+       static int debug;
 #endif
 
-#include <linux/usb.h>
-
 #include "usb-serial.h"
 
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Anonymous"
+#define DRIVER_DESC "USB ZyXEL omni.net LCD PLUS Driver"
+
 #define ZYXEL_VENDOR_ID                0x0586
 #define ZYXEL_OMNINET_ID       0x1000
 
@@ -129,6 +140,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
        struct usb_serial_port  *wport;
        struct omninet_data     *od;
        unsigned long           flags;
+       int                     result;
 
        if (port_paranoia_check (port, __FUNCTION__))
                return -ENODEV;
@@ -149,7 +161,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
 
                od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
                if( !od ) {
-                       err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct omninet_data));
+                       err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct omninet_data));
                        --port->open_count;
                        port->active = 0;
                        spin_unlock_irqrestore (&port->port_lock, flags);
@@ -162,8 +174,13 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
                wport->tty = port->tty;
 
                /* Start reading from the device */
-               if (usb_submit_urb(port->read_urb))
-                       dbg(__FUNCTION__" - read bulk (%p) failed", port->read_urb);
+               FILL_BULK_URB(port->read_urb, serial->dev, 
+                             usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+                             port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+                             omninet_read_bulk_callback, port);
+               result = usb_submit_urb(port->read_urb);
+               if (result)
+                       err(__FUNCTION__ " - failed submitting read urb, error %d", result);
        }
 
        spin_unlock_irqrestore (&port->port_lock, flags);
@@ -222,6 +239,7 @@ static void omninet_read_bulk_callback (struct urb *urb)
        struct omninet_header   *header = (struct omninet_header *) &data[0];
 
        int i;
+       int result;
 
 //     dbg("omninet_read_bulk_callback");
 
@@ -235,8 +253,7 @@ static void omninet_read_bulk_callback (struct urb *urb)
                return;
        }
 
-#ifdef DEBUG
-       if(header->oh_xxx != 0x30) {
+       if ((debug) && (header->oh_xxx != 0x30)) {
                if (urb->actual_length) {
                        printk (KERN_DEBUG __FILE__ ": omninet_read %d: ", header->oh_len);
                        for (i = 0; i < (header->oh_len + OMNINET_HEADERLEN); i++) {
@@ -245,7 +262,6 @@ static void omninet_read_bulk_callback (struct urb *urb)
                        printk ("\n");
                }
        }
-#endif
 
        if (urb->actual_length && header->oh_len) {
                for (i = 0; i < header->oh_len; i++) {
@@ -255,8 +271,13 @@ static void omninet_read_bulk_callback (struct urb *urb)
        }
 
        /* Continue trying to always read  */
-       if (usb_submit_urb(urb))
-               dbg(__FUNCTION__" - failed resubmitting read urb");
+       FILL_BULK_URB(urb, serial->dev, 
+                     usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+                     urb->transfer_buffer, urb->transfer_buffer_length,
+                     omninet_read_bulk_callback, port);
+       result = usb_submit_urb(urb);
+       if (result)
+               err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 
        return;
 }
@@ -270,11 +291,7 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns
        struct omninet_header   *header = (struct omninet_header *) wport->write_urb->transfer_buffer;
 
        unsigned long           flags;
-/*
-#ifdef DEBUG
-       int i;
-#endif
-*/
+       int                     result;
 
 //     dbg("omninet_write port %d", port->number);
 
@@ -282,18 +299,6 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns
                dbg(__FUNCTION__" - write request of 0 bytes");
                return (0);
        }
-/*
-#ifdef DEBUG
-       printk (KERN_DEBUG __FILE__ ": omninet_write %d: ", count);
-               for (i = 0; i < count; i++) {
-                       if( isalpha(buf[i]) )
-                               printk ("%c ", buf[i]);
-                       else
-                               printk ("%.2x ", buf[i]);
-               }
-               printk ("\n");
-#endif
-*/
        if (wport->write_urb->status == -EINPROGRESS) {
                dbg (__FUNCTION__" - already writing");
                return (0);
@@ -310,6 +315,7 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns
                memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count);
        }
 
+       usb_serial_debug_data (__FILE__, __FUNCTION__, count, wport->write_urb->transfer_buffer);
 
        header->oh_seq  = od->od_outseq++;
        header->oh_len  = count;
@@ -319,8 +325,10 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns
        /* send the data out the bulk port, always 64 bytes */
        wport->write_urb->transfer_buffer_length = 64;
 
-       if (usb_submit_urb(wport->write_urb)) {
-               dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed");
+       wport->write_urb->dev = serial->dev;
+       result = usb_submit_urb(wport->write_urb);
+       if (result) {
+               err(__FUNCTION__ " - failed submitting write urb, error %d", result);
                spin_unlock_irqrestore (&port->port_lock, flags);
                return 0;
        }
@@ -392,6 +400,8 @@ static void omninet_shutdown (struct usb_serial *serial)
 static int __init omninet_init (void)
 {
        usb_serial_register (&zyxel_omninet_device);
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
        return 0;
 }
 
@@ -405,3 +415,9 @@ static void __exit omninet_exit (void)
 module_init(omninet_init);
 module_exit(omninet_exit);
 
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
index 53ca79157c1c4ef404c65445c954915f71416013..99f3392e8a4fb1358ca44b60af42279424140549 100644 (file)
@@ -220,15 +220,24 @@ static inline struct usb_serial* get_usb_serial (struct usb_serial_port *port, c
 
 static inline void usb_serial_debug_data (const char *file, const char *function, int size, const unsigned char *data)
 {
-#ifdef CONFIG_USB_SERIAL_DEBUG
        int i;
+
+       if (!debug)
+               return;
+       
        printk (KERN_DEBUG "%s: %s - length = %d, data = ", file, function, size);
        for (i = 0; i < size; ++i) {
                printk ("%.2x ", data[i]);
        }
        printk ("\n");
-#endif
 }
 
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
+
+
+
 #endif /* ifdef __LINUX_USB_SERIAL_H */
 
index b6a57e1d6e912c6f46ff51beb42512176aa90271..a34c45419480b7d4809d68bdf444a9532fd28a93 100644 (file)
@@ -14,6 +14,9 @@
  * based on a driver by Brad Keryan)
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * 
+ * (04/08/2001) gb
+ *     Identify version on module load.
  *
  * 2001_02_05 gkh
  *     Fixed buffer overflows bug with the generic serial driver.  Thanks to
 #include <linux/list.h>
 #include <linux/smp_lock.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/usb.h>
 
 #ifdef CONFIG_USB_SERIAL_DEBUG
-       #define DEBUG
+       static int debug = 1;
 #else
-       #undef DEBUG
+       static int debug;
 #endif
-#include <linux/usb.h>
-
-/* Module information */
-MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
-MODULE_DESCRIPTION("USB Serial Driver");
 
 #include "usb-serial.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/"
+#define DRIVER_DESC "USB Serial Driver core"
+
 #define MAX(a,b)       (((a)>(b))?(a):(b))
 
 /* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
@@ -296,11 +302,6 @@ static void generic_shutdown               (struct usb_serial *serial);
 #ifdef CONFIG_USB_SERIAL_GENERIC
 static __u16   vendor  = 0x05f9;
 static __u16   product = 0xffff;
-MODULE_PARM(vendor, "i");
-MODULE_PARM_DESC(vendor, "User specified USB idVendor");
-
-MODULE_PARM(product, "i");
-MODULE_PARM_DESC(product, "User specified USB idProduct");
 
 /* All of the device info needed for the Generic Serial Converter */
 static struct usb_serial_device_type generic_device = {
@@ -346,6 +347,7 @@ static struct termios *             serial_termios[SERIAL_TTY_MINORS];
 static struct termios *                serial_termios_locked[SERIAL_TTY_MINORS];
 static struct usb_serial       *serial_table[SERIAL_TTY_MINORS];       /* initially all NULL */
 
+
 LIST_HEAD(usb_serial_driver_list);
 
 
@@ -808,8 +810,6 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns
                spin_lock_irqsave (&port->port_lock, flags);
                count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
 
-               usb_serial_debug_data (__FILE__, __FUNCTION__, count, buf);
-
                if (from_user) {
                        copy_from_user(port->write_urb->transfer_buffer, buf, count);
                }
@@ -817,6 +817,8 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns
                        memcpy (port->write_urb->transfer_buffer, buf, count);
                }  
 
+               usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
+
                /* set up our urb */
                FILL_BULK_URB(port->write_urb, serial->dev, 
                              usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
@@ -1194,6 +1196,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
        /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
        max_endpoints = MAX(num_bulk_in, num_bulk_out);
        max_endpoints = MAX(max_endpoints, num_interrupt_in);
+       max_endpoints = MAX(max_endpoints, serial->num_ports);
        dbg (__FUNCTION__ " - setting up %d port structures for this device", max_endpoints);
        for (i = 0; i < max_endpoints; ++i) {
                port = &serial->port[i];
@@ -1371,8 +1374,10 @@ int usb_serial_init(void)
                err("usb_register failed for the usb-serial driver. Error number %d", result);
                return -1;
        }
-       
-       
+
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
+
        return 0;
 }
 
@@ -1437,3 +1442,17 @@ EXPORT_SYMBOL(usb_serial_deregister);
        EXPORT_SYMBOL(ezusb_set_reset);
 #endif
 
+
+/* Module information */
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+MODULE_PARM(vendor, "i");
+MODULE_PARM_DESC(vendor, "User specified USB idVendor");
+
+MODULE_PARM(product, "i");
+MODULE_PARM_DESC(product, "User specified USB idProduct");
+
index 6e8682d11afc64afb2a8f491feeaddf1fbd6e0cf..0332c23871a342b398f93539f692d4bd65c7f7af 100644 (file)
@@ -10,6 +10,9 @@
  *     (at your option) any later version.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * 
+ * (04/08/2001) gb
+ *     Identify version on module load.
  *
  * (01/21/2000) gkh
  *     Added write_room and chars_in_buffer, as they were previously using the
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/usb.h>
 
 #ifdef CONFIG_USB_SERIAL_DEBUG
-       #define DEBUG
+       static int debug = 1;
 #else
-       #undef DEBUG
+       static int debug;
 #endif
-#include <linux/usb.h>
 
 #include "usb-serial.h"
-
 #include "visor.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
+#define DRIVER_DESC "USB HandSpring Visor driver"
+
 #define MIN(a,b)                (((a)<(b))?(a):(b))
 
 /* function prototypes for a handspring visor */
@@ -149,7 +158,7 @@ struct usb_serial_device_type handspring_device = {
 
 
 #define NUM_URBS                       24
-#define URB_TRANSFER_BUFFER_SIZE       64
+#define URB_TRANSFER_BUFFER_SIZE       768
 static struct urb      *write_urb_pool[NUM_URBS];
 static spinlock_t      write_urb_pool_lock;
 static int             bytes_in;
@@ -644,7 +653,10 @@ static int __init visor_init (void)
                        continue;
                }
        }
-       
+
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
+
        return 0;
 }
 
@@ -677,5 +689,9 @@ static void __exit visor_exit (void)
 module_init(visor_init);
 module_exit(visor_exit);
 
-MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
-MODULE_DESCRIPTION("USB HandSpring Visor driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
index d089b3586bff47c69ee350c9e682c01bc1d77333..79c692a6e73f4781de793cb5d3ea757fc4d7a5eb 100644 (file)
@@ -67,6 +67,8 @@
 #endif
 #include <linux/usb.h>
 
+static int debug;
+
 #include "usb-serial.h"
 
 #include "whiteheat_fw.h"              /* firmware for the ConnectTech WhiteHEAT device */
index e9dfc70e3c975caeea796d69190dede72385b910..3d29eaabaae7b69322e60be937ebab457a478de8 100644 (file)
@@ -1636,6 +1636,11 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
          "Shuttle eUSCSI Bridge", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, 
        { 0x04e6, 0x0006, 0x0100,
          "Shuttle eUSB MMC Adapter", US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN}, 
+       { 0x054c, 0x0010, 0x0210, "Sony DSC", US_SC_SCSI, US_PR_CB, 
+         US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE | US_FL_ALT_LENGTH},
+       { 0x054c, 0x0010, 0x0322,
+         "Sony DSC-S75", US_SC_SCSI, US_PR_CB, 
+         US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE | US_FL_ALT_LENGTH},
        { 0x057b, 0x0000, 0x0114,
          "Y-E Data Flashbuster-U", US_SC_UFI, US_PR_CB, US_FL_SINGLE_LUN},
        { 0x059b, 0x0030, 0x0100,
@@ -1646,6 +1651,8 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
           "Iomega USB Zip 250", US_SC_SCSI, US_PR_BULK, US_FL_SINGLE_LUN},
         { 0x059b, 0x0034, 0x0100,
           "Iomega Zip 100", US_SC_SCSI, US_PR_BULK, US_FL_SINGLE_LUN},
+       { 0x0644, 0x1000, 0x0133,
+         "TEAC CD-210PU", US_SC_8020, US_PR_BULK, US_FL_ALT_LENGTH},
        { 0x0693, 0x0002, 0x0100,
          "Hagiwara FlashGate SmartMedia", US_SC_SCSI, US_PR_BULK,
          US_FL_ALT_LENGTH},
index 22f3b7f3f7608e6534c3ddbd0f1ee4e27dedde26..5dd8d9c9ed1adfc9877b0d335a0aa6eac5a922f6 100644 (file)
@@ -500,6 +500,8 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                (*info->blank)(arg, info);
                return 0;
        default:
+               if (fb->fb_ioctl == NULL)
+                       return -EINVAL;
                return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(info),
                                    info);
        }
index d56d630462d02fd89786b60869804d22f8f1185e..9e8bd41bbe5c66cd942e0b760ac1a38bf70e26e0 100644 (file)
@@ -473,7 +473,7 @@ beyond_if:
        regs->gp = ex.a_gpvalue;
 #endif
        start_thread(regs, ex.a_entry, p);
-       if (current->flags & PF_PTRACED)
+       if (current->ptrace & PT_PTRACED)
                send_sig(SIGTRAP, current, 0);
        return 0;
 }
index 206ddccb07c2c1a2c1a13f557d724ef50fe08f59..f8981a3ca0a7a8f943d395964bb37ab5cdfb98a1 100644 (file)
@@ -799,7 +799,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 #endif
 
        start_thread(regs, elf_entry, bprm->p);
-       if (current->flags & PF_PTRACED)
+       if (current->ptrace & PT_PTRACED)
                send_sig(SIGTRAP, current, 0);
        retval = 0;
 out:
index 498afbb2b69e7001bab12fe9f969d85951e8b14d..434048874d956a3f6634140d17c56182bb9f67a7 100644 (file)
@@ -48,7 +48,7 @@ enum {
 typedef struct binfmt_entry {
        struct binfmt_entry *next;
        long id;
-       int flags;                      /* type, status, etc. */
+       long flags;                     /* type, status, etc. */
        int offset;                     /* offset of magic */
        int size;                       /* size of magic/mask */
        char *magic;                    /* magic or filename extension */
index 74a872db5a783555c748b25d46c5f0b75d1dc2a6..64d49bba48a474dcb76d89f158cf5333d6f6bdad 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -557,7 +557,7 @@ flush_failed:
  */
 static inline int must_not_trace_exec(struct task_struct * p)
 {
-       return (p->flags & PF_PTRACED) && !cap_raised(p->p_pptr->cap_effective, CAP_SYS_PTRACE);
+       return (p->ptrace & PT_PTRACED) && !cap_raised(p->p_pptr->cap_effective, CAP_SYS_PTRACE);
 }
 
 /* 
index 35c55ec235b2220e7155b2b436ec313890a87b62..6588eeda41cf90226e86f7982f6af3fe409ff31e 100644 (file)
@@ -62,7 +62,7 @@ static struct task_struct * get_task(int pid)
                 * that we would allow ptrace to work.
                 */
                if (tsk) {
-                       if (!(tsk->flags & PF_PTRACED)
+                       if (!(tsk->ptrace & PT_PTRACED)
                            || tsk->state != TASK_STOPPED
                            || tsk->p_pptr != current)
                                tsk = NULL;
index ae9c1c4cc2702d638dff1eba6d42b489b158e84f..cfb62dd17aac5947a028ff7b1eef39177344e138 100644 (file)
@@ -1,5 +1,16 @@
 ChangeLog for smbfs.
 
+2001-05-24 Urban Widmark <urban@teststation.com>
+
+       * proc.c: fix smb_proc_open to allow open being called more than once
+         with different modes (O_RDONLY -> O_WRONLY) without closing.
+         (bugfix from 2.4.3, fix by Michael Kockelkorn)
+       * inode.c: tail -f fix for non-readonly opened files
+         (related to the smb_proc_open change).
+         (bugfix from 2.4.3)
+       * inode.c: tail -f fix for fast size changes with the same mtime.
+         (bugfix from 2.4.3)
+
 2000-11-22 Igor Zhbanov <bsg@uniyar.ac.ru>
 
        * proc.c: fixed date_unix2dos for dates earlier than 01/01/1980
index e4cf5171988bfc631fac929edd43daf751a96eaa..c539de2ba90303bdbae4e8e8f64c48203b162ed5 100644 (file)
@@ -242,20 +242,11 @@ smb_revalidate_inode(struct dentry *dentry)
 {
        struct inode *inode = dentry->d_inode;
        time_t last_time;
+       off_t last_sz;
        int error = 0;
 
        DEBUG1("\n");
 
-       /*
-        * If this is a file opened with write permissions,
-        * the inode will be up-to-date.
-        */
-       if (S_ISREG(inode->i_mode) && smb_is_open(inode))
-       {
-               if (inode->u.smbfs_i.access != SMB_O_RDONLY)
-                       goto out;
-       }
-
        /*
         * Check whether we've recently refreshed the inode.
         */
@@ -271,8 +262,9 @@ smb_revalidate_inode(struct dentry *dentry)
         * (Note: a size change should have a different mtime.)
         */
        last_time = inode->i_mtime;
+       last_sz = inode->i_size;
        error = smb_refresh_inode(dentry);
-       if (error || inode->i_mtime != last_time)
+       if (error || inode->i_mtime != last_time || inode->i_size != last_sz)
        {
                VERBOSE("%s/%s changed, old=%ld, new=%ld\n",
                        DENTRY_PATH(dentry),
index ba511314494a0928397fdd5e6a478d9377da9c62..33b05c0a3a4e2fb4016f6036e1b1e605f30deef8 100644 (file)
@@ -890,8 +890,6 @@ retry:
        /* smb_vwv2 has mtime */
        /* smb_vwv4 has size  */
        ino->u.smbfs_i.access = (WVAL(server->packet, smb_vwv6) & SMB_ACCMASK);
-       if (!(wish & (O_WRONLY | O_RDWR)))
-               ino->u.smbfs_i.access = SMB_O_RDONLY;
        ino->u.smbfs_i.open = server->generation;
 
 out:
index 0f4e34b0064740bf5df208d64150201345aded6e..f9a8c10237438e0a2193a137616a11349e697e37 100644 (file)
@@ -589,7 +589,7 @@ out_null:
  * filesystems which don't use real block-devices.  -- jrs
  */
 
-static unsigned int unnamed_dev_in_use[256/(8*sizeof(unsigned int))] = { 0, };
+static unsigned long unnamed_dev_in_use[256/(8*sizeof(unsigned long))] = { 0, };
 
 kdev_t get_unnamed_dev(void)
 {
index d2c53014f246ec1e28d5db3ebcc59ffc96cc168c..86e5e74d520f2caebdfcf1c55bbe0762c450e56c 100644 (file)
@@ -53,4 +53,13 @@ extern struct linux_hose_info *bus2hose[256];
 #define IOBASE_SPARSE_IO        3
 #define IOBASE_DENSE_IO         4
 
+/* Return the index of the PCI controller for device PDEV. */
+static __inline__ int pci_controller_num(struct pci_dev *pdev)
+{
+       if (bus2hose[pdev->bus->number] == NULL)
+               return -ENXIO;
+
+       return bus2hose[pdev->bus->number]->pci_host_index;
+}
+
 #endif /* __ALPHA_PCI_H */
diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h
new file mode 100644 (file)
index 0000000..5fdd4bf
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _ARM_PCI_H
+#define _ARM_PCI_H
+
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)       (0)
+
+#endif /* !(_ARM_PCI_H) */
diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h
new file mode 100644 (file)
index 0000000..088981b
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _I386_PCI_H
+#define _I386_PCI_H
+
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)       (0)
+
+#endif /* !(_I386_PCI_H) */
index 647764bd17421ef335db8e2d023df44513bac9ed..28e3a60aacbe3ee3b2a3ef4125133ed7c9325e9b 100644 (file)
@@ -52,12 +52,12 @@ LFLUSH_I_AND_D = 0x00000808
 LSIGTRAP = 5
 
 /* process bits for task_struct.flags */
-PF_TRACESYS_OFF = 3
-PF_TRACESYS_BIT = 5
-PF_PTRACED_OFF = 3
-PF_PTRACED_BIT = 4
-PF_DTRACE_OFF = 1
-PF_DTRACE_BIT = 5
+PT_TRACESYS_OFF = 3
+PT_TRACESYS_BIT = 5
+PT_PTRACED_OFF = 3
+PT_PTRACED_BIT = 4
+PT_DTRACE_OFF = 1
+PT_DTRACE_BIT = 5
 
 #define SAVE_ALL_INT save_all_int
 #define SAVE_ALL_SYS save_all_sys
index a6d698336a39bf80ac804f18b51163b63cf6912b..62b771b65839b09c33096535676f95c5b4388e01 100644 (file)
 #define TASK_FLAGS         4
 #define TASK_SIGPENDING    8
 #define TASK_NEED_RESCHED  20
-#define TASK_COUNTER       24
-#define TASK_PRIORITY      28
-#define TASK_MM            920
+#define TASK_PTRACE        24
+#define TASK_COUNTER       28
+#define TASK_PRIORITY      32
+#define TASK_MM            924
 
 /* MIPS specific thread_struct offsets. */
 #define THREAD_REG16   560
index 16305751d28204be5c1e657f3652877cedb1499e..a08e1ecc0b1107c0b3f1d27206740ed64ce3728b 100644 (file)
@@ -39,4 +39,7 @@ struct pci_ops {
 
 extern struct pci_ops *pci_ops;
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)       (0)
+
 #endif /* __ASM_MIPS_PCI_H */
index 8b7b8291c80a04c4694a75e900f30f394aa31345..23332e070ebfd0d1d1ad7c8228a7b5a452e1031e 100644 (file)
@@ -9,5 +9,7 @@
 #define IOBASE_MEMORY          1
 #define IOBASE_IO              2
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)       (0)
 
 #endif
diff --git a/include/asm-sparc/pci.h b/include/asm-sparc/pci.h
new file mode 100644 (file)
index 0000000..30e2946
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _SPARC_PCI_H
+#define _SPARC_PCI_H
+
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)       (0)
+
+#endif /* !(_SPARC_PCI_H) */
index 02fa614b944fafa47cd73ff42615d481bb857722..4626264e2d854a157b5aefbf580297b885df0d5b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: siginfo.h,v 1.4 1999/04/28 19:45:20 davem Exp $
+/* $Id: siginfo.h,v 1.4.2.1 2001/03/01 00:49:02 davem Exp $
  * siginfo.c:
  */
 
index c9d1bd029bf35998446d348c16ee5104435c143c..334da5a21b40993da20996ffc8d8e4c36164a735 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.18.2.1 1999/09/10 09:54:34 davem Exp $
+/* $Id: uaccess.h,v 1.18.2.2 2001/03/01 00:49:02 davem Exp $
  * uaccess.h: User space memore access functions.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
index e1096c43a95f29897a0aeb365dbc0fbae60e3a94..c541962821e91f20c58b1bd2e1100027e91494e1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.26.2.1 2000/08/10 23:50:04 davem Exp $
+/* $Id: bitops.h,v 1.26.2.2 2001/06/07 06:19:33 davem Exp $
  * bitops.h: Bit string operations on the V9.
  *
  * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -20,7 +20,7 @@
  * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
  */
 
-extern __inline__ unsigned long test_and_set_bit(unsigned long nr, void *addr)
+extern __inline__ unsigned long test_and_set_bit(unsigned long nr, volatile void *addr)
 {
        unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
        unsigned long oldbit;
@@ -41,7 +41,7 @@ extern __inline__ unsigned long test_and_set_bit(unsigned long nr, void *addr)
        return oldbit != 0;
 }
 
-extern __inline__ void set_bit(unsigned long nr, void *addr)
+extern __inline__ void set_bit(unsigned long nr, volatile void *addr)
 {
        unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
 
@@ -60,7 +60,7 @@ extern __inline__ void set_bit(unsigned long nr, void *addr)
        : "g5", "g7", "cc", "memory");
 }
 
-extern __inline__ unsigned long test_and_clear_bit(unsigned long nr, void *addr)
+extern __inline__ unsigned long test_and_clear_bit(unsigned long nr, volatile void *addr)
 {
        unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
        unsigned long oldbit;
@@ -81,7 +81,7 @@ extern __inline__ unsigned long test_and_clear_bit(unsigned long nr, void *addr)
        return oldbit != 0;
 }
 
-extern __inline__ void clear_bit(unsigned long nr, void *addr)
+extern __inline__ void clear_bit(unsigned long nr, volatile void *addr)
 {
        unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
 
@@ -100,7 +100,7 @@ extern __inline__ void clear_bit(unsigned long nr, void *addr)
        : "g5", "g7", "cc", "memory");
 }
 
-extern __inline__ unsigned long test_and_change_bit(unsigned long nr, void *addr)
+extern __inline__ unsigned long test_and_change_bit(unsigned long nr, volatile void *addr)
 {
        unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
        unsigned long oldbit;
@@ -119,7 +119,7 @@ extern __inline__ unsigned long test_and_change_bit(unsigned long nr, void *addr
        return oldbit != 0;
 }
 
-extern __inline__ void change_bit(unsigned long nr, void *addr)
+extern __inline__ void change_bit(unsigned long nr, volatile void *addr)
 {
        unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
 
@@ -135,7 +135,7 @@ extern __inline__ void change_bit(unsigned long nr, void *addr)
        : "g5", "g7", "cc", "memory");
 }
 
-extern __inline__ unsigned long test_bit(int nr, __const__ void *addr)
+extern __inline__ unsigned long test_bit(int nr, __const__ volatile void *addr)
 {
        return 1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63));
 }
index 12baff70a9f1a3414985e35068fbe1e1e4f16faf..4a7e155e090f7e74dbae65aad9fc78718c013462 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pbm.h,v 1.16.2.1 2000/06/14 07:41:19 davem Exp $
+/* $Id: pbm.h,v 1.16.2.2 2001/05/16 07:28:43 davem Exp $
  * pbm.h: U2P PCI bus module pseudo driver software state.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -64,6 +64,7 @@ struct linux_psycho {
        unsigned long                   *pci_mem_space;
        u32                             upa_portid;
        int                             index;
+       int                             pbms_same_domain;
        struct linux_pbm_info           pbm_A;
        struct linux_pbm_info           pbm_B;
 
diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h
new file mode 100644 (file)
index 0000000..7a3eae8
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _SPARC64_PCI_H
+#define _SPARC64_PCI_H
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+/* Return the index of the PCI controller for device PDEV. */
+
+extern int pci_controller_num(struct pci_dev *pdev);
+
+/* Platform support for /proc/bus/pci/X/Y mmap()s. */
+
+#define HAVE_PCI_MMAP
+
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+                              enum pci_mmap_state mmap_state,
+                              int write_combine);
+
+#endif /* !(_SPARC64_PCI_H) */
index 169e88d0222e668acf8d1be4ba8f8183548dc3bd..0e3e56ee64972dbe17c6ce172ce848ab9498bab1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sab82532.h,v 1.4 1998/10/25 23:04:29 ecd Exp $
+/* $Id: sab82532.h,v 1.4.2.1 2001/05/28 23:13:36 ecd Exp $
  * sab82532.h: Register Definitions for the Siemens SAB82532 DUSCC
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -148,7 +148,7 @@ struct sab82532 {
        int                              close_delay;
        unsigned short                   closing_wait;
        unsigned short                   closing_wait2;
-       int                              all_sent;
+       unsigned long                    irqflags;
        int                              is_console;
        unsigned char                    interrupt_mask0;
        unsigned char                    interrupt_mask1;
@@ -180,6 +180,10 @@ struct sab82532 {
        struct sab82532                 *prev;
 };
 
+/* irqflags bits */
+#define SAB82532_ALLS                  0x00000001
+#define SAB82532_XPR                   0x00000002
+
 
 /* RFIFO Status Byte */
 #define SAB82532_RSTAT_PE              0x80
index 19f2d24de3f3ed61cb204b1cb5d3dd0a697f20cb..71142823ffc146d9c6b266e719c26bcb73b7d272 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.29.2.1 1999/09/10 09:54:38 davem Exp $ */
+/* $Id: uaccess.h,v 1.29.2.2 2001/03/01 00:49:03 davem Exp $ */
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
 
index 2718430f3a9d89edd0016b3fd2464046c4e617df..43ee8ce9122aa9c9dd61db7f7140188c141ebf0a 100644 (file)
@@ -17,7 +17,7 @@
 
 #define        net_device                      device
 #define dev_kfree_skb_irq(a)           dev_kfree_skb(a)
-#define netif_wake_queue(dev)          clear_bit(0, &dev->tbusy)
+#define netif_wake_queue(dev)          do { clear_bit(0, &dev->tbusy); mark_bh(NET_BH); } while(0)
 #define netif_stop_queue(dev)          set_bit(0, &dev->tbusy)
 #define netif_start_queue(dev)         do { dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; } while (0)
 #define netif_queue_stopped(dev)       dev->tbusy
index 856fc0168e9015f3ca6be34f70c6ddcde3bfe5f5..55fddc932201d7be4e5a8ffde88ba73775458cb8 100644 (file)
@@ -166,7 +166,7 @@ struct pardevice {
        struct wait_queue *wait_q;
        unsigned long int time;
        unsigned long int timeslice;
-       unsigned int waiting;
+       unsigned long waiting;
        struct pardevice *waitprev;
        struct pardevice *waitnext;
 };
index d9e09482350c1dca7713f3f2e83f951b412ec3eb..964d6837dd6cdc338fa09abd32de2e05ae7b0f2f 100644 (file)
 #define PCI_SLOT(devfn)                (((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)                ((devfn) & 0x07)
 
+/* Ioctls for /proc/bus/pci/X/Y nodes. */
+#define PCIIOC_BASE            ('P' << 24 | 'C' << 16 | 'I' << 8)
+#define PCIIOC_CONTROLLER      (PCIIOC_BASE | 0x00)    /* Get controller for PCI device. */
+#define PCIIOC_MMAP_IS_IO      (PCIIOC_BASE | 0x01)    /* Set mmap state to I/O space. */
+#define PCIIOC_MMAP_IS_MEM     (PCIIOC_BASE | 0x02)    /* Set mmap state to MEM space. */
+#define PCIIOC_WRITE_COMBINE   (PCIIOC_BASE | 0x03)    /* Enable/disable write-combining. */
+
 #ifdef __KERNEL__
 
 #include <linux/types.h>
 #include <linux/config.h>
 
+/* File state for mmap()s on /proc/bus/pci/X/Y */
+enum pci_mmap_state {
+       pci_mmap_io,
+       pci_mmap_mem
+};
+
 /*
  * There is one pci_dev structure for each slot-number/function-number
  * combination:
@@ -1425,6 +1438,10 @@ extern struct pci_dev    *pci_devices;   /* list of all devices */
 #define PCIBIOS_SET_FAILED             0x88
 #define PCIBIOS_BUFFER_TOO_SMALL       0x89
 
+/* Include architecture-dependent settings and functions */
+
+#include <asm/pci.h>
+
 /* Low-level architecture-dependent routines */
 
 int pcibios_present (void);
index 33471421add273204569da989b2de07b1b3c36ca..f93e09e4813cb40a7aa56d0101b297af3f6f6350 100644 (file)
@@ -254,6 +254,7 @@ struct task_struct {
                                         */
        struct exec_domain *exec_domain;
        long need_resched;
+       unsigned long ptrace;
 
 /* various fields */
        long counter;
@@ -361,8 +362,6 @@ struct task_struct {
                                        /* Not implemented yet, only for 486*/
 #define PF_STARTING    0x00000002      /* being created */
 #define PF_EXITING     0x00000004      /* getting shut down */
-#define PF_PTRACED     0x00000010      /* set if ptrace (0) has been called */
-#define PF_TRACESYS    0x00000020      /* tracing system calls */
 #define PF_FORKNOEXEC  0x00000040      /* forked but didn't exec */
 #define PF_SUPERPRIV   0x00000100      /* used super-user privileges */
 #define PF_DUMPCORE    0x00000200      /* dumped core */
@@ -372,7 +371,14 @@ struct task_struct {
 #define PF_FREE_PAGES  0x00002000      /* The current-> */
 
 #define PF_USEDFPU     0x00100000      /* task used FPU this quantum (SMP) */
-#define PF_DTRACE      0x00200000      /* delayed trace (used on m68k, i386) */
+
+/*
+ * Ptrace flags
+ */
+#define PT_PTRACED     0x00000001      /* set if ptrace (0) has been called */
+#define PT_TRACESYS    0x00000002      /* tracing system calls */
+#define PT_DTRACE      0x00000004      /* delayed trace (used on m68k, i386) */
+
 
 /*
  * Limit the stack by to some sane default: root can always
@@ -387,7 +393,7 @@ struct task_struct {
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
  */
 #define INIT_TASK \
-/* state etc */        { 0,0,0,KERNEL_DS,&default_exec_domain,0, \
+/* state etc */        { 0,0,0,KERNEL_DS,&default_exec_domain,0,0, \
 /* counter */  DEF_PRIORITY,DEF_PRIORITY,0, \
 /* SMP */      0,0,0,-1, \
 /* schedlink */        &init_task,&init_task, &init_task, &init_task, \
index 6f5d80c09393f3133008b05365de9e565e924e4a..e03a9c2b4d42d4e4e2ae4e05b83138930b022e5f 100644 (file)
@@ -143,7 +143,7 @@ struct rpc_xprt {
        struct rpc_wait_queue   pingwait;       /* waiting on ping() */
        struct rpc_rqst *       free;           /* free slots */
        struct rpc_rqst         slot[RPC_MAXREQS];
-       unsigned int            sockstate;      /* Socket state */
+       unsigned long           sockstate;      /* Socket state */
        unsigned char           nocong      : 1,/* no congestion control */
                                stream      : 1,/* TCP */
                                shutdown    : 1,/* being shut down */
index 98437d30c6deef4acb9c34567157b4c68034c200..7c16051e4004c24e13a49e28cb0ec2484e22fed2 100644 (file)
@@ -339,7 +339,7 @@ static void exit_notify(void)
                p = current->p_cptr;
                current->p_cptr = p->p_osptr;
                p->p_ysptr = NULL;
-               p->flags &= ~(PF_PTRACED|PF_TRACESYS);
+               p->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
 
                p->p_pptr = p->p_opptr;
                p->p_osptr = p->p_pptr->p_cptr;
@@ -475,7 +475,7 @@ repeat:
                        case TASK_STOPPED:
                                if (!p->exit_code)
                                        continue;
-                               if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
+                               if (!(options & WUNTRACED) && !(p->ptrace & PT_PTRACED))
                                        continue;
                                read_unlock(&tasklist_lock);
                                retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; 
index 70a98bb198c62ef20c30955537a9f036f6cae2e7..0835eebd034691f40a6f05a79a3928a5b9fbbbec 100644 (file)
@@ -557,7 +557,7 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p)
        new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU | PF_VFORK);
        new_flags |= PF_FORKNOEXEC;
        if (!(clone_flags & CLONE_PTRACE))
-               new_flags &= ~(PF_PTRACED|PF_TRACESYS);
+               p->ptrace = 0;
        if (clone_flags & CLONE_VFORK)
                new_flags |= PF_VFORK;
        p->flags = new_flags;
index d3cf1f90c4810a3fe9ce1c25e7d7c8f85284a311..dc0044bb82b7aa0e62256e0589967c9c03e1d468 100644 (file)
@@ -222,7 +222,7 @@ static int ignored_signal(int sig, struct task_struct *t)
        struct k_sigaction *ka;
 
        /* Don't ignore traced or blocked signals */
-       if ((t->flags & PF_PTRACED) || sigismember(&t->blocked, sig))
+       if ((t->ptrace & PT_PTRACED) || sigismember(&t->blocked, sig))
                return 0;
        
        signals = t->sig;
index 4dafeb907f68f45b27013d0c59f915051631b860..85767479118ff4cbdb6251595be6d496fe658413 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The Internet Protocol (IP) module.
  *
- * Version:    $Id: ip_input.c,v 1.37.2.4 2001/01/04 04:20:16 davem Exp $
+ * Version:    $Id: ip_input.c,v 1.37.2.5 2001/06/07 06:47:54 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -181,8 +181,11 @@ static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
        int    type;
 
        type = skb->h.icmph->type;
-       if (type < 32)
-               return test_bit(type, &sk->tp_pinfo.tp_raw4.filter);
+       if (type < 32) {
+               __u32 data = sk->tp_pinfo.tp_raw4.filter.data;
+
+               return ((1 << type) & data) != 0;
+       }
 
        /* Do not block unknown ICMP types */
        return 0;
index d20925c95b82ba30ff8eec61747b7836ef99fe5c..e753a17068d6fd338db0b89ce749dd1dadd6cf63 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: ip6_fib.c,v 1.17 1999/04/22 10:07:41 davem Exp $
+ *     $Id: ip6_fib.c,v 1.17.2.1 2001/06/07 06:47:54 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -179,7 +179,7 @@ static __inline__ int addr_diff(void *token1, void *token2, int addrlen)
 
                        xb = ntohl(xb);
 
-                       while (test_bit(j, &xb) == 0)
+                       while ((xb & (1 << j)) == 0)
                                j--;
 
                        return (i * 32 + 31 - j);
index 3cc6300c8e8168daacff18b753ee39e153fa4984..ff3123e3fed0bd31090ab136d2574ce82083be3c 100644 (file)
@@ -6,7 +6,7 @@
  *     Pedro Roque             <roque@di.fc.ul.pt>
  *     Ian P. Morris           <I.P.Morris@soton.ac.uk>
  *
- *     $Id: ip6_input.c,v 1.11.2.2 2000/09/13 01:27:53 davem Exp $
+ *     $Id: ip6_input.c,v 1.11.2.3 2001/06/07 06:47:54 davem Exp $
  *
  *     Based in linux/net/ipv4/ip_input.c
  *
@@ -97,10 +97,14 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
 {
        struct icmp6hdr *icmph;
        struct raw6_opt *opt;
+       int bit_nr;
 
        opt = &sk->tp_pinfo.tp_raw;
        icmph = (struct icmp6hdr *) skb->h.raw;
-       return test_bit(icmph->icmp6_type, &opt->filter);
+       bit_nr = icmph->icmp6_type;
+       if (bit_nr >= (8 * 32))
+               return 0;
+       return ((opt->filter.data[bit_nr >> 5] & (1 << bit_nr)) != 0);
 }
 
 /*
index 52a45fe0284db215f4f36ebfc19ce8428201834c..4c7dc06439b95358431d1335c0110887bee1a827 100644 (file)
@@ -77,7 +77,7 @@ spinlock_t rpc_queue_lock = SPIN_LOCK_UNLOCKED;
  * This is the last-ditch buffer for NFS swap requests
  */
 static u32                     swap_buffer[PAGE_SIZE >> 2];
-static int                     swap_buffer_used = 0;
+static long                    swap_buffer_used = 0;
 
 /*
  * Make allocation of the swap_buffer SMP-safe