Staging: add USB ENE card reader driver
authorAl Cho <acho@novell.com>
Wed, 8 Sep 2010 07:42:32 +0000 (00:42 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 8 Sep 2010 09:49:39 +0000 (02:49 -0700)
This driver is for the ENE card reader that can be found in many
different laptops.  It was written by ENE, but cleaned up to
work properly in the kernel tree by Novell.

Signed-off-by: Al Cho <acho@novell.com>
Cc: <yiyingc@ene.com.tw>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
25 files changed:
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/keucr/Kconfig [new file with mode: 0644]
drivers/staging/keucr/Makefile [new file with mode: 0644]
drivers/staging/keucr/Module.symvers [new file with mode: 0644]
drivers/staging/keucr/TODO [new file with mode: 0644]
drivers/staging/keucr/common.h [new file with mode: 0644]
drivers/staging/keucr/init.c [new file with mode: 0644]
drivers/staging/keucr/init.h [new file with mode: 0644]
drivers/staging/keucr/ms.c [new file with mode: 0644]
drivers/staging/keucr/ms.h [new file with mode: 0644]
drivers/staging/keucr/msscsi.c [new file with mode: 0644]
drivers/staging/keucr/scsiglue.c [new file with mode: 0644]
drivers/staging/keucr/scsiglue.h [new file with mode: 0644]
drivers/staging/keucr/sdscsi.c [new file with mode: 0644]
drivers/staging/keucr/smcommon.h [new file with mode: 0644]
drivers/staging/keucr/smil.h [new file with mode: 0644]
drivers/staging/keucr/smilecc.c [new file with mode: 0644]
drivers/staging/keucr/smilmain.c [new file with mode: 0644]
drivers/staging/keucr/smilsub.c [new file with mode: 0644]
drivers/staging/keucr/smscsi.c [new file with mode: 0644]
drivers/staging/keucr/transport.c [new file with mode: 0644]
drivers/staging/keucr/transport.h [new file with mode: 0644]
drivers/staging/keucr/usb.c [new file with mode: 0644]
drivers/staging/keucr/usb.h [new file with mode: 0644]

index b9d81ea..35ad939 100644 (file)
@@ -159,5 +159,7 @@ source "drivers/staging/sbe-2t3e3/Kconfig"
 
 source "drivers/staging/ath6kl/Kconfig"
 
+source "drivers/staging/keucr/Kconfig"
+
 endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING
index 64ec1e9..a33209b 100644 (file)
@@ -60,3 +60,4 @@ obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/
 obj-$(CONFIG_WESTBRIDGE_ASTORIA)       += westbridge/astoria/
 obj-$(CONFIG_SBE_2T3E3)        += sbe-2t3e3/
 obj-$(CONFIG_ATH6K_LEGACY)     += ath6kl/
+obj-$(CONFIG_USB_ENESTORAGE)   += keucr/
diff --git a/drivers/staging/keucr/Kconfig b/drivers/staging/keucr/Kconfig
new file mode 100644 (file)
index 0000000..ff42d7e
--- /dev/null
@@ -0,0 +1,13 @@
+config USB_ENESTORAGE
+       tristate "USB ENE card reader support"
+       depends on USB && SCSI
+       ---help---
+         Say Y here if you wish to control a ENE Card reader.
+
+         This option depends on 'SCSI' support being enabled, but you
+         probably also need 'SCSI device support: SCSI disk support'
+         (BLK_DEV_SD) for most USB storage devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called keucr.
+
diff --git a/drivers/staging/keucr/Makefile b/drivers/staging/keucr/Makefile
new file mode 100644 (file)
index 0000000..2a4200f
--- /dev/null
@@ -0,0 +1,16 @@
+EXTRA_CFLAGS += -Idrivers/scsi
+
+obj-$(CONFIG_USB_ENESTORAGE)   += keucr.o
+
+keucr-objs :=                  \
+               usb.o           \
+               scsiglue.o      \
+               transport.o     \
+               init.o          \
+               sdscsi.o        \
+               msscsi.o        \
+               ms.o            \
+               smscsi.o        \
+               smilmain.o      \
+               smilsub.o       \
+               smilecc.o
diff --git a/drivers/staging/keucr/Module.symvers b/drivers/staging/keucr/Module.symvers
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/drivers/staging/keucr/TODO b/drivers/staging/keucr/TODO
new file mode 100644 (file)
index 0000000..4e39e03
--- /dev/null
@@ -0,0 +1,11 @@
+TODO:
+       - checkpatch.pl clean
+       - sparse clean
+       - determine if the driver should not be using a duplicate
+         version of the usb-storage scsi interface code, but should
+         be merged into the drivers/usb/storage/ directory and
+         infrastructure instead.
+       - review by the USB developer community
+
+Please send any patches for this driver to Al Cho <acho@novell.com> and
+Greg Kroah-Hartman <gregkh@suse.de>.
diff --git a/drivers/staging/keucr/common.h b/drivers/staging/keucr/common.h
new file mode 100644 (file)
index 0000000..f40c64f
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef COMMON_INCD
+#define COMMON_INCD
+
+typedef void            VOID;
+typedef u8              BOOLEAN;
+typedef u8              BYTE;
+typedef u8              *PBYTE;
+typedef u16             WORD;
+typedef u16             *PWORD;
+typedef u32             DWORD;
+typedef u32             *PDWORD;
+
+#define swapWORD(w)            ((((unsigned short)(w) << 8) & 0xff00) | (((unsigned short)(w) >> 8) & 0x00ff))
+#define swapDWORD(dw)          ((((unsigned long)(dw) << 24) & 0xff000000) |    \
+                                       (((unsigned long)(dw) <<  8) & 0x00ff0000) |    \
+                                       (((unsigned long)(dw) >>  8) & 0x0000ff00) |    \
+                                       (((unsigned long)(dw) >> 24) & 0x000000ff))
+
+#define LittleEndianWORD(w)             (w)
+#define LittleEndianDWORD(dw)           (dw)
+#define BigEndianWORD(w)       swapWORD(w)
+#define BigEndianDWORD(dw)     swapDWORD(dw)
+
+#endif
+
diff --git a/drivers/staging/keucr/init.c b/drivers/staging/keucr/init.c
new file mode 100644 (file)
index 0000000..2ae129b
--- /dev/null
@@ -0,0 +1,541 @@
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+
+#include "usb.h"
+#include "scsiglue.h"
+#include "transport.h"
+#include "init.h"
+
+BYTE           IsSSFDCCompliance;
+BYTE           IsXDCompliance;
+extern DWORD MediaChange;
+extern int     Check_D_MediaFmt(struct us_data *);
+
+//----- ENE_InitMedia() ----------------------------------------
+int ENE_InitMedia(struct us_data *us)
+{
+       int     result;
+       BYTE    MiscReg03 = 0;
+
+       printk("--- Initial Nedia ---\n");
+       result = ENE_Read_BYTE(us, REG_CARD_STATUS, &MiscReg03);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Read register fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+       printk("MiscReg03 = %x\n", MiscReg03);
+
+       if (MiscReg03 & 0x01)
+       {
+               if (!us->SD_Status.Ready)
+               {
+                       result = ENE_SDInit(us);
+                       if (result != USB_STOR_XFER_GOOD)
+                               return USB_STOR_TRANSPORT_ERROR;
+               }
+       }
+
+       if (MiscReg03 & 0x02)
+       {
+               if (!us->SM_Status.Ready && !us->MS_Status.Ready)
+               {
+                       result = ENE_SMInit(us);
+                       if (result != USB_STOR_XFER_GOOD)
+                       {
+                               result = ENE_MSInit(us);
+                               if (result != USB_STOR_XFER_GOOD)
+                                       return USB_STOR_TRANSPORT_ERROR;
+                       }
+               }
+
+       }
+       return result;
+}
+
+//----- ENE_Read_BYTE() ----------------------------------------
+int ENE_Read_BYTE(struct us_data *us, WORD index, void *buf)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int result;
+
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x01;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xED;
+       bcb->CDB[2]                     = (BYTE)(index>>8);
+       bcb->CDB[3]                     = (BYTE)index;
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
+       return result;
+}
+
+//----- ENE_SDInit() ---------------------
+int ENE_SDInit(struct us_data *us)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+       BYTE    buf[0x200];
+
+       printk("transport --- ENE_SDInit\n");
+       // SD Init Part-1
+       result = ENE_LoadBinCode(us, SD_INIT1_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load SD Init Code Part-1 Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->Flags = 0x80;
+       bcb->CDB[0] = 0xF2;
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Exection SD Init Code Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       // SD Init Part-2
+       result = ENE_LoadBinCode(us, SD_INIT2_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load SD Init Code Part-2 Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x200;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF1;
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Exection SD Init Code Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       us->SD_Status =  *(PSD_STATUS)&buf[0];
+       if (us->SD_Status.Insert && us->SD_Status.Ready)
+       {
+               ENE_ReadSDReg(us, (PBYTE)&buf);
+               printk("Insert     = %x\n", us->SD_Status.Insert);
+               printk("Ready      = %x\n", us->SD_Status.Ready);
+               printk("IsMMC      = %x\n", us->SD_Status.IsMMC);
+               printk("HiCapacity = %x\n", us->SD_Status.HiCapacity);
+               printk("HiSpeed    = %x\n", us->SD_Status.HiSpeed);
+               printk("WtP        = %x\n", us->SD_Status.WtP);
+       }
+       else
+       {
+               printk("SD Card Not Ready --- %x\n", buf[0]);
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- ENE_MSInit() ----------------------------------------
+int ENE_MSInit(struct us_data *us)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+       BYTE    buf[0x200];
+       WORD    MSP_BlockSize, MSP_UserAreaBlocks;
+       
+
+       printk("transport --- ENE_MSInit\n");
+       result = ENE_LoadBinCode(us, MS_INIT_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load MS Init Code Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x200;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF1;
+       bcb->CDB[1]                     = 0x01;
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Exection MS Init Code Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       us->MS_Status = *(PMS_STATUS)&buf[0];
+
+       if (us->MS_Status.Insert && us->MS_Status.Ready)
+       {
+               printk("Insert     = %x\n", us->MS_Status.Insert);
+               printk("Ready      = %x\n", us->MS_Status.Ready);
+               printk("IsMSPro    = %x\n", us->MS_Status.IsMSPro);
+               printk("IsMSPHG    = %x\n", us->MS_Status.IsMSPHG);
+               printk("WtP        = %x\n", us->MS_Status.WtP);
+               if (us->MS_Status.IsMSPro)
+               {
+                       MSP_BlockSize      = (buf[6] <<8) | buf[7];
+                       MSP_UserAreaBlocks = (buf[10]<<8) | buf[11];
+                       us->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks;
+               }
+               else
+                       MS_CardInit(us);
+               printk("MS Init Code OK !!\n");
+       }
+       else
+       {
+               printk("MS Card Not Ready --- %x\n", buf[0]);
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- ENE_SMInit() ----------------------------------------
+int ENE_SMInit(struct us_data *us)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+       BYTE    buf[0x200];
+
+       printk("transport --- ENE_SMInit\n");
+
+       result = ENE_LoadBinCode(us, SM_INIT_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load SM Init Code Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x200;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF1;
+       bcb->CDB[1]                     = 0x01;
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Exection SM Init Code Fail !! result = %x\n", result);
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       us->SM_Status = *(PSM_STATUS)&buf[0];
+
+       us->SM_DeviceID = buf[1];
+       us->SM_CardID   = buf[2];
+
+       if (us->SM_Status.Insert && us->SM_Status.Ready)
+       {
+               printk("Insert     = %x\n", us->SM_Status.Insert);
+               printk("Ready      = %x\n", us->SM_Status.Ready);
+               printk("WtP        = %x\n", us->SM_Status.WtP);
+               printk("DeviceID   = %x\n", us->SM_DeviceID);
+               printk("CardID     = %x\n", us->SM_CardID);
+               MediaChange = 1;
+               Check_D_MediaFmt(us);
+       }
+       else
+       {
+               printk("SM Card Not Ready --- %x\n", buf[0]);
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- ENE_ReadSDReg() ----------------------------------------------
+int ENE_ReadSDReg(struct us_data *us, u8 *RdBuf)
+{
+       WORD    tmpreg;
+       DWORD   reg4b;
+       
+       //printk("transport --- ENE_ReadSDReg\n");
+       reg4b = *(PDWORD)&RdBuf[0x18];
+       us->SD_READ_BL_LEN = (BYTE)((reg4b >> 8) & 0x0f);
+
+       tmpreg = (WORD) reg4b;
+       reg4b = *(PDWORD)(&RdBuf[0x14]);
+       if (us->SD_Status.HiCapacity && !us->SD_Status.IsMMC)
+               us->HC_C_SIZE = (reg4b >> 8) & 0x3fffff;
+
+       us->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (WORD)(reg4b >> 22);
+       us->SD_C_SIZE_MULT = (BYTE)(reg4b >> 7)  & 0x07;
+       if (us->SD_Status.HiCapacity && us->SD_Status.IsMMC)
+               us->HC_C_SIZE = *(PDWORD)(&RdBuf[0x100]);
+
+       if (us->SD_READ_BL_LEN > SD_BLOCK_LEN)
+       {
+               us->SD_Block_Mult = 1 << (us->SD_READ_BL_LEN - SD_BLOCK_LEN);           us->SD_READ_BL_LEN = SD_BLOCK_LEN;
+       }
+       else
+       {               us->SD_Block_Mult = 1;
+       }
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- ENE_LoadBinCode() ---------------------
+int ENE_LoadBinCode(struct us_data *us, BYTE flag)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int result;
+       //void *buf;
+       PBYTE buf;
+
+       //printk("transport --- ENE_LoadBinCode\n");
+       if (us->BIN_FLAG == flag)
+               return USB_STOR_TRANSPORT_GOOD;
+
+       buf = kmalloc(0x800, GFP_KERNEL);
+       switch ( flag )
+       {
+               // For SD
+               case SD_INIT1_PATTERN:
+                       printk("SD_INIT1_PATTERN\n");
+                       memcpy(buf, SD_Init1, 0x800);
+               break;
+               case SD_INIT2_PATTERN:
+                       printk("SD_INIT2_PATTERN\n");
+                       memcpy(buf, SD_Init2, 0x800);
+               break;
+               case SD_RW_PATTERN:
+                       printk("SD_RW_PATTERN\n");
+                       memcpy(buf, SD_Rdwr, 0x800);
+               break;
+               // For MS
+               case MS_INIT_PATTERN:
+                       printk("MS_INIT_PATTERN\n");
+                       memcpy(buf, MS_Init, 0x800);
+               break;
+               case MSP_RW_PATTERN:
+                       printk("MSP_RW_PATTERN\n");
+                       memcpy(buf, MSP_Rdwr, 0x800);
+               break;
+               case MS_RW_PATTERN:
+                       printk("MS_RW_PATTERN\n");
+                       memcpy(buf, MS_Rdwr, 0x800);
+               break;
+               // For SS
+               case SM_INIT_PATTERN:
+                       printk("SM_INIT_PATTERN\n");
+                       memcpy(buf, SM_Init, 0x800);
+               break;
+               case SM_RW_PATTERN:
+                       printk("SM_RW_PATTERN\n");
+                       memcpy(buf, SM_Rdwr, 0x800);
+               break;
+       }
+
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x800;
+       bcb->Flags =0x00;
+       bcb->CDB[0] = 0xEF;
+
+       result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
+
+       kfree(buf);
+       us->BIN_FLAG = flag;
+       return result;
+}
+
+//----- ENE_SendScsiCmd() ---------------------
+int ENE_SendScsiCmd(struct us_data *us, BYTE fDir, void *buf, int use_sg)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
+
+       int result;
+       unsigned int transfer_length=bcb->DataTransferLength, cswlen=0, partial=0;
+       unsigned int residue;
+
+       //printk("transport --- ENE_SendScsiCmd\n");
+       // send cmd to out endpoint
+       result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, US_BULK_CB_WRAP_LEN, NULL);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("send cmd to out endpoint fail ---\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       if (buf)
+       {
+               unsigned int pipe = fDir == FDIR_READ ? us->recv_bulk_pipe : us->send_bulk_pipe;
+               // Bulk
+               if (use_sg)
+                       result = usb_stor_bulk_srb(us, pipe, us->srb);
+               else
+                       result = usb_stor_bulk_transfer_sg(us, pipe, buf, transfer_length, 0, &partial);
+               if (result != USB_STOR_XFER_GOOD)
+               {
+                       printk("data transfer fail ---\n");
+                       return USB_STOR_TRANSPORT_ERROR;
+               }
+       }
+
+       // Get CSW for device status
+       result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, &cswlen);
+
+       if (result == USB_STOR_XFER_SHORT && cswlen == 0)
+       {
+               printk("Received 0-length CSW; retrying...\n");
+               result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, &cswlen);
+       }
+
+       if (result == USB_STOR_XFER_STALLED)
+       {
+               /* get the status again */
+               printk("Attempting to get CSW (2nd try)...\n");
+               result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, NULL);
+       }
+
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       /* check bulk status */
+       residue = le32_to_cpu(bcs->Residue);
+
+       /* try to compute the actual residue, based on how much data
+        * was really transferred and what the device tells us */
+       if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE))
+       {
+               residue = min(residue, transfer_length);
+               scsi_set_resid(us->srb, max(scsi_get_resid(us->srb), (int) residue));
+       }
+
+       if (bcs->Status != US_BULK_STAT_OK)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- ENE_Read_Data() ---------------------
+int ENE_Read_Data(struct us_data *us, void *buf, unsigned int length)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
+       int result;
+
+       //printk("transport --- ENE_Read_Data\n");
+       // set up the command wrapper
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = length;
+       bcb->Flags =0x80;
+       bcb->CDB[0] = 0xED;
+       bcb->CDB[2] = 0xFF;
+       bcb->CDB[3] = 0x81;
+
+       // send cmd to out endpoint
+       result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, US_BULK_CB_WRAP_LEN, NULL);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       // R/W data
+       result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, buf, length, NULL);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       // Get CSW for device status
+       result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, NULL);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+       if (bcs->Status != US_BULK_STAT_OK)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- ENE_Write_Data() ---------------------
+int ENE_Write_Data(struct us_data *us, void *buf, unsigned int length)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
+       int result;
+
+       //printk("transport --- ENE_Write_Data\n");
+       // set up the command wrapper
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = length;
+       bcb->Flags =0x00;
+       bcb->CDB[0] = 0xEE;
+       bcb->CDB[2] = 0xFF;
+       bcb->CDB[3] = 0x81;
+
+       // send cmd to out endpoint
+       result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, US_BULK_CB_WRAP_LEN, NULL);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       // R/W data
+       result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, buf, length, NULL);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       // Get CSW for device status
+       result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, NULL);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+       if (bcs->Status != US_BULK_STAT_OK)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- usb_stor_print_cmd() ---------------------
+void usb_stor_print_cmd(struct scsi_cmnd *srb)
+{
+       PBYTE   Cdb = srb->cmnd;
+       DWORD   cmd = Cdb[0];
+       DWORD   bn  =   ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
+                       ((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
+       WORD    blen = ((Cdb[7]<< 8) & 0xff00) | ((Cdb[8]<< 0) & 0x00ff);
+
+       switch (cmd) {
+       case TEST_UNIT_READY:
+               //printk("scsi cmd %X --- SCSIOP_TEST_UNIT_READY\n", cmd);
+               break;
+       case INQUIRY:
+               printk("scsi cmd %X --- SCSIOP_INQUIRY\n", cmd);
+               break;
+       case MODE_SENSE:
+               printk("scsi cmd %X --- SCSIOP_MODE_SENSE\n", cmd);
+               break;
+       case START_STOP:
+               printk("scsi cmd %X --- SCSIOP_START_STOP\n", cmd);
+               break;
+       case READ_CAPACITY:
+               printk("scsi cmd %X --- SCSIOP_READ_CAPACITY\n", cmd);
+               break;
+       case READ_10:
+               //printk("scsi cmd %X --- SCSIOP_READ, bn = %X, blen = %X\n", cmd, bn, blen);
+               break;
+       case WRITE_10:
+               //printk("scsi cmd %X --- SCSIOP_WRITE, bn = %X, blen = %X\n", cmd, bn, blen);
+               break;
+       case ALLOW_MEDIUM_REMOVAL:
+               printk("scsi cmd %X --- SCSIOP_ALLOW_MEDIUM_REMOVAL\n", cmd);
+               break;
+       default:
+               printk("scsi cmd %X --- Other cmd\n", cmd);
+               break;
+       }
+       bn = 0;
+       blen = 0;
+}
+
+
diff --git a/drivers/staging/keucr/init.h b/drivers/staging/keucr/init.h
new file mode 100644 (file)
index 0000000..17af95b
--- /dev/null
@@ -0,0 +1,1042 @@
+#include "common.h"
+
+BYTE SD_Init1[] = {
+0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0x90, 0xFF, 0x09,
+0xE0, 0x30, 0xE5, 0xFC, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE0, 0x92, 0x14, 0x20, 0x14, 0x0A, 0xC2,
+0x0F, 0xD2, 0x10, 0xC2, 0x17, 0xC3, 0x02, 0xE3, 0x13, 0x7F, 0x03, 0x12, 0x2F, 0xCB, 0x7E, 0x00,
+0x7F, 0x10, 0x12, 0xE3, 0xFA, 0x90, 0xFE, 0x07, 0xE0, 0x54, 0xBA, 0xF0, 0x75, 0x16, 0x00, 0x75,
+0x17, 0x00, 0x90, 0xFE, 0x05, 0x74, 0x80, 0xF0, 0x90, 0xFE, 0x07, 0x74, 0x80, 0xF0, 0x7F, 0x32,
+0x7E, 0x00, 0x12, 0xE3, 0xFA, 0x90, 0xFE, 0x05, 0xE0, 0x44, 0x01, 0xF0, 0xE0, 0x44, 0x08, 0xF0,
+0x7F, 0x32, 0x7E, 0x00, 0x12, 0xE3, 0xFA, 0x90, 0xFE, 0x05, 0xE0, 0x54, 0xF7, 0xF0, 0x7F, 0x32,
+0x7E, 0x00, 0x12, 0xE3, 0xFA, 0x90, 0xFF, 0x81, 0xE0, 0xC2, 0xE3, 0xF0, 0xE0, 0x54, 0xCF, 0x44,
+0x20, 0xD2, 0xE3, 0xF0, 0x90, 0xFF, 0x84, 0xE0, 0x54, 0x1F, 0x44, 0x40, 0xF0, 0x90, 0xFE, 0x05,
+0xE0, 0xD2, 0xE0, 0xF0, 0xE0, 0x30, 0xE0, 0xF8, 0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90,
+0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01, 0xC3, 0x90, 0xFE, 0x05, 0xE0,
+0x44, 0x30, 0xF0, 0x90, 0xFE, 0x06, 0x74, 0x70, 0xF0, 0x74, 0xFF, 0x90, 0xFE, 0x08, 0xF0, 0x74,
+0xFF, 0x90, 0xFE, 0x09, 0xF0, 0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0xE4, 0x90, 0xFE, 0x0C,
+0xF0, 0x90, 0xFE, 0x0D, 0xF0, 0x90, 0xFE, 0x0E, 0xF0, 0xC2, 0x12, 0xE4, 0x90, 0xEB, 0xF9, 0xF0,
+0x90, 0xEB, 0xFA, 0xF0, 0x90, 0xFF, 0x81, 0xE0, 0x54, 0x8F, 0x44, 0x7F, 0xF0, 0x7F, 0x32, 0x7E,
+0x00, 0x12, 0xE3, 0xFA, 0x90, 0xFE, 0x05, 0xE0, 0x54, 0xBF, 0xF0, 0x75, 0xF0, 0xFF, 0xD2, 0x17,
+0xC2, 0x13, 0xE5, 0xF0, 0x14, 0xF5, 0xF0, 0x70, 0x03, 0x02, 0xE2, 0xFC, 0x90, 0xFF, 0x83, 0xE0,
+0xA2, 0xE0, 0x92, 0x14, 0x20, 0x14, 0x03, 0x02, 0xE2, 0xFC, 0xE4, 0xFE, 0x74, 0xFF, 0xFF, 0x78,
+0x00, 0x79, 0x08, 0x12, 0xE3, 0x22, 0x20, 0x13, 0x24, 0x30, 0x17, 0x21, 0x90, 0xFF, 0x83, 0xE0,
+0xA2, 0xE0, 0x92, 0x14, 0x20, 0x14, 0x03, 0x02, 0xE2, 0xFC, 0x78, 0x08, 0x79, 0x28, 0x7D, 0xAA,
+0x7C, 0x01, 0x7B, 0x00, 0x7A, 0x00, 0x12, 0xE3, 0x22, 0x50, 0x02, 0x21, 0xED, 0x90, 0xFF, 0x83,
+0xE0, 0xA2, 0xE0, 0x92, 0x14, 0x20, 0x14, 0x03, 0x02, 0xE2, 0xFC, 0x30, 0x13, 0x02, 0x80, 0x17,
+0x78, 0x37, 0x79, 0x50, 0x7A, 0x00, 0x7B, 0x00, 0x7C, 0x00, 0x7D, 0x00, 0x12, 0xE3, 0x22, 0x50,
+0x02, 0x80, 0x7A, 0x78, 0x69, 0x80, 0x02, 0x78, 0x01, 0x79, 0x2A, 0x7A, 0x80, 0x30, 0x17, 0x02,
+0x7A, 0x40, 0x7B, 0x70, 0x7C, 0x00, 0x7D, 0x00, 0x12, 0xE3, 0x22, 0x50, 0x16, 0x90, 0xFE, 0x04,
+0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01,
+0xC3, 0x80, 0x4A, 0x90, 0xFE, 0x20, 0xE0, 0x54, 0x00, 0xB4, 0x00, 0x23, 0x90, 0xFE, 0x21, 0xE0,
+0x54, 0x00, 0xB4, 0x00, 0x1A, 0x90, 0xFE, 0x22, 0xE0, 0x54, 0x70, 0xB4, 0x70, 0x11, 0x90, 0xFE,
+0x23, 0xE0, 0x30, 0xE7, 0x0A, 0x30, 0x17, 0x05, 0x20, 0xE6, 0x02, 0xC2, 0x17, 0x41, 0x02, 0xC3,
+0xEF, 0x94, 0x01, 0xFF, 0xEE, 0x94, 0x00, 0xFE, 0xC0, 0x06, 0xC0, 0x07, 0x7F, 0x64, 0x7E, 0x00,
+0x12, 0xE3, 0xFA, 0xD0, 0x07, 0xD0, 0x06, 0xEE, 0x4F, 0x60, 0x02, 0x21, 0x4D, 0x7F, 0x64, 0x7E,
+0x00, 0x12, 0xE3, 0xFA, 0xB2, 0x17, 0x30, 0x17, 0x07, 0xB2, 0x13, 0x20, 0x13, 0x02, 0x01, 0xFE,
+0x21, 0x0C, 0x78, 0x02, 0x79, 0x2D, 0x12, 0xE3, 0x22, 0x50, 0x03, 0x02, 0xE2, 0xFC, 0x7B, 0x0F,
+0x7C, 0xFE, 0x7D, 0x20, 0x7E, 0xEA, 0x7F, 0x1A, 0x12, 0xE3, 0xD3, 0x78, 0x03, 0x20, 0x13, 0x02,
+0x78, 0x03, 0x79, 0x28, 0x90, 0xEB, 0xFA, 0xE0, 0xFA, 0x90, 0xEB, 0xF9, 0xE0, 0xFB, 0x7C, 0x00,
+0x7D, 0x00, 0x12, 0xE3, 0x22, 0x50, 0x03, 0x02, 0xE2, 0xFC, 0x90, 0xFE, 0x22, 0xE0, 0x90, 0xEB,
+0xF9, 0xF0, 0x90, 0xFE, 0x23, 0xE0, 0x90, 0xEB, 0xFA, 0xF0, 0x90, 0xFF, 0x81, 0xE0, 0xC2, 0xE3,
+0xF0, 0x30, 0x13, 0x11, 0x90, 0xFF, 0x85, 0xE0, 0x54, 0xCF, 0x44, 0x20, 0xF0, 0x90, 0xFF, 0x81,
+0x74, 0x94, 0xF0, 0x80, 0x0F, 0x90, 0xFF, 0x85, 0xE0, 0x54, 0xCF, 0x44, 0x30, 0xF0, 0x90, 0xFF,
+0x81, 0x74, 0x94, 0xF0, 0x90, 0xFF, 0x81, 0xE0, 0xD2, 0xE3, 0xF0, 0x7F, 0x32, 0x7E, 0x00, 0x12,
+0xE3, 0xFA, 0x78, 0x09, 0x79, 0x4D, 0x90, 0xEB, 0xFA, 0xE0, 0xFA, 0x90, 0xEB, 0xF9, 0xE0, 0xFB,
+0x7C, 0x00, 0x7D, 0x00, 0x12, 0xE3, 0x22, 0x50, 0x03, 0x02, 0xE2, 0xFC, 0x12, 0xE3, 0x91, 0x78,
+0x87, 0x79, 0x50, 0x90, 0xEB, 0xFA, 0xE0, 0xFA, 0x90, 0xEB, 0xF9, 0xE0, 0xFB, 0x7C, 0x00, 0x7D,
+0x00, 0x12, 0xE3, 0x22, 0x50, 0x03, 0x02, 0xE2, 0xFC, 0x30, 0x13, 0x09, 0x90, 0xFE, 0x05, 0xE0,
+0x54, 0xBF, 0xF0, 0x80, 0x35, 0x78, 0x37, 0x79, 0x50, 0x90, 0xEB, 0xFA, 0xE0, 0xFA, 0x90, 0xEB,
+0xF9, 0xE0, 0xFB, 0x7C, 0x00, 0x7D, 0x00, 0x12, 0xE3, 0x22, 0x50, 0x03, 0x02, 0xE2, 0xFC, 0x78,
+0x46, 0x79, 0x50, 0x7A, 0x00, 0x7B, 0x00, 0x7C, 0x00, 0x7D, 0x02, 0x12, 0xE3, 0x22, 0x50, 0x03,
+0x02, 0xE2, 0xFC, 0x90, 0xFE, 0x05, 0xE0, 0x44, 0x40, 0xF0, 0xD3, 0x22, 0x30, 0x14, 0x14, 0x90,
+0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3,
+0x80, 0x01, 0xC3, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0x90, 0xFE, 0xCC, 0xE0, 0x44, 0x80, 0xF0,
+0xC3, 0x22, 0xE8, 0x90, 0xFE, 0x15, 0xF0, 0xE9, 0x90, 0xFE, 0x14, 0xF0, 0xED, 0x90, 0xFE, 0x18,
+0xF0, 0xEC, 0x90, 0xFE, 0x19, 0xF0, 0xEB, 0x90, 0xFE, 0x1A, 0xF0, 0xEA, 0x90, 0xFE, 0x1B, 0xF0,
+0x74, 0xFF, 0x90, 0xFE, 0x10, 0xF0, 0x90, 0xFE, 0x11, 0xF0, 0x90, 0xFE, 0x12, 0xF0, 0xE8, 0x54,
+0x80, 0xFE, 0x90, 0xFE, 0x04, 0x74, 0x01, 0xF0, 0x30, 0x14, 0x08, 0x90, 0xFE, 0x10, 0xE0, 0x54,
+0x05, 0x60, 0x02, 0xD3, 0x22, 0x90, 0xFE, 0x11, 0xE0, 0x30, 0xE0, 0xEC, 0xBE, 0x80, 0x03, 0x30,
+0xE1, 0xE6, 0x90, 0xFE, 0x10, 0xE0, 0x54, 0x05, 0x70, 0xE9, 0xC3, 0x22, 0x30, 0x13, 0x02, 0xC3,
+0x22, 0x90, 0xFE, 0x22, 0xE0, 0x70, 0x06, 0x90, 0xFE, 0x23, 0xE0, 0x60, 0x02, 0xD3, 0x22, 0xC3,
+0x22, 0x7B, 0x0F, 0x7C, 0xFE, 0x7D, 0x20, 0x7E, 0xEA, 0x7F, 0x29, 0x12, 0xE3, 0xD3, 0x30, 0x13,
+0x1B, 0x90, 0xFE, 0x20, 0xE0, 0x54, 0x30, 0x64, 0x30, 0x70, 0x02, 0xD2, 0x11, 0x30, 0x13, 0x0C,
+0x90, 0xFE, 0x2E, 0xE0, 0x54, 0x3C, 0x64, 0x10, 0x70, 0x02, 0xD2, 0x12, 0x30, 0x17, 0x03, 0x02,
+0xE3, 0xC4, 0x80, 0x03, 0x20, 0x13, 0x00, 0xC2, 0x11, 0x90, 0xFE, 0x13, 0xE0, 0x30, 0xE2, 0x02,
+0xD2, 0x11, 0x22, 0xC0, 0x04, 0xC0, 0x05, 0x8E, 0x83, 0x8F, 0x82, 0xEB, 0x60, 0x17, 0xC0, 0x82,
+0xC0, 0x83, 0x8C, 0x83, 0x8D, 0x82, 0xE0, 0xA3, 0xAC, 0x83, 0xAD, 0x82, 0xD0, 0x83, 0xD0, 0x82,
+0xF0, 0xA3, 0x1B, 0x80, 0xE6, 0xD0, 0x05, 0xD0, 0x04, 0x22, 0x75, 0x8A, 0x00, 0x75, 0x8C, 0xCE,
+0xC2, 0x8D, 0x90, 0xEA, 0x65, 0xE4, 0xF0, 0xA3, 0xF0, 0xD2, 0x8C, 0x90, 0xEA, 0x65, 0xE0, 0xFC,
+0xA3, 0xE0, 0xFD, 0xEC, 0xC3, 0x9E, 0x40, 0xF3, 0x70, 0x05, 0xED, 0xC3, 0x9F, 0x40, 0xEC, 0xC2,
+0x8C, 0x22, 0xF5, 0xD3, 0xE0, 0x64, 0x01, 0x70, 0x02, 0xD2, 0x3F, 0x75, 0x17, 0x00, 0x75, 0x18,
+0x00, 0x85, 0x14, 0x19, 0x75, 0x1B, 0x01, 0x12, 0x2F, 0x8C, 0x40, 0x03, 0x02, 0xE4, 0x45, 0x90,
+0xEA, 0x49, 0xE5, 0x14, 0xF0, 0x05, 0x14, 0x02, 0xE2, 0xDC, 0xD2, 0x22, 0x90, 0xEA, 0x49, 0xE0,
+0x64, 0xFF, 0x70, 0x02, 0x80, 0x02, 0x80, 0x12, 0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25,
+0x04, 0xE0, 0x20, 0xE1, 0xF9, 0x12, 0x2F, 0x9E, 0xC3, 0x22, 0x30, 0x3F, 0x36, 0x74, 0x88, 0x90,
+0xEA, 0x44, 0xF0, 0x75, 0x17, 0x00, 0x79, 0x00, 0x7A, 0x00, 0x7B, 0x10, 0x7C, 0x02, 0x7D, 0x02,
+0x12, 0x2F, 0xA7, 0x7F, 0x80, 0x12, 0x2F, 0xC5, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0xFE, 0xF0, 0x90,
+0xFE, 0x45, 0xE0, 0x44, 0x04, 0xF0, 0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25, 0x04, 0xE0,
+0x20, 0xE1, 0xF9, 0xD3, 0x22, 0x75, 0x8A, 0x00, 0x75, 0x8C, 0xCE, 0xC2, 0x8D, 0x90, 0xEA, 0x65,
+0xE4, 0xF0, 0xA3, 0xF0, 0xD2, 0x8C, 0x90, 0xEA, 0x65, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEC, 0xC3,
+0x9E, 0x40, 0xF3, 0x70, 0x05, 0xED, 0xC3, 0x9F, 0x40, 0xEC, 0xC2, 0x8C, 0x22, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x53, 0x44, 0x2D, 0x49, 0x6E, 0x69, 0x74, 0x31, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x31 };
+
+BYTE SD_Init2[] = {
+0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0x90, 0xFF, 0x09,
+0xE0, 0x30, 0xE5, 0xFC, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE0, 0x92, 0x14, 0x20, 0x14, 0x0A, 0xC2,
+0x0F, 0xD2, 0x10, 0xC2, 0x17, 0xC3, 0x02, 0xE0, 0xA0, 0x20, 0x13, 0x05, 0x12, 0xE3, 0x8D, 0x80,
+0x03, 0x12, 0xE1, 0x1F, 0xD2, 0x0F, 0xC2, 0x10, 0xD3, 0x90, 0xF3, 0xFF, 0x75, 0xF0, 0xFF, 0x74,
+0x00, 0xA3, 0xF0, 0xD5, 0xF0, 0xFB, 0x7B, 0x0F, 0x7C, 0xEA, 0x7D, 0x29, 0x7E, 0xF4, 0x7F, 0x10,
+0x12, 0xE5, 0x5D, 0x90, 0xF4, 0x00, 0xE4, 0xA2, 0x14, 0x92, 0xE0, 0xA2, 0x0F, 0x92, 0xE1, 0xA2,
+0x10, 0x92, 0xE2, 0xA2, 0x13, 0x92, 0xE3, 0xA2, 0x17, 0x92, 0xE4, 0xA2, 0x12, 0x92, 0xE5, 0xA2,
+0x11, 0x92, 0xE6, 0xF0, 0xF0, 0x74, 0xFF, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0xFF, 0x2A,
+0x74, 0x02, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0xD3, 0x22, 0x30, 0x14, 0x14, 0x90, 0xFE, 0x04, 0xE0,
+0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01, 0xC3,
+0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0x90, 0xFE, 0xCC, 0xE0, 0x44, 0x80, 0xF0, 0x02, 0xE0, 0x39,
+0xE8, 0x90, 0xFE, 0x15, 0xF0, 0xE9, 0x90, 0xFE, 0x14, 0xF0, 0xED, 0x90, 0xFE, 0x18, 0xF0, 0xEC,
+0x90, 0xFE, 0x19, 0xF0, 0xEB, 0x90, 0xFE, 0x1A, 0xF0, 0xEA, 0x90, 0xFE, 0x1B, 0xF0, 0x74, 0xFF,
+0x90, 0xFE, 0x10, 0xF0, 0x90, 0xFE, 0x11, 0xF0, 0x90, 0xFE, 0x12, 0xF0, 0xE8, 0x54, 0x80, 0xFE,
+0x90, 0xFE, 0x04, 0x74, 0x01, 0xF0, 0x30, 0x14, 0x08, 0x90, 0xFE, 0x10, 0xE0, 0x54, 0x05, 0x60,
+0x02, 0xD3, 0x22, 0x90, 0xFE, 0x11, 0xE0, 0x30, 0xE0, 0xEC, 0xBE, 0x80, 0x03, 0x30, 0xE1, 0xE6,
+0x90, 0xFE, 0x10, 0xE0, 0x54, 0x05, 0x70, 0xE9, 0xC3, 0x22, 0x30, 0x13, 0x02, 0xC3, 0x22, 0x90,
+0xFE, 0x22, 0xE0, 0x70, 0x06, 0x90, 0xFE, 0x23, 0xE0, 0x60, 0x02, 0xD3, 0x22, 0xC3, 0x22, 0x20,
+0x12, 0x03, 0x02, 0xE3, 0x17, 0x90, 0xFE, 0x1C, 0x74, 0xFF, 0xF0, 0x90, 0xFE, 0x1D, 0x74, 0x01,
+0xF0, 0x74, 0x00, 0x90, 0xFE, 0x1E, 0xF0, 0x90, 0xFE, 0x1F, 0xF0, 0x90, 0xFE, 0xCC, 0xE0, 0x54,
+0x7F, 0xF0, 0x90, 0xFE, 0x06, 0xE0, 0x54, 0xF0, 0xF0, 0x90, 0xFE, 0xC0, 0x74, 0xF4, 0xF0, 0xA3,
+0x74, 0x00, 0xF0, 0x90, 0xFE, 0xC6, 0x74, 0x01, 0xF0, 0xA3, 0x74, 0xFF, 0xF0, 0x90, 0xFE, 0xC5,
+0xE4, 0xF0, 0x90, 0xFE, 0xC4, 0x74, 0x04, 0xF0, 0x78, 0x10, 0x79, 0x50, 0x7A, 0x00, 0x7B, 0x00,
+0x7C, 0x02, 0x7D, 0x00, 0x12, 0xE0, 0xB0, 0x50, 0x03, 0x02, 0xE3, 0x17, 0x78, 0x08, 0x79, 0xE8,
+0x12, 0xE0, 0xB0, 0x50, 0x03, 0x02, 0xE3, 0x17, 0x90, 0xFE, 0xC8, 0xE0, 0xF0, 0x90, 0xFE, 0xC4,
+0xE0, 0x44, 0x01, 0xF0, 0x30, 0x14, 0x10, 0x90, 0xFE, 0xC8, 0xE0, 0x64, 0x01, 0x60, 0x11, 0x90,
+0xFE, 0x10, 0xE0, 0x54, 0x0A, 0x60, 0xED, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xC3, 0x80, 0x01,
+0xD3, 0x40, 0x03, 0x02, 0xE3, 0x17, 0x20, 0x17, 0x02, 0x80, 0x39, 0xC3, 0x90, 0xF4, 0xD4, 0xE0,
+0x90, 0xF5, 0x00, 0xF0, 0x90, 0xEB, 0xF8, 0x94, 0x01, 0xF0, 0x90, 0xF4, 0xD5, 0xE0, 0x90, 0xF5,
+0x01, 0xF0, 0x90, 0xEB, 0xF7, 0x94, 0x00, 0xF0, 0x90, 0xF4, 0xD6, 0xE0, 0x90, 0xF5, 0x02, 0xF0,
+0x90, 0xEB, 0xF6, 0x94, 0x00, 0xF0, 0x90, 0xF4, 0xD7, 0xE0, 0x90, 0xF5, 0x03, 0xF0, 0x90, 0xEB,
+0xF5, 0x94, 0x00, 0xF0, 0x90, 0xF4, 0x00, 0x43, 0x82, 0xC4, 0xE0, 0x54, 0x03, 0xF5, 0x09, 0x90,
+0xFE, 0xCC, 0xE0, 0x44, 0x80, 0xF0, 0x90, 0xFE, 0x06, 0xE0, 0x54, 0x3F, 0x44, 0x00, 0xF0, 0x90,
+0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3,
+0x80, 0x01, 0xC3, 0x74, 0x03, 0x90, 0xFE, 0x1C, 0xF0, 0x74, 0x00, 0x90, 0xFE, 0x1D, 0xF0, 0x90,
+0xFE, 0x1E, 0xF0, 0x90, 0xFE, 0x1F, 0xF0, 0x78, 0x10, 0x79, 0x50, 0x7A, 0x00, 0x7B, 0x00, 0x7C,
+0x00, 0x7D, 0x04, 0x12, 0xE0, 0xB0, 0x50, 0x03, 0x02, 0xE3, 0x17, 0x90, 0xFE, 0x07, 0xE0, 0xC2,
+0xE6, 0xF0, 0x90, 0xFE, 0x07, 0xE0, 0xD2, 0xE0, 0xF0, 0x90, 0xFE, 0x05, 0xE0, 0xD2, 0xE7, 0xF0,
+0x7B, 0x55, 0x7C, 0xAA, 0x7D, 0xAA, 0x7E, 0x55, 0x12, 0xE3, 0x35, 0x50, 0x05, 0x75, 0x08, 0x02,
+0x41, 0xB0, 0x90, 0xFE, 0x07, 0xE0, 0x54, 0xBE, 0xF0, 0x90, 0xFE, 0x05, 0xE0, 0x44, 0x40, 0xF0,
+0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA,
+0xD3, 0x80, 0x01, 0xC3, 0x7B, 0x5A, 0x7C, 0x5A, 0x7D, 0xA5, 0x7E, 0x00, 0x12, 0xE3, 0x35, 0x50,
+0x05, 0x75, 0x08, 0x01, 0x41, 0xB0, 0x90, 0xFE, 0x05, 0xE0, 0x54, 0xBF, 0xF0, 0x02, 0xE3, 0x17,
+0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA,
+0xD3, 0x80, 0x01, 0xC3, 0xE5, 0x08, 0x78, 0x86, 0x79, 0x50, 0x7A, 0x03, 0x7B, 0xB7, 0xFC, 0x7D,
+0x00, 0x12, 0xE0, 0xB0, 0x50, 0x03, 0x02, 0xE3, 0x17, 0x78, 0x86, 0x79, 0x50, 0x7A, 0x03, 0x7B,
+0xB9, 0x7C, 0x01, 0x7D, 0x00, 0x12, 0xE0, 0xB0, 0x40, 0xBC, 0xE5, 0x09, 0x20, 0xE1, 0x04, 0x74,
+0x94, 0x80, 0x02, 0x74, 0x84, 0x90, 0xFF, 0x81, 0xF0, 0x90, 0xFE, 0x07, 0xE0, 0xD2, 0xE6, 0xF0,
+0x90, 0xFF, 0x85, 0xE0, 0x54, 0xCF, 0x44, 0x30, 0xF0, 0x90, 0xFF, 0x81, 0xE0, 0xD2, 0xE3, 0xF0,
+0x7F, 0x32, 0x7E, 0x00, 0x12, 0xE5, 0x84, 0x90, 0xFE, 0x06, 0xE0, 0x54, 0x3F, 0x44, 0x40, 0xF0,
+0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA,
+0xD3, 0x80, 0x01, 0xC3, 0x22, 0xC0, 0x05, 0xC0, 0x06, 0x78, 0x13, 0x79, 0x68, 0x12, 0xE0, 0xB0,
+0x50, 0x03, 0x02, 0xE3, 0x8B, 0xEB, 0x90, 0xFE, 0x00, 0xF0, 0xEC, 0xF0, 0x90, 0xFE, 0x12, 0xE0,
+0x30, 0xE1, 0xF9, 0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06,
+0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01, 0xC3, 0x78, 0x0E, 0x79, 0xE8, 0x12, 0xE0, 0xB0, 0x50, 0x03,
+0x02, 0xE3, 0x8B, 0x90, 0xFE, 0x12, 0xE0, 0x20, 0xE1, 0xF9, 0xD0, 0x06, 0xD0, 0x05, 0x90, 0xFE,
+0x00, 0xE0, 0x6D, 0x70, 0x06, 0xE0, 0x6E, 0x70, 0x02, 0xD3, 0x22, 0xC3, 0x22, 0x90, 0xFE, 0x06,
+0xE0, 0x54, 0x3F, 0x44, 0x00, 0xF0, 0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04,
+0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01, 0xC3, 0x74, 0x07, 0x90, 0xFE, 0x1C, 0xF0,
+0x74, 0x00, 0x90, 0xFE, 0x1D, 0xF0, 0x90, 0xFE, 0x1E, 0xF0, 0x90, 0xFE, 0x1F, 0xF0, 0x78, 0x10,
+0x79, 0x50, 0x7A, 0x00, 0x7B, 0x00, 0x30, 0x17, 0x06, 0x7C, 0x02, 0x7D, 0x00, 0x80, 0x04, 0x7C,
+0x00, 0x7D, 0x08, 0x12, 0xE0, 0xB0, 0x50, 0x03, 0x02, 0xE4, 0x39, 0x78, 0x37, 0x79, 0x50, 0x90,
+0xEB, 0xFA, 0xE0, 0xFA, 0x90, 0xEB, 0xF9, 0xE0, 0xFB, 0x7C, 0x00, 0x7D, 0x00, 0x12, 0xE0, 0xB0,
+0x50, 0x03, 0x02, 0xE4, 0x39, 0x78, 0x73, 0x79, 0xE8, 0x7A, 0x00, 0x7B, 0x00, 0x7C, 0x00, 0x7D,
+0x00, 0x12, 0xE0, 0xB0, 0x50, 0x03, 0x02, 0xE4, 0x39, 0x90, 0xFE, 0x12, 0xE0, 0x20, 0xE1, 0xF9,
+0x78, 0x08, 0x90, 0xEA, 0x3F, 0xC0, 0x83, 0xC0, 0x82, 0x90, 0xFE, 0x00, 0xE0, 0xD0, 0x82, 0xD0,
+0x83, 0xF0, 0xC3, 0xE5, 0x82, 0x24, 0xFF, 0xF5, 0x82, 0xE5, 0x83, 0x34, 0xFF, 0xF5, 0x83, 0xD8,
+0xE4, 0x90, 0xEA, 0x3F, 0xE0, 0x54, 0x0F, 0x70, 0x25, 0x90, 0xFE, 0x07, 0xE0, 0xC2, 0xE6, 0xF0,
+0x90, 0xFE, 0x06, 0xE0, 0x54, 0x3F, 0x44, 0x40, 0xF0, 0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0,
+0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01, 0xC3, 0x22, 0x90, 0xFE,
+0x06, 0xE0, 0x54, 0x3F, 0x44, 0x40, 0xF0, 0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE,
+0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01, 0xC3, 0x7E, 0x00, 0x12, 0xE4, 0xBF,
+0x40, 0x03, 0x02, 0xE4, 0xBE, 0x7E, 0x80, 0x12, 0xE4, 0xBF, 0x40, 0x03, 0x02, 0xE4, 0xBE, 0x90,
+0xFF, 0x81, 0xE0, 0xC2, 0xE3, 0xF0, 0x90, 0xFF, 0x81, 0x74, 0x84, 0xF0, 0x90, 0xFE, 0x07, 0xE0,
+0xD2, 0xE6, 0xF0, 0x90, 0xFF, 0x81, 0xE0, 0xD2, 0xE3, 0xF0, 0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06,
+0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01, 0xC3, 0x22, 0x90,
+0xFE, 0x1C, 0x74, 0x3F, 0xF0, 0x90, 0xFE, 0x1D, 0x74, 0x00, 0xF0, 0x74, 0x00, 0x90, 0xFE, 0x1E,
+0xF0, 0x90, 0xFE, 0x1F, 0xF0, 0x90, 0xFE, 0xCC, 0xE0, 0x54, 0x7F, 0xF0, 0x90, 0xFE, 0x06, 0xE0,
+0x54, 0xF0, 0xF0, 0x90, 0xFE, 0xC0, 0x74, 0xF4, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0x90, 0xFE, 0xC6,
+0x74, 0x00, 0xF0, 0xA3, 0x74, 0x3F, 0xF0, 0x90, 0xFE, 0xC5, 0xE4, 0xF0, 0x90, 0xFE, 0xC4, 0x74,
+0x04, 0xF0, 0x78, 0x06, 0x79, 0xE8, 0xAA, 0x06, 0x7B, 0xFF, 0x7C, 0xFF, 0x7D, 0x01, 0x12, 0xE0,
+0xB0, 0x50, 0x03, 0x02, 0xE5, 0x5B, 0x90, 0xFE, 0xC8, 0x74, 0x01, 0xF0, 0x90, 0xFE, 0xC4, 0xE0,
+0x44, 0x01, 0xF0, 0x30, 0x14, 0x10, 0x90, 0xFE, 0xC8, 0xE0, 0x64, 0x01, 0x60, 0x11, 0x90, 0xFE,
+0x10, 0xE0, 0x54, 0x0A, 0x60, 0xED, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xC3, 0x80, 0x01, 0xD3,
+0x40, 0x03, 0x02, 0xE5, 0x5B, 0x90, 0xFE, 0xCC, 0xE0, 0x44, 0x80, 0xF0, 0x90, 0xF4, 0x0D, 0xE0,
+0x90, 0xF4, 0x10, 0xE0, 0x64, 0x0F, 0x60, 0x03, 0xD3, 0x80, 0x01, 0xC3, 0x22, 0xC0, 0x04, 0xC0,
+0x05, 0x8E, 0x83, 0x8F, 0x82, 0xEB, 0x60, 0x17, 0xC0, 0x82, 0xC0, 0x83, 0x8C, 0x83, 0x8D, 0x82,
+0xE0, 0xA3, 0xAC, 0x83, 0xAD, 0x82, 0xD0, 0x83, 0xD0, 0x82, 0xF0, 0xA3, 0x1B, 0x80, 0xE6, 0xD0,
+0x05, 0xD0, 0x04, 0x22, 0x75, 0x8A, 0x00, 0x75, 0x8C, 0xCE, 0xC2, 0x8D, 0x90, 0xEA, 0x65, 0xE4,
+0xF0, 0xA3, 0xF0, 0xD2, 0x8C, 0x90, 0xEA, 0x65, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEC, 0xC3, 0x9E,
+0x40, 0xF3, 0x70, 0x05, 0xED, 0xC3, 0x9F, 0x40, 0xEC, 0xC2, 0x8C, 0x22, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x53, 0x44, 0x2D, 0x49, 0x6E, 0x69, 0x74, 0x32, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x31 };
+
+BYTE SD_Rdwr[] = {
+0x90, 0xF0, 0x11, 0xE0, 0x90, 0xEB, 0x2A, 0xF0, 0x90, 0xF0, 0x12, 0xE0, 0x90, 0xEB, 0x2B, 0xF0,
+0x90, 0xF0, 0x13, 0xE0, 0x90, 0xEB, 0x2C, 0xF0, 0x90, 0xF0, 0x14, 0xE0, 0x90, 0xEB, 0x2D, 0xF0,
+0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE0, 0x92, 0x14, 0x30, 0x14, 0x3E, 0x30, 0x0F, 0x3B, 0x90, 0xEB,
+0x2A, 0xE0, 0xF5, 0x10, 0xA3, 0xE0, 0xF5, 0x11, 0xA3, 0xE0, 0xF5, 0x12, 0xA3, 0xE0, 0xF5, 0x13,
+0xC3, 0xE5, 0x3D, 0x13, 0xF5, 0x14, 0xE5, 0x3E, 0x13, 0xF5, 0x15, 0x85, 0x14, 0x16, 0x85, 0x15,
+0x17, 0x90, 0xF0, 0x0C, 0xE0, 0x54, 0x80, 0x70, 0x12, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06,
+0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0x02, 0xE2, 0x31, 0xC3, 0x22, 0x90, 0xFF, 0x09, 0xE0, 0x30,
+0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0xE5, 0x15, 0x24, 0xFF, 0x90, 0xFE, 0x1E, 0xF0,
+0xE5, 0x14, 0x34, 0xFF, 0x90, 0xFE, 0x1F, 0xF0, 0x90, 0xFE, 0x1C, 0x74, 0xFF, 0xF0, 0x90, 0xFE,
+0x1D, 0x74, 0x01, 0xF0, 0x90, 0xFE, 0xCC, 0xE0, 0x54, 0x7F, 0xF0, 0x90, 0xFE, 0x06, 0xE0, 0x54,
+0xF0, 0xF0, 0x90, 0xFE, 0xC0, 0x74, 0xF4, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0x90, 0xFE, 0xC6, 0x74,
+0x01, 0xF0, 0xA3, 0x74, 0xFF, 0xF0, 0x90, 0xFE, 0xC5, 0xE4, 0xF0, 0x90, 0xFE, 0xC4, 0x74, 0x04,
+0xF0, 0x78, 0x10, 0x79, 0x50, 0x7A, 0x00, 0x7B, 0x00, 0x7C, 0x02, 0x7D, 0x00, 0x12, 0xE3, 0xEA,
+0x50, 0x03, 0x02, 0xE1, 0xFA, 0x12, 0xE4, 0x44, 0x50, 0x03, 0x02, 0xE1, 0xFA, 0xAD, 0x13, 0xAC,
+0x12, 0xAB, 0x11, 0xAA, 0x10, 0x80, 0x00, 0xE5, 0x15, 0x64, 0x01, 0x45, 0x14, 0x70, 0x0E, 0x78,
+0x11, 0x79, 0xE8, 0x12, 0xE3, 0xEA, 0x50, 0x03, 0x02, 0xE1, 0xFA, 0x80, 0x0C, 0x78, 0x12, 0x79,
+0xE8, 0x12, 0xE3, 0xEA, 0x50, 0x03, 0x02, 0xE1, 0xFA, 0x12, 0xE4, 0x44, 0x50, 0x03, 0x02, 0xE1,
+0xFA, 0x30, 0x14, 0x07, 0x90, 0xFE, 0x12, 0xE0, 0x30, 0xE4, 0xF6, 0x20, 0x14, 0x03, 0x02, 0xE1,
+0xFA, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xFC, 0x90, 0xFE, 0xC8, 0x74, 0x01, 0xF0, 0x90, 0xFE,
+0xC4, 0xE0, 0x44, 0x01, 0xF0, 0xC3, 0xE5, 0x17, 0x94, 0x01, 0xF5, 0x17, 0xE5, 0x16, 0x94, 0x00,
+0xF5, 0x16, 0x45, 0x17, 0x60, 0x42, 0x30, 0x14, 0x10, 0x90, 0xFE, 0xC8, 0xE0, 0x64, 0x01, 0x60,
+0x11, 0x90, 0xFE, 0x10, 0xE0, 0x54, 0x0A, 0x60, 0xED, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xC3,
+0x80, 0x01, 0xD3, 0x40, 0x03, 0x02, 0xE1, 0xFA, 0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0, 0xA3, 0x74,
+0x00, 0xF0, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xFC, 0x90, 0xFE, 0xC8, 0x74, 0x01, 0xF0, 0x90,
+0xFE, 0xC4, 0xE0, 0x44, 0x01, 0xF0, 0x80, 0xAD, 0x30, 0x14, 0x10, 0x90, 0xFE, 0xC8, 0xE0, 0x64,
+0x01, 0x60, 0x11, 0x90, 0xFE, 0x10, 0xE0, 0x54, 0x0A, 0x60, 0xED, 0x90, 0xFE, 0xD8, 0x74, 0x01,
+0xF0, 0xC3, 0x80, 0x01, 0xD3, 0x40, 0x03, 0x02, 0xE1, 0xFA, 0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0,
+0xA3, 0x74, 0x00, 0xF0, 0xE5, 0x15, 0x64, 0x01, 0x45, 0x14, 0x60, 0x29, 0x90, 0xFF, 0x09, 0xE0,
+0x30, 0xE5, 0xFC, 0x78, 0x8C, 0x79, 0x50, 0x12, 0xE3, 0xEA, 0x50, 0x03, 0x02, 0xE1, 0xFA, 0x12,
+0xE4, 0x44, 0x50, 0x11, 0x90, 0xFE, 0x22, 0xE0, 0x70, 0x20, 0x90, 0xFE, 0x23, 0xE0, 0x64, 0x80,
+0x60, 0x03, 0x02, 0xE1, 0xFA, 0x90, 0xFE, 0xCC, 0xE0, 0x44, 0x80, 0xF0, 0x75, 0x3C, 0x00, 0x75,
+0x3D, 0x00, 0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22, 0x30, 0x14, 0x14, 0x90, 0xFE, 0x04,
+0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01,
+0xC3, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0x90, 0xFE, 0xCC, 0xE0, 0x44, 0x80, 0xF0, 0x75, 0x3F,
+0x00, 0xC3, 0xE5, 0x17, 0x33, 0xF5, 0x3E, 0xE5, 0x16, 0x33, 0xF5, 0x3D, 0x75, 0x3C, 0x00, 0xC3,
+0x22, 0xE5, 0x3E, 0x54, 0x01, 0x45, 0x3F, 0x60, 0x03, 0x02, 0xE0, 0x69, 0xE5, 0x15, 0x24, 0xFF,
+0x90, 0xFE, 0x1E, 0xF0, 0xE5, 0x14, 0x34, 0xFF, 0x90, 0xFE, 0x1F, 0xF0, 0x90, 0xFE, 0x1C, 0x74,
+0xFF, 0xF0, 0x90, 0xFE, 0x1D, 0x74, 0x01, 0xF0, 0x90, 0xFE, 0x06, 0xE0, 0x54, 0xF0, 0x44, 0x0F,
+0xF0, 0x90, 0xFE, 0xC0, 0x74, 0xF0, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0xE5, 0x4D, 0x24, 0xFF, 0xFF,
+0xE5, 0x4C, 0x34, 0xFF, 0x90, 0xFE, 0xC6, 0xF0, 0xA3, 0xEF, 0xF0, 0xE4, 0x90, 0xFE, 0xC5, 0xF0,
+0x74, 0x06, 0x90, 0xFE, 0xC4, 0xF0, 0x90, 0xFE, 0xCC, 0xE0, 0x54, 0x7F, 0xF0, 0x78, 0x10, 0x79,
+0x50, 0x7A, 0x00, 0x7B, 0x00, 0x7C, 0x02, 0x7D, 0x00, 0x12, 0xE3, 0xEA, 0x50, 0x03, 0x02, 0xE3,
+0x9E, 0x12, 0xE4, 0x44, 0x50, 0x03, 0x02, 0xE3, 0x9E, 0xAD, 0x13, 0xAC, 0x12, 0xAB, 0x11, 0xAA,
+0x10, 0x80, 0x10, 0x74, 0x00, 0xFD, 0xC3, 0xE5, 0x13, 0x33, 0xFC, 0xE5, 0x12, 0x33, 0xFB, 0xE5,
+0x11, 0x33, 0xFA, 0xE5, 0x15, 0x64, 0x01, 0x45, 0x14, 0x70, 0x0E, 0x78, 0x18, 0x79, 0x68, 0x12,
+0xE3, 0xEA, 0x50, 0x03, 0x02, 0xE3, 0x9E, 0x80, 0x0C, 0x78, 0x19, 0x79, 0x68, 0x12, 0xE3, 0xEA,
+0x50, 0x03, 0x02, 0xE3, 0x9E, 0x12, 0xE4, 0x44, 0x50, 0x03, 0x02, 0xE3, 0x9E, 0x75, 0x1F, 0x01,
+0x20, 0x2D, 0x03, 0x75, 0x1F, 0x08, 0xE5, 0x16, 0x45, 0x17, 0x70, 0x03, 0x02, 0xE3, 0x6B, 0x85,
+0x1F, 0x1E, 0x30, 0x14, 0x3C, 0x90, 0xFF, 0x09, 0x30, 0x14, 0x04, 0xE0, 0x30, 0xE1, 0xF9, 0x90,
+0xFE, 0xC8, 0x74, 0x01, 0xF0, 0x90, 0xFE, 0xC4, 0xE0, 0x44, 0x01, 0xF0, 0x30, 0x14, 0x10, 0x90,
+0xFE, 0xC8, 0xE0, 0x64, 0x01, 0x60, 0x11, 0x90, 0xFE, 0x10, 0xE0, 0x54, 0x0A, 0x60, 0xED, 0x90,
+0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xC3, 0x80, 0x01, 0xD3, 0x40, 0x03, 0x02, 0xE3, 0x9E, 0x90, 0xFE,
+0x12, 0x30, 0x14, 0x2A, 0xE0, 0x30, 0xE1, 0xF9, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90,
+0xFF, 0x23, 0x74, 0x80, 0xF0, 0x15, 0x1E, 0xE5, 0x1E, 0x70, 0xA7, 0xC3, 0xE5, 0x17, 0x94, 0x01,
+0xF5, 0x17, 0xE5, 0x16, 0x94, 0x00, 0xF5, 0x16, 0x02, 0xE2, 0xF6, 0x90, 0xFE, 0x12, 0x30, 0x14,
+0x2D, 0xE0, 0x20, 0xE4, 0xF9, 0xE5, 0x15, 0x64, 0x01, 0x45, 0x14, 0x60, 0x58, 0x78, 0x8C, 0x79,
+0x50, 0x12, 0xE3, 0xEA, 0x50, 0x03, 0x02, 0xE3, 0x9E, 0x12, 0xE4, 0x44, 0x50, 0x03, 0x02, 0xE3,
+0x9E, 0x30, 0x14, 0x41, 0x90, 0xFE, 0x12, 0xE0, 0x20, 0xE4, 0xF6, 0x02, 0xE3, 0xD5, 0x30, 0x14,
+0x14, 0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70,
+0xFA, 0xD3, 0x80, 0x01, 0xC3, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0x90, 0xFE, 0xCC, 0xE0, 0x44,
+0x80, 0xF0, 0x75, 0x3F, 0x00, 0xC3, 0xE5, 0x17, 0x33, 0xF5, 0x3E, 0xE5, 0x16, 0x33, 0xF5, 0x3D,
+0x75, 0x3C, 0x00, 0xC3, 0x22, 0x90, 0xFE, 0xCC, 0xE0, 0x44, 0x80, 0xF0, 0x75, 0x3C, 0x00, 0x75,
+0x3D, 0x00, 0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22, 0xE8, 0x90, 0xFE, 0x15, 0xF0, 0xE9,
+0x90, 0xFE, 0x14, 0xF0, 0xED, 0x90, 0xFE, 0x18, 0xF0, 0xEC, 0x90, 0xFE, 0x19, 0xF0, 0xEB, 0x90,
+0xFE, 0x1A, 0xF0, 0xEA, 0x90, 0xFE, 0x1B, 0xF0, 0x74, 0xFF, 0x90, 0xFE, 0x10, 0xF0, 0x90, 0xFE,
+0x11, 0xF0, 0x90, 0xFE, 0x12, 0xF0, 0xE8, 0x54, 0x80, 0xFE, 0x90, 0xFE, 0x04, 0x74, 0x01, 0xF0,
+0x30, 0x14, 0x08, 0x90, 0xFE, 0x10, 0xE0, 0x54, 0x05, 0x60, 0x02, 0xD3, 0x22, 0x90, 0xFE, 0x11,
+0xE0, 0x30, 0xE0, 0xEC, 0xBE, 0x80, 0x03, 0x30, 0xE1, 0xE6, 0x90, 0xFE, 0x10, 0xE0, 0x54, 0x05,
+0x70, 0xE9, 0xC3, 0x22, 0x30, 0x13, 0x02, 0xC3, 0x22, 0x90, 0xFE, 0x22, 0xE0, 0x70, 0x06, 0x90,
+0xFE, 0x23, 0xE0, 0x60, 0x02, 0xD3, 0x22, 0xC3, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x53, 0x44, 0x2D, 0x52, 0x57, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x31 };
+
+BYTE MS_Init[] = {
+0x90, 0xF0, 0x15, 0xE0, 0xF5, 0x1C, 0x11, 0x2C, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90,
+0xFF, 0x23, 0x74, 0x80, 0xF0, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xFC, 0x51, 0x59, 0x75, 0x3F,
+0x00, 0x75, 0x3E, 0x00, 0x75, 0x3D, 0x00, 0x75, 0x3C, 0x00, 0xD3, 0x22, 0x90, 0xFF, 0x83, 0xE0,
+0xA2, 0xE1, 0x92, 0x25, 0x20, 0x25, 0x06, 0xC2, 0x1F, 0xD2, 0x19, 0xC3, 0x22, 0x7F, 0x02, 0x12,
+0x2F, 0xCB, 0x20, 0x19, 0x05, 0x30, 0x1F, 0x02, 0xD3, 0x22, 0x90, 0xEA, 0x44, 0x74, 0x80, 0xF0,
+0x7F, 0x10, 0x12, 0x2F, 0xC5, 0x90, 0xFE, 0x47, 0xE0, 0x44, 0x80, 0xF0, 0x78, 0x00, 0xE8, 0xC3,
+0x94, 0x04, 0x50, 0x0A, 0x7F, 0x88, 0x7E, 0x13, 0x12, 0xE4, 0xA6, 0x08, 0x80, 0xF0, 0x90, 0xFE,
+0x45, 0xE0, 0x54, 0xFB, 0xF0, 0x90, 0xFE, 0x47, 0xE0, 0x54, 0xBF, 0xF0, 0x90, 0xFE, 0x45, 0xE0,
+0x54, 0xFE, 0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0x7F, 0xF0, 0x90, 0xFE, 0x46, 0xE0, 0x44, 0x40,
+0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0xC7, 0x44, 0x18, 0xF0, 0x90, 0xFE, 0x47, 0xE0, 0x44, 0x08,
+0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x44, 0x40, 0xF0, 0x7F, 0x32, 0x7E, 0x00, 0x12, 0xE4, 0xA6, 0x90,
+0xFE, 0x51, 0xE0, 0x54, 0x33, 0xF0, 0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25, 0x04, 0xE0,
+0x20, 0xE1, 0xF9, 0x90, 0xFE, 0x51, 0xE0, 0x54, 0x0F, 0xF0, 0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0,
+0x30, 0x25, 0x04, 0xE0, 0x20, 0xE1, 0xF9, 0x90, 0xFE, 0x44, 0x74, 0x04, 0xF0, 0x30, 0x25, 0x04,
+0xE0, 0x20, 0xE2, 0xF9, 0x90, 0xFE, 0x4C, 0xE0, 0xF0, 0x90, 0xFE, 0x4D, 0xE0, 0xF0, 0x90, 0xFE,
+0x48, 0x74, 0x7F, 0xF0, 0x90, 0xFE, 0x49, 0x74, 0x9F, 0xF0, 0x90, 0xFE, 0x51, 0xE0, 0x54, 0x3C,
+0x44, 0x02, 0xF0, 0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25, 0x04, 0xE0, 0x20, 0xE1, 0xF9,
+0x90, 0xFE, 0x46, 0xE0, 0x44, 0x20, 0xF0, 0x79, 0x02, 0x7A, 0x06, 0x7B, 0x00, 0x7C, 0x00, 0x7D,
+0x06, 0x7E, 0xEB, 0x7F, 0xC9, 0x12, 0x2F, 0xA7, 0x40, 0x03, 0x02, 0xE2, 0x37, 0xC2, 0x45, 0xC2,
+0x1E, 0x90, 0xEB, 0xCB, 0xE0, 0x64, 0x01, 0x70, 0x65, 0x90, 0xEB, 0xCD, 0xE0, 0x70, 0x5F, 0x90,
+0xEB, 0xCE, 0xE0, 0x60, 0x08, 0x54, 0x03, 0x60, 0x55, 0xD2, 0x1E, 0x80, 0x09, 0x90, 0xEB, 0xC9,
+0xE0, 0x30, 0xE0, 0x02, 0xD2, 0x1E, 0x90, 0xEA, 0x45, 0x74, 0x01, 0xF0, 0x75, 0x0B, 0x00, 0xE5,
+0x0B, 0xC3, 0x94, 0x80, 0x50, 0x31, 0x12, 0x2F, 0xB9, 0x40, 0x03, 0x02, 0xE2, 0x37, 0x90, 0xEB,
+0xC8, 0xE0, 0x54, 0x80, 0x70, 0x0B, 0x7F, 0x38, 0x7E, 0x13, 0x12, 0xE4, 0xA6, 0x05, 0x0B, 0x80,
+0xDE, 0x12, 0x2F, 0xB9, 0x40, 0x03, 0x02, 0xE2, 0x37, 0x90, 0xEB, 0xC8, 0xE0, 0xF9, 0x54, 0x40,
+0x60, 0x0A, 0xE9, 0x54, 0x01, 0x70, 0x03, 0x02, 0xE2, 0x37, 0xD2, 0x1E, 0x80, 0x24, 0x90, 0xEB,
+0xCB, 0xE0, 0x64, 0x00, 0x60, 0x03, 0x02, 0xE2, 0x37, 0x90, 0xEA, 0x45, 0x74, 0x00, 0xF0, 0x7F,
+0x90, 0x12, 0x2F, 0xC5, 0x12, 0xE2, 0xB0, 0x40, 0x03, 0x02, 0xE2, 0x37, 0xD2, 0x1F, 0xC2, 0x19,
+0xD3, 0x22, 0x90, 0xEA, 0x44, 0x74, 0x00, 0xF0, 0x75, 0x17, 0x00, 0x79, 0x00, 0x7A, 0x00, 0x7B,
+0x10, 0x7C, 0x02, 0x7D, 0x02, 0x12, 0x2F, 0xA7, 0x40, 0x02, 0x80, 0x5B, 0x7F, 0x80, 0x12, 0x2F,
+0xC5, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0xFE, 0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x44, 0x04, 0xF0, 0x90,
+0xEB, 0xCC, 0xE0, 0x64, 0x07, 0x70, 0x2D, 0x90, 0xEA, 0x44, 0x74, 0x40, 0xF0, 0x75, 0x17, 0x00,
+0x79, 0x00, 0x7A, 0x00, 0x7B, 0x10, 0x7C, 0x02, 0x7D, 0x02, 0x12, 0x2F, 0xA7, 0x40, 0x02, 0x80,
+0x26, 0x7F, 0x80, 0x12, 0x2F, 0xC5, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0xFA, 0xF0, 0x90, 0xFE, 0x45,
+0xE0, 0x44, 0x01, 0xF0, 0x90, 0xEA, 0x45, 0xE0, 0x60, 0x07, 0x12, 0x2F, 0xCE, 0x40, 0x02, 0x80,
+0x06, 0xD2, 0x1F, 0xC2, 0x19, 0xD3, 0x22, 0xE4, 0x90, 0xFE, 0x48, 0xF0, 0x90, 0xFE, 0x49, 0xF0,
+0x90, 0xFE, 0x4C, 0xE0, 0xF0, 0x90, 0xFE, 0x4D, 0xE0, 0xF0, 0x90, 0xFE, 0x47, 0xE0, 0x54, 0x7F,
+0xF0, 0xC2, 0x25, 0xC2, 0x1F, 0xD2, 0x19, 0xC3, 0x22, 0x90, 0xEA, 0x45, 0xE0, 0x64, 0x01, 0x70,
+0x03, 0xD3, 0x80, 0x01, 0xC3, 0xE4, 0x92, 0xE3, 0xC0, 0xE0, 0x90, 0xEB, 0xCC, 0xE0, 0x64, 0x07,
+0x70, 0x03, 0xD3, 0x80, 0x01, 0xC3, 0xD0, 0xE0, 0x92, 0xE4, 0xA2, 0x25, 0x92, 0xE0, 0xA2, 0x1F,
+0x92, 0xE1, 0xA2, 0x19, 0x92, 0xE2, 0xA2, 0x1E, 0x92, 0xE6, 0x90, 0xF4, 0x00, 0xF0, 0x74, 0xFF,
+0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0x7B, 0x40, 0x7C, 0xEB, 0x7D, 0x6F, 0xAE, 0x83, 0xAF,
+0x82, 0x12, 0x2F, 0xC8, 0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0xD3, 0x22,
+0xC2, 0x1E, 0x74, 0xFF, 0x90, 0xEA, 0x49, 0xF0, 0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25,
+0x04, 0xE0, 0x20, 0xE1, 0xF9, 0x90, 0xFF, 0x09, 0x30, 0x25, 0x07, 0xE0, 0x30, 0xE5, 0xF9, 0xD3,
+0x80, 0x01, 0xC3, 0x40, 0x01, 0x22, 0xC2, 0x1A, 0xC2, 0x22, 0x75, 0x14, 0x00, 0xE5, 0x14, 0x64,
+0x0C, 0x70, 0x03, 0x02, 0xE4, 0x4B, 0x75, 0x17, 0x00, 0x75, 0x18, 0x00, 0x85, 0x14, 0x19, 0x75,
+0x1B, 0x00, 0x12, 0x2F, 0x8C, 0x40, 0x03, 0x02, 0xE4, 0x46, 0x30, 0x41, 0x03, 0x02, 0xE4, 0x46,
+0x90, 0xEB, 0xDD, 0xE0, 0x20, 0xE7, 0x03, 0x02, 0xE4, 0x46, 0x90, 0xEB, 0xDE, 0xE0, 0x20, 0xE2,
+0x02, 0x80, 0x03, 0x02, 0xE4, 0x46, 0x90, 0xF4, 0x00, 0xE0, 0xFE, 0x90, 0xF4, 0x01, 0xE0, 0x64,
+0x01, 0x4E, 0x60, 0x03, 0x02, 0xE4, 0x46, 0x90, 0xEA, 0x49, 0xE0, 0x64, 0xFF, 0x60, 0x03, 0x02,
+0xE4, 0x4B, 0x90, 0xF5, 0xA0, 0xE0, 0x64, 0x01, 0x60, 0x03, 0x02, 0xE4, 0x46, 0x90, 0xF5, 0xD6,
+0xE0, 0x64, 0x01, 0x60, 0x03, 0x02, 0xE4, 0x46, 0x90, 0xF5, 0xD8, 0xE0, 0xFF, 0xC3, 0x74, 0x03,
+0x9F, 0x50, 0x03, 0x02, 0xE4, 0x46, 0xEF, 0x60, 0x04, 0xD2, 0x1E, 0x80, 0x0B, 0xC2, 0x1E, 0x90,
+0xEB, 0xC9, 0xE0, 0x30, 0xE0, 0x02, 0xD2, 0x1E, 0x90, 0xF5, 0xA2, 0xE0, 0xFE, 0x90, 0xF5, 0xA3,
+0xE0, 0xFF, 0x25, 0xE0, 0x90, 0xEA, 0x47, 0xF0, 0xE4, 0x74, 0x10, 0x9F, 0x74, 0x00, 0x9E, 0x50,
+0x03, 0x02, 0xE4, 0x46, 0x90, 0xF5, 0xA4, 0xE0, 0xFE, 0x90, 0xF5, 0xA5, 0xE0, 0xFF, 0xC3, 0x74,
+0x00, 0x9F, 0x74, 0x20, 0x9E, 0x50, 0x03, 0x02, 0xE4, 0x46, 0xEE, 0x4F, 0x70, 0x03, 0x02, 0xE4,
+0x46, 0x90, 0xF5, 0xA6, 0xE0, 0xFE, 0x90, 0xF5, 0xA7, 0xE0, 0xFF, 0xEE, 0x4F, 0x70, 0x03, 0x02,
+0xE4, 0x46, 0x90, 0xF5, 0x78, 0xE0, 0x64, 0x01, 0x60, 0x03, 0x02, 0xE4, 0x46, 0x90, 0xF5, 0x74,
+0xE0, 0xFC, 0x90, 0xF5, 0x75, 0xE0, 0xFD, 0x90, 0xF5, 0x76, 0xE0, 0x90, 0xEA, 0x5B, 0xF0, 0xFE,
+0x90, 0xF5, 0x77, 0xE0, 0x90, 0xEA, 0x5C, 0xF0, 0xFF, 0x4E, 0x4D, 0x4C, 0x70, 0x03, 0x02, 0xE4,
+0x46, 0x90, 0xF5, 0x70, 0xE0, 0xFC, 0x90, 0xF5, 0x71, 0xE0, 0xFD, 0x90, 0xF5, 0x72, 0xE0, 0xFE,
+0x90, 0xF5, 0x73, 0xE0, 0xFF, 0xEC, 0x90, 0xEA, 0x55, 0xF0, 0xED, 0x90, 0xEA, 0x56, 0xF0, 0xEE,
+0x90, 0xEA, 0x57, 0xF0, 0xEF, 0x90, 0xEA, 0x58, 0xF0, 0xEC, 0x64, 0xFF, 0x70, 0x12, 0xED, 0x64,
+0xFF, 0x70, 0x0D, 0xEE, 0x64, 0xFF, 0x70, 0x08, 0xEF, 0x64, 0xFF, 0x70, 0x03, 0x02, 0xE4, 0x46,
+0xC2, 0x3F, 0x90, 0xF5, 0xD3, 0xE0, 0x64, 0x01, 0x70, 0x02, 0xD2, 0x3F, 0x75, 0x17, 0x00, 0x75,
+0x18, 0x00, 0x85, 0x14, 0x19, 0x75, 0x1B, 0x01, 0x12, 0x2F, 0x8C, 0x40, 0x03, 0x02, 0xE4, 0x46,
+0x90, 0xEA, 0x49, 0xE5, 0x14, 0xF0, 0x05, 0x14, 0x02, 0xE2, 0xDD, 0xD2, 0x22, 0x90, 0xEA, 0x49,
+0xE0, 0x64, 0xFF, 0x70, 0x02, 0x80, 0x02, 0x80, 0x12, 0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30,
+0x25, 0x04, 0xE0, 0x20, 0xE1, 0xF9, 0x12, 0x2F, 0x9E, 0xC3, 0x22, 0x30, 0x3F, 0x36, 0x74, 0x88,
+0x90, 0xEA, 0x44, 0xF0, 0x75, 0x17, 0x00, 0x79, 0x00, 0x7A, 0x00, 0x7B, 0x10, 0x7C, 0x02, 0x7D,
+0x02, 0x12, 0x2F, 0xA7, 0x7F, 0x80, 0x12, 0x2F, 0xC5, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0xFE, 0xF0,
+0x90, 0xFE, 0x45, 0xE0, 0x44, 0x04, 0xF0, 0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25, 0x04,
+0xE0, 0x20, 0xE1, 0xF9, 0xD3, 0x22, 0x75, 0x8A, 0x00, 0x75, 0x8C, 0xCE, 0xC2, 0x8D, 0x90, 0xEA,
+0x65, 0xE4, 0xF0, 0xA3, 0xF0, 0xD2, 0x8C, 0x90, 0xEA, 0x65, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEC,
+0xC3, 0x9E, 0x40, 0xF3, 0x70, 0x05, 0xED, 0xC3, 0x9F, 0x40, 0xEC, 0xC2, 0x8C, 0x22, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x4D, 0x53, 0x2D, 0x49, 0x6E, 0x69, 0x74, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30 };
+
+BYTE MSP_Rdwr[] = {
+0x90, 0xF0, 0x10, 0xE0, 0x90, 0xEA, 0x46, 0xF0, 0xB4, 0x04, 0x03, 0x02, 0xE1, 0x1E, 0x90, 0xFF,
+0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0x90, 0xFF, 0x09, 0xE0, 0x30,
+0xE5, 0xFC, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25, 0x40, 0x01, 0x22, 0x20, 0x1F, 0x02,
+0xC3, 0x22, 0x30, 0x45, 0x02, 0xC3, 0x22, 0xC3, 0xE5, 0x3D, 0x13, 0xF5, 0x08, 0xE5, 0x3E, 0x13,
+0xF5, 0x09, 0x78, 0x96, 0x79, 0x20, 0xAA, 0x08, 0xAB, 0x09, 0x12, 0xE2, 0x53, 0x20, 0x1D, 0x10,
+0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25, 0x30, 0x25, 0x03, 0x30, 0x24, 0xEF, 0xD2, 0x24,
+0x20, 0x23, 0x10, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25, 0x30, 0x25, 0x03, 0x30, 0x24,
+0xEF, 0xD2, 0x24, 0x30, 0x24, 0x02, 0xC3, 0x22, 0xC2, 0x24, 0xC2, 0x23, 0x90, 0xEA, 0x4B, 0xE0,
+0x30, 0xE3, 0x0B, 0xC2, 0x25, 0x90, 0xFF, 0x85, 0xE0, 0x54, 0xFD, 0xF0, 0xC3, 0x22, 0x30, 0xE2,
+0x78, 0x90, 0xFF, 0x09, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25, 0x30, 0x25, 0x0A, 0x90,
+0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xEE, 0xD3, 0x80, 0x01, 0xC3, 0x40, 0x01, 0x22, 0x79, 0x00, 0x90,
+0xFE, 0x46, 0xE0, 0x54, 0xF0, 0x49, 0xF0, 0x78, 0x2D, 0x12, 0x2F, 0xAA, 0x7E, 0xF4, 0x7F, 0x00,
+0x7D, 0x00, 0x7C, 0x02, 0x12, 0x2F, 0xC2, 0x20, 0x1D, 0x10, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1,
+0x92, 0x25, 0x30, 0x25, 0x03, 0x30, 0x24, 0xEF, 0xD2, 0x24, 0x30, 0x24, 0x13, 0x75, 0x3F, 0x00,
+0xC3, 0xE5, 0x09, 0x33, 0xF5, 0x3E, 0xE5, 0x08, 0x33, 0xF5, 0x3D, 0x75, 0x3C, 0x00, 0xC3, 0x22,
+0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0xE5, 0x09, 0x24, 0xFF, 0xF5, 0x09,
+0xE5, 0x08, 0x34, 0xFF, 0xF5, 0x08, 0x02, 0xE0, 0x60, 0x90, 0xEA, 0x4B, 0xE0, 0x20, 0xE0, 0x03,
+0x02, 0xE0, 0x60, 0xE4, 0xF5, 0x3F, 0xF5, 0x3E, 0xF5, 0x3D, 0xF5, 0x3C, 0xD3, 0x22, 0x90, 0xFF,
+0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0x90, 0xFF, 0x09, 0xE0, 0x30,
+0xE5, 0xFC, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25, 0x40, 0x01, 0x22, 0x20, 0x1F, 0x02,
+0xC3, 0x22, 0x30, 0x1E, 0x02, 0xC3, 0x22, 0xC3, 0xE5, 0x3D, 0x13, 0xF5, 0x08, 0xE5, 0x3E, 0x13,
+0xF5, 0x09, 0x78, 0x96, 0x79, 0x21, 0xAA, 0x08, 0xAB, 0x09, 0x12, 0xE2, 0x53, 0x20, 0x1D, 0x10,
+0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25, 0x30, 0x25, 0x03, 0x30, 0x24, 0xEF, 0xD2, 0x24,
+0x30, 0x2D, 0x05, 0x75, 0x0A, 0x01, 0x80, 0x03, 0x75, 0x0A, 0x08, 0x20, 0x23, 0x10, 0x90, 0xFF,
+0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25, 0x30, 0x25, 0x03, 0x30, 0x24, 0xEF, 0xD2, 0x24, 0x30, 0x24,
+0x02, 0xC3, 0x22, 0xC2, 0x24, 0xC2, 0x23, 0x90, 0xEA, 0x4B, 0xE0, 0x30, 0xE1, 0x0B, 0xC2, 0x25,
+0x90, 0xFF, 0x85, 0xE0, 0x54, 0xFD, 0xF0, 0xC3, 0x22, 0x20, 0xE2, 0x03, 0x02, 0xE2, 0x3E, 0x79,
+0x0F, 0x90, 0xFE, 0x46, 0xE0, 0x54, 0xF0, 0x49, 0xF0, 0x75, 0x0B, 0x00, 0xE5, 0x0B, 0xC3, 0x95,
+0x0A, 0x50, 0x43, 0x90, 0xFF, 0x09, 0x30, 0x25, 0x0B, 0xE0, 0x30, 0xE1, 0xF9, 0x90, 0xFF, 0x09,
+0xF0, 0xD3, 0x80, 0x01, 0xC3, 0x50, 0x0F, 0xAF, 0x0B, 0x7C, 0xF0, 0x7D, 0x00, 0xAB, 0x4D, 0xAA,
+0x4C, 0x12, 0x2F, 0xBF, 0x40, 0x0F, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23,
+0x74, 0x80, 0xF0, 0xC3, 0x22, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74,
+0x80, 0xF0, 0x05, 0x0B, 0x80, 0xB6, 0x20, 0x1D, 0x10, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92,
+0x25, 0x30, 0x25, 0x03, 0x30, 0x24, 0xEF, 0xD2, 0x24, 0x30, 0x24, 0x13, 0x75, 0x3F, 0x00, 0xC3,
+0xE5, 0x09, 0x33, 0xF5, 0x3E, 0xE5, 0x08, 0x33, 0xF5, 0x3D, 0x75, 0x3C, 0x00, 0xC3, 0x22, 0xE5,
+0x09, 0x24, 0xFF, 0xF5, 0x09, 0xE5, 0x08, 0x34, 0xFF, 0xF5, 0x08, 0x02, 0xE1, 0x7B, 0x90, 0xEA,
+0x4B, 0xE0, 0x20, 0xE0, 0x03, 0x02, 0xE1, 0x7B, 0xE4, 0xF5, 0x3F, 0xF5, 0x3E, 0xF5, 0x3D, 0xF5,
+0x3C, 0xD3, 0x22, 0x90, 0xFE, 0x4C, 0xE0, 0xF0, 0x90, 0xFE, 0x4D, 0xE0, 0xF0, 0xC2, 0x24, 0xC2,
+0x23, 0xC2, 0x1D, 0x90, 0xFE, 0x50, 0xE8, 0xF0, 0x90, 0xFE, 0x40, 0xE9, 0xF0, 0x90, 0xFE, 0x40,
+0xEA, 0xF0, 0x90, 0xFE, 0x40, 0xEB, 0xF0, 0x90, 0xEB, 0x2A, 0xE0, 0x90, 0xFE, 0x40, 0xF0, 0x90,
+0xEB, 0x2B, 0xE0, 0x90, 0xFE, 0x40, 0xF0, 0x90, 0xEB, 0x2C, 0xE0, 0x90, 0xFE, 0x40, 0xF0, 0x90,
+0xEB, 0x2D, 0xE0, 0x90, 0xFE, 0x40, 0xF0, 0x90, 0xFE, 0x44, 0x74, 0x01, 0xF0, 0x22, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x4D, 0x53, 0x50, 0x2D, 0x52, 0x57, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30 };
+
+BYTE MS_Rdwr[] = {
+0x90, 0xF0, 0x10, 0xE0, 0x90, 0xEA, 0x46, 0xF0, 0xB4, 0x02, 0x02, 0x80, 0x36, 0x90, 0xF0, 0x11,
+0xE0, 0xF5, 0x17, 0x90, 0xF0, 0x12, 0xE0, 0xF5, 0x18, 0x90, 0xF0, 0x13, 0xE0, 0xF5, 0x19, 0x90,
+0xF0, 0x14, 0xE0, 0xF5, 0x1B, 0x90, 0xF0, 0x15, 0xE0, 0xF5, 0x1C, 0x90, 0xF0, 0x16, 0xE0, 0xF5,
+0x1D, 0x90, 0xF0, 0x17, 0xE0, 0xF5, 0x1E, 0x90, 0xF0, 0x18, 0xE0, 0xF5, 0x1F, 0x90, 0xF0, 0x19,
+0xE0, 0xF5, 0x10, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0,
+0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xFC, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25, 0x40,
+0x01, 0x22, 0x90, 0xEA, 0x46, 0xE0, 0xB4, 0x02, 0x02, 0x80, 0x2B, 0xB4, 0x03, 0x03, 0x02, 0xE0,
+0x96, 0xB4, 0x04, 0x05, 0xD2, 0x21, 0x02, 0xE2, 0xBC, 0xB4, 0x08, 0x0E, 0x85, 0x1C, 0x11, 0x85,
+0x1D, 0x12, 0x85, 0x10, 0x1B, 0xC2, 0x21, 0x02, 0xE2, 0xBC, 0xB4, 0x06, 0x03, 0x02, 0xE2, 0x2F,
+0xB4, 0x05, 0x03, 0x02, 0xE2, 0x7A, 0x20, 0x1F, 0x02, 0xC3, 0x22, 0x90, 0xEA, 0x46, 0xE0, 0xB4,
+0x03, 0x03, 0x02, 0xE1, 0x94, 0xC3, 0xE5, 0x3D, 0x13, 0xF5, 0x14, 0xE5, 0x3E, 0x13, 0xF5, 0x15,
+0x90, 0xEB, 0x2A, 0xE0, 0xFC, 0x90, 0xEB, 0x2B, 0xE0, 0xFD, 0x90, 0xEB, 0x2C, 0xE0, 0xFE, 0x90,
+0xEB, 0x2D, 0xE0, 0xFF, 0x90, 0xEA, 0x47, 0xE0, 0x14, 0xFB, 0x60, 0x12, 0xC3, 0xEC, 0x13, 0xFC,
+0xED, 0x13, 0xFD, 0xEE, 0x13, 0xFE, 0xEF, 0x13, 0xFF, 0xC3, 0xEB, 0x13, 0x80, 0xEB, 0x8E, 0x1E,
+0x8F, 0x1F, 0x90, 0xEB, 0x2D, 0xE0, 0xFF, 0x90, 0xEA, 0x47, 0xE0, 0x14, 0x5F, 0xF5, 0x1B, 0xD2,
+0x1A, 0x90, 0xEA, 0x47, 0xE0, 0xC3, 0x95, 0x1B, 0xF5, 0x16, 0xE5, 0x14, 0x70, 0x0A, 0xE5, 0x16,
+0xD3, 0x95, 0x15, 0x40, 0x03, 0x85, 0x15, 0x16, 0xE5, 0x1E, 0xF5, 0x18, 0xE5, 0x1F, 0xF5, 0x19,
+0x75, 0x17, 0x00, 0x90, 0xEA, 0x5C, 0xE0, 0xF8, 0x90, 0xEB, 0x6D, 0xE0, 0x65, 0x18, 0x70, 0x08,
+0xA3, 0xE0, 0x65, 0x19, 0x70, 0x03, 0x80, 0x07, 0xA3, 0xA3, 0xD8, 0xEF, 0xC3, 0x80, 0x01, 0xD3,
+0x40, 0x4F, 0xE5, 0x16, 0x64, 0x01, 0x70, 0x07, 0x12, 0x2F, 0x8C, 0x50, 0x41, 0x80, 0x07, 0xAB,
+0x16, 0x12, 0xE5, 0x60, 0x50, 0x38, 0xC3, 0xE5, 0x15, 0x95, 0x16, 0xF5, 0x15, 0xE5, 0x14, 0x94,
+0x00, 0xF5, 0x14, 0xE5, 0x14, 0x45, 0x15, 0x60, 0x17, 0x05, 0x0D, 0xE5, 0x0D, 0x70, 0x02, 0x05,
+0x0C, 0x05, 0x1F, 0xE5, 0x1F, 0x70, 0x02, 0x05, 0x1E, 0x74, 0x00, 0xF5, 0x1B, 0x02, 0xE0, 0xF1,
+0x75, 0x3F, 0x00, 0x75, 0x3E, 0x00, 0x75, 0x3D, 0x00, 0x75, 0x3C, 0x00, 0xD3, 0x22, 0x12, 0x2F,
+0x9E, 0x75, 0x3F, 0x00, 0xC3, 0xE5, 0x15, 0x33, 0xF5, 0x3E, 0xE5, 0x14, 0x33, 0xF5, 0x3D, 0x75,
+0x3C, 0x00, 0xC3, 0x22, 0xE5, 0x1C, 0x70, 0x03, 0x75, 0x1C, 0x01, 0xC3, 0x94, 0x80, 0x40, 0x03,
+0x75, 0x1C, 0x80, 0xAA, 0x1C, 0xAD, 0x1B, 0x90, 0xF4, 0x00, 0xC0, 0x83, 0xC0, 0x82, 0xEA, 0x60,
+0x5F, 0xAE, 0x18, 0xAF, 0x19, 0xE4, 0x90, 0xFE, 0x48, 0xF0, 0x90, 0xFE, 0x49, 0xF0, 0x12, 0x2F,
+0x8F, 0x90, 0xFE, 0x48, 0x74, 0x7F, 0xF0, 0x90, 0xFE, 0x49, 0x74, 0x9F, 0xF0, 0x90, 0xEB, 0xDD,
+0xE0, 0xD0, 0x82, 0xD0, 0x83, 0xF0, 0xA3, 0xC0, 0x83, 0xC0, 0x82, 0x90, 0xEB, 0xDE, 0xE0, 0xD0,
+0x82, 0xD0, 0x83, 0xF0, 0xA3, 0xC0, 0x83, 0xC0, 0x82, 0x90, 0xEB, 0xDF, 0xE0, 0xD0, 0x82, 0xD0,
+0x83, 0xF0, 0xA3, 0xC0, 0x83, 0xC0, 0x82, 0x90, 0xEB, 0xE0, 0xE0, 0xD0, 0x82, 0xD0, 0x83, 0xF0,
+0xA3, 0xC0, 0x83, 0xC0, 0x82, 0x1A, 0x05, 0x19, 0xE5, 0x19, 0x70, 0x02, 0x05, 0x18, 0x80, 0x9E,
+0xD0, 0x82, 0xD0, 0x83, 0xE5, 0x1C, 0x25, 0xE0, 0xFF, 0x74, 0x00, 0x33, 0xFE, 0xEF, 0x25, 0xE0,
+0xFF, 0xEE, 0x33, 0xFE, 0x90, 0xFF, 0x2A, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x02, 0xE1, 0x70, 0x20,
+0x1F, 0x02, 0xC3, 0x22, 0x30, 0x1E, 0x02, 0x80, 0xF9, 0xD2, 0x1A, 0x75, 0x17, 0x00, 0x75, 0x3F,
+0x00, 0x75, 0x3E, 0x00, 0x75, 0x3D, 0x00, 0x75, 0x3C, 0x00, 0x90, 0xEA, 0x5C, 0xE0, 0xF8, 0x90,
+0xEB, 0x6D, 0xE0, 0x65, 0x18, 0x70, 0x08, 0xA3, 0xE0, 0x65, 0x19, 0x70, 0x03, 0x80, 0x07, 0xA3,
+0xA3, 0xD8, 0xEF, 0xC3, 0x80, 0x01, 0xD3, 0x40, 0x0E, 0x75, 0x1C, 0xF8, 0x75, 0x1D, 0xFF, 0x12,
+0xE7, 0x77, 0x40, 0x05, 0x12, 0x2F, 0x9E, 0xC3, 0x22, 0x22, 0x20, 0x1F, 0x02, 0xC3, 0x22, 0x30,
+0x1E, 0x02, 0x80, 0xF9, 0xD2, 0x1A, 0x75, 0x3F, 0x00, 0x75, 0x3E, 0x00, 0x75, 0x3D, 0x00, 0x75,
+0x3C, 0x00, 0x90, 0xEA, 0x5C, 0xE0, 0xF8, 0x90, 0xEB, 0x6D, 0xE0, 0x65, 0x18, 0x70, 0x08, 0xA3,
+0xE0, 0x65, 0x19, 0x70, 0x03, 0x80, 0x07, 0xA3, 0xA3, 0xD8, 0xEF, 0xC3, 0x80, 0x01, 0xD3, 0x40,
+0x08, 0x12, 0xE6, 0x6F, 0x40, 0x05, 0x12, 0x2F, 0x9E, 0xC3, 0x22, 0x22, 0x20, 0x1F, 0x02, 0xC3,
+0x22, 0x30, 0x1E, 0x02, 0x80, 0xF9, 0xC3, 0xE5, 0x3D, 0x13, 0xF5, 0x14, 0xE5, 0x3E, 0x13, 0xF5,
+0x15, 0x30, 0x21, 0x39, 0x90, 0xEB, 0x2A, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3,
+0xE0, 0xFF, 0x90, 0xEA, 0x47, 0xE0, 0x14, 0xFB, 0x60, 0x12, 0xC3, 0xEC, 0x13, 0xFC, 0xED, 0x13,
+0xFD, 0xEE, 0x13, 0xFE, 0xEF, 0x13, 0xFF, 0xC3, 0xEB, 0x13, 0x80, 0xEB, 0x8E, 0x18, 0x8F, 0x19,
+0x90, 0xEB, 0x2D, 0xE0, 0xFF, 0x90, 0xEA, 0x47, 0xE0, 0x14, 0x5F, 0xF5, 0x1B, 0xD2, 0x1C, 0xC3,
+0x90, 0xEA, 0x47, 0xE0, 0x95, 0x1B, 0xF5, 0x16, 0xE5, 0x14, 0x70, 0x0A, 0xD3, 0xE5, 0x16, 0x95,
+0x15, 0x40, 0x03, 0x85, 0x15, 0x16, 0x90, 0xEA, 0x5C, 0xE0, 0xF8, 0x90, 0xEB, 0x6D, 0xE0, 0x65,
+0x18, 0x70, 0x08, 0xA3, 0xE0, 0x65, 0x19, 0x70, 0x03, 0x80, 0x07, 0xA3, 0xA3, 0xD8, 0xEF, 0xC3,
+0x80, 0x01, 0xD3, 0x50, 0x03, 0x02, 0xE4, 0x34, 0x20, 0x21, 0x2F, 0xC2, 0x42, 0x75, 0x10, 0x00,
+0xE5, 0x10, 0x65, 0x1B, 0x70, 0x03, 0x02, 0xE3, 0x7A, 0x12, 0x2F, 0x89, 0x40, 0x03, 0x02, 0xE4,
+0x31, 0xE5, 0x10, 0x70, 0x11, 0xC0, 0x1C, 0xC0, 0x1B, 0x75, 0x1B, 0x00, 0x75, 0x1C, 0xEF, 0x12,
+0x2F, 0x95, 0xD0, 0x1B, 0xD0, 0x1C, 0x05, 0x10, 0x80, 0xD6, 0x75, 0x17, 0x00, 0x30, 0x21, 0x06,
+0xC0, 0x18, 0xC0, 0x19, 0x80, 0x10, 0x75, 0x1C, 0xF8, 0x75, 0x1D, 0xFF, 0xC0, 0x18, 0xC0, 0x19,
+0x85, 0x11, 0x18, 0x85, 0x12, 0x19, 0xE5, 0x16, 0xB4, 0x01, 0x0C, 0x12, 0xE5, 0x11, 0x40, 0x13,
+0xD0, 0x19, 0xD0, 0x18, 0x02, 0xE4, 0x31, 0x12, 0x2F, 0x92, 0x40, 0x07, 0xD0, 0x19, 0xD0, 0x18,
+0x02, 0xE4, 0x31, 0xD0, 0x19, 0xD0, 0x18, 0xE5, 0x10, 0x25, 0x16, 0xF5, 0x10, 0x20, 0x21, 0x3A,
+0x90, 0xEA, 0x47, 0xE0, 0x65, 0x10, 0x60, 0x0C, 0x12, 0x2F, 0x89, 0x40, 0x03, 0x02, 0xE4, 0x31,
+0x05, 0x10, 0x80, 0xEC, 0x20, 0x42, 0x05, 0x12, 0xE7, 0x77, 0x80, 0x09, 0x75, 0x1B, 0x00, 0x75,
+0x1C, 0x7F, 0x12, 0x2F, 0x95, 0x75, 0x17, 0x00, 0x85, 0x11, 0x18, 0x85, 0x12, 0x19, 0x75, 0x1B,
+0x00, 0x75, 0x1C, 0xF8, 0x75, 0x1D, 0xFF, 0x12, 0xE6, 0x6F, 0xC3, 0xE5, 0x15, 0x95, 0x16, 0xF5,
+0x15, 0xE5, 0x14, 0x94, 0x00, 0xF5, 0x14, 0xE5, 0x15, 0x45, 0x14, 0x60, 0x16, 0x05, 0x19, 0xE5,
+0x19, 0x70, 0x02, 0x05, 0x18, 0x05, 0x0D, 0xE5, 0x0D, 0x70, 0x02, 0x05, 0x0C, 0x75, 0x1B, 0x00,
+0x02, 0xE3, 0x0F, 0x75, 0x3F, 0x00, 0x75, 0x3E, 0x00, 0x75, 0x3D, 0x00, 0x75, 0x3C, 0x00, 0xD3,
+0x22, 0x12, 0x2F, 0x9E, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80,
+0xF0, 0x75, 0x3F, 0x00, 0xC3, 0xE5, 0x15, 0x33, 0xF5, 0x3E, 0xE5, 0x14, 0x33, 0xF5, 0x3D, 0x75,
+0x3C, 0x00, 0xC3, 0x22, 0x75, 0x1A, 0x20, 0x12, 0x2F, 0xA4, 0x40, 0x03, 0x02, 0xE5, 0x0F, 0x79,
+0x0F, 0x90, 0xFE, 0x46, 0xE0, 0x54, 0xF0, 0x49, 0xF0, 0x78, 0xD2, 0x12, 0x2F, 0xAA, 0x30, 0x1C,
+0x5A, 0x30, 0x2D, 0x05, 0x75, 0x16, 0x01, 0x80, 0x03, 0x75, 0x16, 0x08, 0x75, 0x08, 0x00, 0xE5,
+0x08, 0x65, 0x16, 0x70, 0x02, 0x80, 0x55, 0x90, 0xFF, 0x09, 0x30, 0x25, 0x0B, 0xE0, 0x30, 0xE1,
+0xF9, 0x90, 0xFF, 0x09, 0xF0, 0xD3, 0x80, 0x01, 0xC3, 0x50, 0x0F, 0xAF, 0x08, 0x7C, 0xF0, 0x7D,
+0x00, 0xAB, 0x4D, 0xAA, 0x4C, 0x12, 0x2F, 0xBF, 0x40, 0x10, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1,
+0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0x02, 0xE5, 0x0A, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1,
+0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0x05, 0x08, 0x80, 0xB4, 0x7C, 0xF0, 0x7D, 0x00, 0x7B,
+0x00, 0x7A, 0x02, 0x7F, 0x00, 0x12, 0x2F, 0xBF, 0x40, 0x02, 0x80, 0x2E, 0x20, 0x1D, 0x08, 0x30,
+0x25, 0x03, 0x30, 0x24, 0xF7, 0xD2, 0x24, 0x30, 0x24, 0x02, 0xC3, 0x22, 0x79, 0x55, 0x7A, 0x01,
+0x12, 0x2F, 0xAD, 0x40, 0x02, 0x80, 0x18, 0x12, 0x2F, 0xB0, 0x30, 0x24, 0x02, 0xC3, 0x22, 0xEF,
+0x54, 0xC1, 0x64, 0x80, 0x60, 0x02, 0x80, 0x02, 0xD3, 0x22, 0x79, 0xC3, 0x12, 0x2F, 0x9B, 0xC3,
+0x22, 0xC0, 0x16, 0x30, 0x1E, 0x03, 0x02, 0xE5, 0x5C, 0x75, 0x09, 0x00, 0x7C, 0x08, 0x30, 0x2D,
+0x02, 0x7C, 0x20, 0x20, 0x25, 0x03, 0x02, 0xE5, 0x5C, 0xC0, 0x04, 0x12, 0xE4, 0x54, 0xD0, 0x04,
+0x50, 0x04, 0xD0, 0x16, 0xD3, 0x22, 0xA9, 0x09, 0xE9, 0x54, 0x07, 0x60, 0x0C, 0x90, 0xFE, 0x4C,
+0xE0, 0xF0, 0x90, 0xFE, 0x4D, 0xE0, 0xF0, 0x80, 0x09, 0x20, 0x25, 0x03, 0x02, 0xE5, 0x5C, 0x12,
+0x2F, 0xB3, 0x05, 0x09, 0xE5, 0x09, 0x6C, 0x60, 0x03, 0x02, 0xE5, 0x23, 0xD0, 0x16, 0xC3, 0x22,
+0xC0, 0x03, 0x75, 0x1A, 0x00, 0x12, 0x2F, 0xB6, 0x40, 0x04, 0xD0, 0x03, 0xC3, 0x22, 0xC2, 0x41,
+0x79, 0xAA, 0x7A, 0x00, 0x12, 0x2F, 0xAD, 0x50, 0xF1, 0xD0, 0x03, 0x1B, 0x8B, 0x08, 0xC2, 0x40,
+0x20, 0x20, 0x08, 0x30, 0x25, 0x03, 0x30, 0x24, 0xF7, 0xD2, 0x24, 0x30, 0x24, 0x02, 0xC3, 0x22,
+0x12, 0x2F, 0xB0, 0xC2, 0x20, 0xC2, 0x24, 0xEF, 0x54, 0xE1, 0xFF, 0x30, 0xE0, 0x03, 0x02, 0xE6,
+0x6D, 0x20, 0xE6, 0x0F, 0x30, 0xE7, 0x02, 0xD2, 0x40, 0x20, 0xE5, 0x19, 0x64, 0x80, 0x70, 0x03,
+0x02, 0xE6, 0x4B, 0x12, 0x2F, 0xB9, 0x40, 0x03, 0x02, 0xE6, 0x68, 0x90, 0xEB, 0xCA, 0xE0, 0x54,
+0x15, 0x60, 0x02, 0xD2, 0x41, 0xE5, 0x08, 0x70, 0x0E, 0x20, 0x40, 0x0B, 0x79, 0x33, 0x7A, 0x01,
+0x12, 0x2F, 0xAD, 0x40, 0x02, 0xC1, 0x6D, 0x12, 0x2F, 0xBC, 0x40, 0x02, 0xC1, 0x6D, 0x90, 0xEB,
+0xDE, 0xE0, 0x54, 0x30, 0x64, 0x30, 0x60, 0x02, 0xC1, 0x6D, 0x79, 0x00, 0x90, 0xFE, 0x46, 0xE0,
+0x54, 0xF0, 0x49, 0xF0, 0x79, 0x00, 0x78, 0x2D, 0x12, 0x2F, 0xAA, 0x90, 0xFF, 0x09, 0x30, 0x25,
+0x07, 0xE0, 0x30, 0xE5, 0xF9, 0xD3, 0x80, 0x01, 0xC3, 0x40, 0x02, 0x80, 0x5B, 0xC0, 0x01, 0x7E,
+0xF4, 0x7F, 0x00, 0x7D, 0x00, 0x7C, 0x02, 0x12, 0x2F, 0xC2, 0xD0, 0x01, 0x40, 0x09, 0x09, 0xE9,
+0x64, 0x20, 0x70, 0xD2, 0x02, 0xE6, 0x68, 0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0, 0xA3, 0x74, 0x00,
+0xF0, 0x20, 0x1D, 0x08, 0x30, 0x25, 0x03, 0x30, 0x24, 0xF7, 0xD2, 0x24, 0x30, 0x24, 0x02, 0xC3,
+0x22, 0x30, 0x40, 0x02, 0x80, 0x05, 0x15, 0x08, 0x02, 0xE5, 0x80, 0x30, 0x41, 0x16, 0x79, 0xCC,
+0x12, 0x2F, 0x9B, 0xC2, 0x1A, 0x90, 0xEA, 0x47, 0xE0, 0x65, 0x1B, 0x60, 0x07, 0x12, 0x2F, 0x8C,
+0x05, 0x1B, 0x80, 0xF1, 0xD2, 0x1A, 0xD3, 0x22, 0x79, 0xC3, 0x12, 0x2F, 0x9B, 0xC3, 0x22, 0xC0,
+0x08, 0x30, 0x1E, 0x02, 0x80, 0x33, 0x75, 0x1A, 0x40, 0x75, 0x1D, 0xFF, 0x75, 0x08, 0x00, 0x20,
+0x25, 0x02, 0x80, 0x25, 0x12, 0xE6, 0xAD, 0x50, 0x04, 0xD0, 0x08, 0xD3, 0x22, 0xA9, 0x08, 0xE9,
+0x54, 0x07, 0x60, 0x02, 0x80, 0x08, 0x20, 0x25, 0x02, 0x80, 0x0E, 0x12, 0x2F, 0xB3, 0x05, 0x08,
+0xE5, 0x08, 0x64, 0x20, 0x60, 0x03, 0x02, 0xE6, 0x7F, 0xD0, 0x08, 0xC3, 0x22, 0x90, 0xFE, 0x4C,
+0xE0, 0xF0, 0x90, 0xFE, 0x4D, 0xE0, 0xF0, 0xC2, 0x1D, 0xC2, 0x24, 0x90, 0xFE, 0x50, 0x74, 0x87,
+0xF0, 0x90, 0xFE, 0x40, 0x74, 0x00, 0xF0, 0x90, 0xFE, 0x40, 0x74, 0x00, 0xF0, 0x90, 0xFE, 0x40,
+0x74, 0x10, 0xF0, 0x90, 0xFE, 0x40, 0x74, 0x0F, 0xF0, 0x90, 0xFE, 0x57, 0x74, 0x0F, 0xF0, 0x90,
+0xFE, 0x44, 0x74, 0x01, 0xF0, 0x20, 0x1D, 0x08, 0x30, 0x25, 0x03, 0x30, 0x24, 0xF7, 0xD2, 0x24,
+0x30, 0x24, 0x02, 0xC3, 0x22, 0x79, 0x00, 0x90, 0xFE, 0x46, 0xE0, 0x54, 0xF0, 0x49, 0xF0, 0x90,
+0xFE, 0x4D, 0x30, 0x25, 0x07, 0xE0, 0x30, 0xE5, 0xF9, 0xD3, 0x80, 0x01, 0xC3, 0x40, 0x01, 0x22,
+0x78, 0xB4, 0x12, 0x2F, 0xAA, 0x90, 0xEA, 0x44, 0xE0, 0x90, 0xFE, 0x40, 0xF0, 0x78, 0x17, 0x7D,
+0x09, 0xE6, 0x08, 0x90, 0xFE, 0x40, 0xF0, 0xDD, 0xF8, 0x74, 0xFF, 0x90, 0xFE, 0x40, 0xF0, 0xF0,
+0xF0, 0xF0, 0xC2, 0x1D, 0xC2, 0x24, 0xF0, 0x20, 0x1D, 0x08, 0x30, 0x25, 0x03, 0x30, 0x24, 0xF7,
+0xD2, 0x24, 0x30, 0x24, 0x02, 0xC3, 0x22, 0x90, 0xFE, 0x4E, 0x30, 0x25, 0x07, 0xE0, 0x30, 0xE6,
+0xF9, 0xD3, 0x80, 0x01, 0xC3, 0x79, 0x55, 0x7A, 0x01, 0x12, 0x2F, 0xAD, 0x40, 0x02, 0x80, 0x13,
+0x12, 0x2F, 0xB0, 0x30, 0x24, 0x02, 0xC3, 0x22, 0xEF, 0x20, 0xE0, 0x07, 0x54, 0xC0, 0xB4, 0x80,
+0x02, 0x80, 0x02, 0xC3, 0x22, 0xD3, 0x22, 0x30, 0x1E, 0x02, 0x80, 0x0A, 0x12, 0xE7, 0x88, 0x40,
+0x03, 0x02, 0xE7, 0x86, 0xD3, 0x22, 0xC3, 0x22, 0xC0, 0x08, 0x75, 0x08, 0x00, 0x20, 0x25, 0x02,
+0x80, 0x25, 0x12, 0x2F, 0xA1, 0x50, 0x03, 0xD0, 0x08, 0x22, 0xA9, 0x08, 0xE9, 0x54, 0x07, 0x60,
+0x02, 0x80, 0x09, 0xA2, 0x25, 0x40, 0x02, 0x80, 0x0E, 0x12, 0x2F, 0xB3, 0x05, 0x08, 0xE5, 0x08,
+0x64, 0x20, 0x60, 0x03, 0x02, 0xE7, 0x8D, 0xD0, 0x08, 0xC3, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x4D, 0x53, 0x2D, 0x52, 0x57, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30 };
+
+BYTE SM_Init[] = {
+0x7B, 0x09, 0x7C, 0xF0, 0x7D, 0x10, 0x7E, 0xE9, 0x7F, 0xCC, 0x12, 0x2F, 0x71, 0x90, 0xE9, 0xCC,
+0xE0, 0xB4, 0x07, 0x12, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80,
+0xF0, 0x12, 0x2F, 0x5C, 0xD3, 0x22, 0x78, 0x00, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x0A,
+0x20, 0x0A, 0x03, 0x02, 0xE0, 0xD0, 0x7F, 0x00, 0x12, 0x2F, 0xCB, 0x20, 0x01, 0x05, 0xC2, 0x25,
+0x02, 0xE0, 0xEB, 0xC3, 0xE8, 0x94, 0x02, 0x40, 0x03, 0x02, 0xE0, 0xD0, 0xC0, 0x00, 0x90, 0xFE,
+0x66, 0x74, 0x90, 0xF0, 0x12, 0xE1, 0x40, 0x90, 0xFF, 0x95, 0xE0, 0xC2, 0xE4, 0xF0, 0x90, 0xFF,
+0x97, 0x74, 0x01, 0xF0, 0x7E, 0x01, 0x7F, 0x90, 0x12, 0x2F, 0x74, 0x90, 0xFF, 0x97, 0x74, 0x03,
+0xF0, 0x90, 0xFE, 0xC5, 0xE4, 0xF0, 0x74, 0x00, 0x90, 0xFE, 0x6A, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0,
+0xA3, 0xF0, 0x7E, 0x23, 0x7F, 0xDC, 0x12, 0x2F, 0x74, 0x12, 0x2F, 0x5C, 0x90, 0xFE, 0x64, 0xE0,
+0x54, 0x01, 0x60, 0x04, 0xD2, 0x02, 0x80, 0x02, 0xC2, 0x02, 0x90, 0xFF, 0x95, 0xE0, 0xD2, 0xE4,
+0xF0, 0x78, 0x10, 0x79, 0x04, 0x12, 0xE1, 0x71, 0x50, 0x3A, 0x90, 0xE9, 0xC6, 0xE0, 0x90, 0xE9,
+0xC3, 0xF0, 0x78, 0x9A, 0x79, 0x04, 0x12, 0xE1, 0x71, 0x50, 0x29, 0x90, 0xE9, 0xC7, 0xE0, 0xB4,
+0xB5, 0x22, 0x90, 0xE9, 0xC4, 0xF0, 0xD0, 0x00, 0xD2, 0x00, 0xC2, 0x01, 0xC2, 0x25, 0x80, 0x1B,
+0xC2, 0x00, 0xD2, 0x01, 0x74, 0xFF, 0x90, 0xE9, 0xC3, 0xF0, 0xA3, 0xF0, 0x51, 0x01, 0xC2, 0x0A,
+0xC2, 0x02, 0x80, 0x07, 0xD0, 0x00, 0x05, 0x00, 0x02, 0xE0, 0x43, 0x90, 0xFF, 0x09, 0xE0, 0x30,
+0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xFC, 0xE4,
+0xA2, 0x0A, 0x92, 0xE0, 0xA2, 0x00, 0x92, 0xE1, 0xA2, 0x01, 0x92, 0xE2, 0xA2, 0x02, 0x92, 0xE6,
+0xA2, 0x25, 0x92, 0xE7, 0x90, 0xF4, 0x00, 0xF0, 0x90, 0xE9, 0xC3, 0xE0, 0x90, 0xF4, 0x01, 0xF0,
+0x90, 0xE9, 0xC4, 0xE0, 0x90, 0xF4, 0x02, 0xF0, 0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0, 0xA3, 0x74,
+0x00, 0xF0, 0x75, 0x3C, 0x00, 0x75, 0x3D, 0x00, 0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22,
+0x90, 0xFE, 0x71, 0xE4, 0xF0, 0x90, 0xFE, 0x72, 0x74, 0x01, 0xF0, 0x90, 0xFE, 0x64, 0x74, 0x0C,
+0xF0, 0x90, 0xFE, 0x64, 0x74, 0x00, 0x45, 0x4E, 0xF0, 0x90, 0xFE, 0x64, 0xE0, 0x54, 0x10, 0x60,
+0x08, 0x90, 0xFE, 0x72, 0x74, 0x81, 0xF0, 0xD3, 0x22, 0x90, 0xFE, 0x64, 0x74, 0x08, 0xF0, 0xC3,
+0x22, 0x90, 0xFE, 0x6F, 0xE9, 0x14, 0xF0, 0x90, 0xFE, 0x70, 0xE0, 0x54, 0xFC, 0xF0, 0x90, 0xFE,
+0x68, 0x74, 0x00, 0xF0, 0xB8, 0x9A, 0x2A, 0x74, 0x15, 0x90, 0xFE, 0x64, 0xF0, 0x74, 0x9A, 0x90,
+0xFE, 0x60, 0xF0, 0x74, 0x16, 0x90, 0xFE, 0x64, 0xF0, 0x74, 0x00, 0x90, 0xFE, 0x60, 0xF0, 0x30,
+0x0A, 0x5D, 0x90, 0xFE, 0x64, 0xE0, 0x20, 0xE7, 0xF6, 0x74, 0x14, 0x90, 0xFE, 0x64, 0xF0, 0x80,
+0x20, 0x90, 0xFE, 0x6E, 0xE8, 0x44, 0x01, 0xF0, 0xC2, 0x09, 0x12, 0xE3, 0x26, 0x20, 0x08, 0x0E,
+0x12, 0xE3, 0x32, 0x30, 0x3E, 0xF7, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x09, 0x20, 0x09,
+0x2E, 0x7A, 0xE9, 0x7B, 0xC5, 0x7C, 0xFE, 0x7D, 0x60, 0xB8, 0x10, 0x07, 0x90, 0xFE, 0x69, 0xE0,
+0x20, 0xE6, 0xFC, 0x8C, 0x83, 0x8D, 0x82, 0xE0, 0x8A, 0x83, 0x8B, 0x82, 0xF0, 0xA3, 0xAA, 0x83,
+0xAB, 0x82, 0xD9, 0xE5, 0xB8, 0x9A, 0x06, 0x74, 0x10, 0x90, 0xFE, 0x64, 0xF0, 0xD3, 0x22, 0xC3,
+0x22, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25, 0x20, 0x25, 0x06, 0xC2, 0x1F, 0xD2, 0x19,
+0xC3, 0x22, 0x7F, 0x02, 0x12, 0x2F, 0xCB, 0x20, 0x19, 0x05, 0x30, 0x1F, 0x02, 0xD3, 0x22, 0x90,
+0xEA, 0x44, 0x74, 0x80, 0xF0, 0x7F, 0x10, 0x12, 0x2F, 0xC5, 0x90, 0xFE, 0x47, 0xE0, 0x44, 0x80,
+0xF0, 0x78, 0x00, 0xE8, 0xC3, 0x94, 0x04, 0x50, 0x0A, 0x7F, 0x88, 0x7E, 0x13, 0x12, 0xE3, 0x4D,
+0x08, 0x80, 0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0xFB, 0xF0, 0x90, 0xFE, 0x47, 0xE0, 0x54, 0xBF,
+0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0xFE, 0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0x7F, 0xF0, 0x90,
+0xFE, 0x46, 0xE0, 0x44, 0x40, 0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0xC7, 0x44, 0x18, 0xF0, 0x90,
+0xFE, 0x47, 0xE0, 0x44, 0x08, 0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x44, 0x40, 0xF0, 0x7F, 0x32, 0x7E,
+0x00, 0x12, 0xE3, 0x4D, 0x90, 0xFE, 0x51, 0xE0, 0x54, 0x33, 0xF0, 0x90, 0xFE, 0x44, 0x74, 0x02,
+0xF0, 0x30, 0x25, 0x04, 0xE0, 0x20, 0xE1, 0xF9, 0x90, 0xFE, 0x51, 0xE0, 0x54, 0x0F, 0xF0, 0x90,
+0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25, 0x04, 0xE0, 0x20, 0xE1, 0xF9, 0x90, 0xFE, 0x44, 0x74,
+0x04, 0xF0, 0x30, 0x25, 0x04, 0xE0, 0x20, 0xE2, 0xF9, 0x90, 0xFE, 0x4C, 0xE0, 0xF0, 0x90, 0xFE,
+0x4D, 0xE0, 0xF0, 0x90, 0xFE, 0x48, 0x74, 0x7F, 0xF0, 0x90, 0xFE, 0x49, 0x74, 0x9F, 0xF0, 0x90,
+0xFE, 0x51, 0xE0, 0x54, 0x3C, 0x44, 0x02, 0xF0, 0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25,
+0x04, 0xE0, 0x20, 0xE1, 0xF9, 0x90, 0xFE, 0x46, 0xE0, 0x44, 0x20, 0xF0, 0x79, 0x02, 0x7A, 0x06,
+0x7B, 0x00, 0x7C, 0x00, 0x7D, 0x06, 0x7E, 0xEB, 0x7F, 0xC9, 0x12, 0x2F, 0xA7, 0x40, 0x03, 0x02,
+0xE3, 0x04, 0xD3, 0x22, 0xE4, 0x90, 0xFE, 0x48, 0xF0, 0x90, 0xFE, 0x49, 0xF0, 0x90, 0xFE, 0x4C,
+0xE0, 0xF0, 0x90, 0xFE, 0x4D, 0xE0, 0xF0, 0x90, 0xFE, 0x47, 0xE0, 0x54, 0x7F, 0xF0, 0xC2, 0x25,
+0xC2, 0x1F, 0xD2, 0x19, 0xC3, 0x22, 0xC2, 0x3E, 0x75, 0x7C, 0x00, 0x75, 0x7D, 0x00, 0x75, 0x7E,
+0x00, 0x22, 0x05, 0x7C, 0xE5, 0x7C, 0x70, 0x14, 0x05, 0x7D, 0xE5, 0x7D, 0x70, 0x04, 0x05, 0x7E,
+0x80, 0x0A, 0xB4, 0x17, 0x07, 0xE5, 0x7E, 0xB4, 0x06, 0x02, 0xD2, 0x3E, 0x22, 0x75, 0x8A, 0x00,
+0x75, 0x8C, 0xCE, 0xC2, 0x8D, 0x90, 0xEA, 0x65, 0xE4, 0xF0, 0xA3, 0xF0, 0xD2, 0x8C, 0x90, 0xEA,
+0x65, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEC, 0xC3, 0x9E, 0x40, 0xF3, 0x70, 0x05, 0xED, 0xC3, 0x9F,
+0x40, 0xEC, 0xC2, 0x8C, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x58, 0x44, 0x2D, 0x49, 0x6E, 0x69, 0x74, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x31 };
+
+BYTE SM_Rdwr[] = {
+0x7B, 0x0C, 0x7C, 0xF0, 0x7D, 0x10, 0x7E, 0xE9, 0x7F, 0xCC, 0x12, 0x2F, 0x71, 0x90, 0xE9, 0xC3,
+0xE0, 0xB4, 0x73, 0x04, 0x74, 0x40, 0x80, 0x09, 0xB4, 0x75, 0x04, 0x74, 0x40, 0x80, 0x02, 0x74,
+0xC0, 0x90, 0xFE, 0x70, 0xF0, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74,
+0x80, 0xF0, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x0A, 0x40, 0x01, 0x22, 0x90, 0xFE, 0x6A,
+0xE4, 0xF0, 0x90, 0xE9, 0xCC, 0xE0, 0xB4, 0x02, 0x05, 0xD2, 0x06, 0x02, 0xE0, 0x78, 0xB4, 0x03,
+0x03, 0x02, 0xE3, 0xD0, 0xB4, 0x04, 0x03, 0x02, 0xE1, 0xC6, 0xB4, 0x05, 0x03, 0x02, 0xE5, 0x20,
+0xB4, 0x06, 0x03, 0x02, 0xE5, 0xE0, 0xB4, 0x07, 0x05, 0x12, 0x2F, 0x5C, 0xD3, 0x22, 0xB4, 0x08,
+0x05, 0xC2, 0x06, 0x02, 0xE6, 0x3B, 0xC3, 0x22, 0xE5, 0x3E, 0xC3, 0x13, 0x90, 0xE9, 0xCA, 0xF0,
+0xC0, 0xE0, 0x75, 0xF0, 0x02, 0xC0, 0xF0, 0x12, 0xE0, 0xD8, 0xEF, 0x70, 0x21, 0x20, 0x37, 0x07,
+0x20, 0x09, 0x04, 0xD0, 0xF0, 0x80, 0x05, 0xD0, 0xF0, 0xD5, 0xF0, 0xE9, 0xD0, 0xE0, 0x90, 0xFF,
+0x28, 0xE0, 0x30, 0xE7, 0xFC, 0x90, 0xFF, 0x28, 0xE0, 0x44, 0x01, 0xF0, 0xC3, 0x22, 0xD0, 0xF0,
+0x90, 0xE9, 0xCF, 0xE0, 0x24, 0x01, 0xF0, 0x90, 0xE9, 0xCE, 0xE0, 0x34, 0x00, 0xF0, 0x90, 0xE9,
+0xCD, 0xE0, 0x34, 0x00, 0xF0, 0xD0, 0xE0, 0x14, 0x70, 0xB6, 0x75, 0x3C, 0x00, 0x75, 0x3D, 0x00,
+0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22, 0xC2, 0x08, 0xC2, 0x36, 0xC2, 0x37, 0xE4, 0x90,
+0xEB, 0xC2, 0xF0, 0x90, 0xE9, 0xCD, 0xE0, 0xF8, 0xA3, 0xE0, 0xF9, 0xA3, 0xE0, 0x90, 0xFE, 0x6B,
+0xF0, 0xA3, 0xE9, 0xF0, 0xA3, 0xE8, 0xF0, 0x90, 0xFE, 0x6F, 0x74, 0x0F, 0xF0, 0x90, 0xFE, 0x70,
+0xE0, 0x54, 0xFC, 0x44, 0x02, 0xF0, 0x90, 0xFE, 0xC6, 0x74, 0x02, 0xF0, 0xA3, 0x74, 0x0F, 0xF0,
+0x90, 0xFE, 0xC0, 0x74, 0xF4, 0xF0, 0x74, 0x00, 0xA3, 0xF0, 0x90, 0xFE, 0x68, 0x74, 0x21, 0xF0,
+0x90, 0xFE, 0x64, 0x74, 0x70, 0x45, 0x4E, 0xF0, 0x90, 0xFE, 0x64, 0x74, 0x30, 0x45, 0x4E, 0xF0,
+0x30, 0x06, 0x07, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xFC, 0x90, 0xFE, 0x6E, 0x74, 0x51, 0xF0,
+0x90, 0xFE, 0xC4, 0x74, 0x21, 0xF0, 0xC2, 0x09, 0x12, 0xE7, 0xB0, 0x20, 0x08, 0x0E, 0x12, 0xE7,
+0xBC, 0x30, 0x3E, 0xF7, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x09, 0x30, 0x09, 0x03, 0x7F,
+0x00, 0x22, 0x12, 0xE7, 0xB0, 0x20, 0x36, 0x11, 0x20, 0x37, 0x0E, 0x12, 0xE7, 0xBC, 0x30, 0x3E,
+0xF4, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x37, 0x30, 0x37, 0x03, 0x7F, 0x00, 0x22, 0x90,
+0xFE, 0x64, 0x74, 0x10, 0x45, 0x4E, 0xF0, 0x90, 0xFE, 0x64, 0x74, 0x00, 0x45, 0x4E, 0xF0, 0x12,
+0x2F, 0x65, 0x12, 0x2F, 0x68, 0xBF, 0x00, 0x09, 0x74, 0x02, 0x90, 0xEB, 0xC2, 0xF0, 0x7F, 0x00,
+0x22, 0x12, 0x2F, 0x6B, 0xBF, 0x00, 0x0F, 0x12, 0x2F, 0x6E, 0xBF, 0x00, 0x09, 0x74, 0x01, 0x90,
+0xEB, 0xC2, 0xF0, 0x7F, 0x00, 0x22, 0x30, 0x06, 0x0A, 0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0, 0xA3,
+0x74, 0x00, 0xF0, 0x7F, 0x01, 0x22, 0x12, 0xE3, 0xAA, 0x74, 0x01, 0x90, 0xE9, 0xCB, 0xF0, 0xE5,
+0x3E, 0xC3, 0x13, 0x90, 0xE9, 0xCA, 0xF0, 0xC0, 0xE0, 0x75, 0xF0, 0x02, 0xC0, 0xF0, 0x12, 0xE2,
+0x2F, 0xEF, 0x70, 0x21, 0x20, 0x37, 0x07, 0x20, 0x09, 0x04, 0xD0, 0xF0, 0x80, 0x05, 0xD0, 0xF0,
+0xD5, 0xF0, 0xE9, 0xD0, 0xE0, 0x90, 0xFF, 0x28, 0xE0, 0x30, 0xE7, 0xFC, 0x90, 0xFF, 0x28, 0xE0,
+0x44, 0x01, 0xF0, 0xC3, 0x22, 0xD0, 0xF0, 0x90, 0xE9, 0xD2, 0xE0, 0x24, 0x01, 0xF0, 0x90, 0xE9,
+0xD1, 0xE0, 0x34, 0x00, 0xF0, 0x90, 0xE9, 0xD0, 0xE0, 0x34, 0x00, 0xF0, 0xD0, 0xE0, 0x14, 0x70,
+0xB6, 0x75, 0x3C, 0x00, 0x75, 0x3D, 0x00, 0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22, 0xC2,
+0x08, 0xC2, 0x36, 0xC2, 0x37, 0x90, 0xFE, 0x68, 0x74, 0x31, 0xF0, 0x90, 0xE9, 0xD0, 0xE0, 0xF8,
+0xA3, 0xE0, 0xF9, 0xA3, 0xE0, 0x90, 0xFE, 0x6B, 0xF0, 0xA3, 0xE9, 0xF0, 0xA3, 0xE8, 0xF0, 0x90,
+0xFE, 0x6F, 0x74, 0x0F, 0xF0, 0x90, 0xFE, 0x70, 0xE0, 0x54, 0xFC, 0x44, 0x22, 0xF0, 0x90, 0xE9,
+0xCB, 0xE0, 0x70, 0x0C, 0x90, 0xFE, 0xC0, 0x74, 0xF4, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0x80, 0x0A,
+0x90, 0xFE, 0xC0, 0x74, 0xF0, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0x90, 0xFE, 0x64, 0x74, 0xF0, 0x45,
+0x4E, 0xF0, 0x90, 0xFE, 0x64, 0x74, 0xB0, 0x45, 0x4E, 0xF0, 0x90, 0xFE, 0x6E, 0x74, 0x81, 0xF0,
+0x90, 0xE9, 0xCB, 0xE0, 0x70, 0x0D, 0x90, 0xFE, 0xC6, 0x74, 0x02, 0xF0, 0xA3, 0x74, 0x0F, 0xF0,
+0x02, 0xE3, 0x56, 0x20, 0x2D, 0x03, 0x02, 0xE2, 0xEF, 0x90, 0xFE, 0xC6, 0x74, 0x01, 0xF0, 0xA3,
+0x74, 0xFF, 0xF0, 0x90, 0xFF, 0x09, 0x30, 0x0A, 0x04, 0xE0, 0x30, 0xE1, 0xF9, 0x90, 0xFE, 0xC4,
+0x74, 0x23, 0xF0, 0x12, 0xE7, 0xB0, 0x20, 0x36, 0x11, 0x20, 0x37, 0x0E, 0x12, 0xE7, 0xBC, 0x30,
+0x3E, 0xF4, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x37, 0x30, 0x37, 0x02, 0x61, 0xA7, 0x90,
+0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0x02, 0xE3, 0x3F, 0x90,
+0xFE, 0xC6, 0xE4, 0xF0, 0xA3, 0x74, 0x3F, 0xF0, 0x78, 0x08, 0xC0, 0x00, 0xC2, 0x36, 0xC2, 0x37,
+0x90, 0xFF, 0x09, 0x30, 0x0A, 0x04, 0xE0, 0x30, 0xE1, 0xF9, 0x90, 0xFE, 0xC4, 0x74, 0x23, 0xF0,
+0x12, 0xE7, 0xB0, 0x20, 0x36, 0x11, 0x20, 0x37, 0x0E, 0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF4, 0x90,
+0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x37, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF,
+0x23, 0x74, 0x80, 0xF0, 0x30, 0x37, 0x04, 0xD0, 0x00, 0x80, 0x6C, 0xD0, 0x00, 0xD8, 0xBB, 0xC2,
+0x36, 0xC2, 0x37, 0x90, 0xFE, 0xC6, 0xE4, 0xF0, 0xA3, 0x74, 0x0F, 0xF0, 0x90, 0xFE, 0xC0, 0x74,
+0xF6, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0x90, 0xFE, 0xC4, 0x74, 0x23, 0xF0, 0x12, 0xE7, 0xB0, 0x20,
+0x36, 0x11, 0x20, 0x37, 0x0E, 0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF4, 0x90, 0xFE, 0xD8, 0x74, 0x01,
+0xF0, 0xD2, 0x37, 0x30, 0x37, 0x02, 0x80, 0x2F, 0xC2, 0x09, 0x12, 0xE7, 0xB0, 0x20, 0x08, 0x0E,
+0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF7, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x09, 0x30, 0x09,
+0x02, 0x80, 0x14, 0x90, 0xFE, 0x64, 0x74, 0x90, 0x45, 0x4E, 0xF0, 0x90, 0xFE, 0x64, 0x74, 0x80,
+0x45, 0x4E, 0xF0, 0x12, 0x2F, 0x59, 0x22, 0x7F, 0x00, 0x22, 0x90, 0xF6, 0x00, 0x7F, 0x06, 0x74,
+0xFF, 0xF0, 0xA3, 0xDF, 0xFC, 0x7B, 0x02, 0x7C, 0xE9, 0x7D, 0xD3, 0x7E, 0xF6, 0x7F, 0x06, 0x12,
+0x2F, 0x71, 0x7B, 0x02, 0x7C, 0xE9, 0x7D, 0xD3, 0x7E, 0xF6, 0x7F, 0x0B, 0x12, 0x2F, 0x71, 0x22,
+0x90, 0xFE, 0xC6, 0xE4, 0xF0, 0xA3, 0x74, 0x0F, 0xF0, 0x90, 0xFE, 0x6F, 0xF0, 0x90, 0xFE, 0x70,
+0xE0, 0x54, 0xFC, 0xF0, 0x90, 0xFE, 0xC0, 0x74, 0xF6, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0x90, 0xFE,
+0x68, 0x74, 0x21, 0xF0, 0x90, 0xFE, 0x66, 0xE0, 0x54, 0xEF, 0xF0, 0x90, 0xE9, 0xD3, 0xE0, 0xF5,
+0x08, 0xA3, 0xE0, 0xF5, 0x09, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xFC, 0xE4, 0xF5, 0x10, 0x7E,
+0xF4, 0x7F, 0x00, 0xC0, 0x06, 0xC0, 0x07, 0xC2, 0x36, 0xC2, 0x37, 0xC2, 0x09, 0x90, 0xE9, 0xCD,
+0xE0, 0xF8, 0xA3, 0xE0, 0xF9, 0xA3, 0xE0, 0x90, 0xFE, 0x6B, 0xF0, 0xA3, 0xE9, 0xF0, 0xA3, 0xE8,
+0xF0, 0x90, 0xFE, 0x6E, 0x74, 0x71, 0xF0, 0x90, 0xFE, 0xC4, 0x74, 0x21, 0xF0, 0x90, 0xFE, 0x65,
+0x12, 0xE7, 0xB0, 0xE0, 0x20, 0xE4, 0x11, 0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF6, 0x90, 0xFE, 0xD8,
+0x74, 0x01, 0xF0, 0xD2, 0x09, 0x02, 0xE4, 0x72, 0x74, 0x10, 0xF0, 0x12, 0xE7, 0xB0, 0x20, 0x36,
+0x11, 0x20, 0x37, 0x0E, 0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF4, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0,
+0xD2, 0x37, 0x20, 0x09, 0x05, 0x20, 0x37, 0x02, 0x80, 0x10, 0x90, 0xFE, 0x66, 0xE0, 0x44, 0x10,
+0xF0, 0x12, 0x2F, 0x5C, 0xD0, 0x07, 0xD0, 0x06, 0xC3, 0x22, 0xD0, 0x07, 0xD0, 0x06, 0x7B, 0x10,
+0x7C, 0xF6, 0x7D, 0x00, 0x12, 0x2F, 0x71, 0x05, 0x10, 0xC3, 0xE5, 0x09, 0x94, 0x01, 0xF5, 0x09,
+0xE5, 0x08, 0x94, 0x00, 0xF5, 0x08, 0x45, 0x09, 0x70, 0x03, 0x02, 0xE4, 0xEF, 0x90, 0xE9, 0xCF,
+0xE0, 0x24, 0x20, 0xF0, 0x90, 0xE9, 0xCE, 0xE0, 0x34, 0x00, 0xF0, 0x90, 0xE9, 0xCD, 0xE0, 0x34,
+0x00, 0xF0, 0xC3, 0xEF, 0x24, 0x10, 0xFF, 0xEE, 0x34, 0x00, 0xFE, 0xE5, 0x10, 0x64, 0x20, 0x60,
+0x03, 0x02, 0xE4, 0x13, 0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0x75, 0x10,
+0x00, 0x7E, 0xF4, 0x7F, 0x00, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xFC, 0x02, 0xE4, 0x13, 0xE5,
+0x10, 0x60, 0x17, 0x7E, 0x00, 0x7F, 0x00, 0x78, 0x04, 0xC3, 0x33, 0xFF, 0xEE, 0x33, 0xFE, 0xEF,
+0xD8, 0xF8, 0x90, 0xFF, 0x2A, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0xFE, 0x66, 0xE0, 0x44, 0x10,
+0xF0, 0x12, 0x2F, 0x5C, 0x78, 0x00, 0x88, 0x3C, 0x88, 0x3D, 0x88, 0x3E, 0x88, 0x3F, 0xD3, 0x22,
+0x12, 0x2F, 0x5F, 0x12, 0x2F, 0x62, 0x90, 0xFE, 0xC6, 0xE4, 0xF0, 0xA3, 0x74, 0x0F, 0xF0, 0x90,
+0xFE, 0x6F, 0xF0, 0x90, 0xFE, 0x70, 0xE0, 0x54, 0xFC, 0xF0, 0x90, 0xFE, 0xC0, 0x74, 0xF6, 0xF0,
+0xA3, 0x74, 0x00, 0xF0, 0x90, 0xFE, 0x68, 0x74, 0x31, 0xF0, 0x90, 0xE9, 0xD3, 0xE0, 0xF8, 0xC0,
+0x00, 0xC2, 0x08, 0xC2, 0x36, 0xC2, 0x37, 0x90, 0xE9, 0xD0, 0xE0, 0xF8, 0xA3, 0xE0, 0xF9, 0xA3,
+0xE0, 0x90, 0xFE, 0x6B, 0xF0, 0xA3, 0xE9, 0xF0, 0xA3, 0xE8, 0xF0, 0x90, 0xFE, 0x6E, 0x74, 0x81,
+0xF0, 0x90, 0xFE, 0xC4, 0x74, 0x23, 0xF0, 0x12, 0xE7, 0xB0, 0x20, 0x36, 0x11, 0x20, 0x37, 0x0E,
+0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF4, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x37, 0x30, 0x37,
+0x07, 0xD0, 0x00, 0x12, 0x2F, 0x5C, 0xC3, 0x22, 0xC2, 0x09, 0x12, 0xE7, 0xB0, 0x20, 0x08, 0x0E,
+0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF7, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x09, 0x20, 0x09,
+0xE0, 0x90, 0xE9, 0xD2, 0xE0, 0x24, 0x01, 0xF0, 0x90, 0xE9, 0xD1, 0xE0, 0x34, 0x00, 0xF0, 0x90,
+0xE9, 0xD0, 0xE0, 0x34, 0x00, 0xF0, 0xD0, 0x00, 0x18, 0xE8, 0x60, 0x03, 0x02, 0xE5, 0x4F, 0x12,
+0x2F, 0x5C, 0x75, 0x3C, 0x00, 0x75, 0x3D, 0x00, 0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22,
+0x90, 0xE9, 0xD0, 0xE0, 0xF8, 0xA3, 0xE0, 0xF9, 0xA3, 0xE0, 0x90, 0xFE, 0x6B, 0xF0, 0xA3, 0xE9,
+0xF0, 0xA3, 0xE8, 0xF0, 0x90, 0xFE, 0x68, 0x74, 0x00, 0xF0, 0xC2, 0x08, 0x90, 0xFE, 0x6E, 0x74,
+0xB1, 0xF0, 0xC2, 0x09, 0x12, 0xE7, 0xB0, 0x20, 0x08, 0x0E, 0x12, 0xE7, 0xBC, 0x30, 0x3E, 0xF7,
+0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xD2, 0x09, 0x20, 0x09, 0x1E, 0x90, 0xFE, 0x70, 0xE0, 0x44,
+0x10, 0xF0, 0x54, 0xEF, 0xF0, 0x12, 0x2F, 0x59, 0xEF, 0x60, 0x0E, 0x75, 0x3C, 0x00, 0x75, 0x3D,
+0x00, 0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22, 0xC3, 0x22, 0x7B, 0x03, 0x7C, 0xE9, 0x7D,
+0xCD, 0x7E, 0xE9, 0x7F, 0xD7, 0x12, 0x2F, 0x71, 0x12, 0xE3, 0xAA, 0x90, 0xE9, 0xD5, 0xE0, 0x60,
+0x12, 0xF9, 0x12, 0xE7, 0x17, 0x40, 0x01, 0x22, 0x90, 0xF6, 0x00, 0x78, 0x06, 0x74, 0xFF, 0xF0,
+0xA3, 0xD8, 0xFC, 0x74, 0x01, 0x90, 0xE9, 0xCB, 0xF0, 0xE5, 0x3E, 0xC3, 0x13, 0x90, 0xE9, 0xCA,
+0xF0, 0xC0, 0xE0, 0x75, 0xF0, 0x02, 0xC0, 0xF0, 0x12, 0xE2, 0x2F, 0xEF, 0x70, 0x21, 0x20, 0x37,
+0x07, 0x20, 0x09, 0x04, 0xD0, 0xF0, 0x80, 0x05, 0xD0, 0xF0, 0xD5, 0xF0, 0xE9, 0xD0, 0xE0, 0x90,
+0xFF, 0x28, 0xE0, 0x30, 0xE7, 0xFC, 0x90, 0xFF, 0x28, 0xE0, 0x44, 0x01, 0xF0, 0xC3, 0x22, 0xD0,
+0xF0, 0x90, 0xE9, 0xD2, 0xE0, 0x24, 0x01, 0xF0, 0x90, 0xE9, 0xD1, 0xE0, 0x34, 0x00, 0xF0, 0x90,
+0xE9, 0xD0, 0xE0, 0x34, 0x00, 0xF0, 0xD0, 0xE0, 0x14, 0x70, 0xB6, 0x90, 0xE9, 0xD5, 0xE0, 0xF8,
+0x90, 0xE9, 0xCA, 0xE0, 0x28, 0xF5, 0xF0, 0xC3, 0x74, 0x20, 0x95, 0xF0, 0x60, 0x22, 0xF9, 0x90,
+0xE9, 0xCA, 0xE0, 0xF5, 0xF0, 0x90, 0xE9, 0xCF, 0xE0, 0x25, 0xF0, 0xF0, 0x90, 0xE9, 0xCE, 0xE0,
+0x34, 0x00, 0xF0, 0x90, 0xE9, 0xCD, 0xE0, 0x34, 0x00, 0xF0, 0x12, 0xE7, 0x17, 0x40, 0x01, 0x22,
+0x90, 0xE9, 0xD6, 0xE0, 0x70, 0x13, 0x7B, 0x03, 0x7C, 0xE9, 0x7D, 0xD7, 0x7E, 0xE9, 0x7F, 0xD0,
+0x12, 0x2F, 0x71, 0x12, 0xE5, 0xE0, 0x40, 0x01, 0x22, 0x75, 0x3C, 0x00, 0x75, 0x3D, 0x00, 0x75,
+0x3E, 0x00, 0x75, 0x3F, 0x00, 0xD3, 0x22, 0x90, 0xE9, 0xD6, 0xE0, 0x60, 0x18, 0x74, 0xFF, 0x90,
+0xF4, 0x00, 0x78, 0xFF, 0xF0, 0xA3, 0x18, 0xB8, 0x00, 0xFA, 0x78, 0xFF, 0xF0, 0xA3, 0x18, 0xB8,
+0x00, 0xFA, 0xF0, 0xA3, 0xF0, 0xC0, 0x01, 0x12, 0xE7, 0x70, 0x40, 0x04, 0xD0, 0x01, 0xC3, 0x22,
+0x90, 0xE9, 0xCF, 0xE0, 0x24, 0x01, 0xF0, 0x90, 0xE9, 0xCE, 0xE0, 0x34, 0x00, 0xF0, 0x90, 0xE9,
+0xCD, 0xE0, 0x34, 0x00, 0xF0, 0x90, 0xE9, 0xD2, 0xE0, 0x24, 0x01, 0xF0, 0x90, 0xE9, 0xD1, 0xE0,
+0x34, 0x00, 0xF0, 0x90, 0xE9, 0xD0, 0xE0, 0x34, 0x00, 0xF0, 0xD0, 0x01, 0xD9, 0xC7, 0xD3, 0x22,
+0xC2, 0x06, 0x90, 0xE9, 0xD6, 0xE0, 0x70, 0x28, 0x12, 0xE0, 0xD8, 0xEF, 0x60, 0x03, 0x02, 0xE7,
+0xA0, 0x90, 0xEB, 0xC2, 0xE0, 0x60, 0x17, 0x64, 0x02, 0x60, 0x15, 0x90, 0xF6, 0x00, 0x78, 0x06,
+0x74, 0xFF, 0xF0, 0xA3, 0xD8, 0xFC, 0x74, 0xF0, 0x90, 0xF6, 0x04, 0xF0, 0x80, 0x02, 0xC3, 0x22,
+0xE4, 0x90, 0xE9, 0xCB, 0xF0, 0x12, 0xE2, 0x2F, 0xEF, 0x70, 0x03, 0x02, 0xE7, 0x81, 0xD3, 0x22,
+0xC2, 0x3E, 0x75, 0x7C, 0x00, 0x75, 0x7D, 0x00, 0x75, 0x7E, 0x00, 0x22, 0x05, 0x7C, 0xE5, 0x7C,
+0x70, 0x14, 0x05, 0x7D, 0xE5, 0x7D, 0x70, 0x04, 0x05, 0x7E, 0x80, 0x0A, 0xB4, 0x17, 0x07, 0xE5,
+0x7E, 0xB4, 0x06, 0x02, 0xD2, 0x3E, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x58, 0x44, 0x2D, 0x52, 0x57, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30 };
+
diff --git a/drivers/staging/keucr/ms.c b/drivers/staging/keucr/ms.c
new file mode 100644 (file)
index 0000000..d4340a9
--- /dev/null
@@ -0,0 +1,956 @@
+#include <linux/slab.h>
+#include "usb.h"
+#include "scsiglue.h"
+#include "transport.h"
+#include "ms.h"
+
+//----- MS_ReaderCopyBlock() ------------------------------------------
+int MS_ReaderCopyBlock(struct us_data *us, WORD oldphy, WORD newphy, WORD PhyBlockAddr, BYTE PageNum, PBYTE buf, WORD len)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+
+       //printk("MS_ReaderCopyBlock --- PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum);
+       result = ENE_LoadBinCode(us, MS_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x200*len;
+       bcb->Flags                      = 0x00;
+       bcb->CDB[0]                     = 0xF0;
+       bcb->CDB[1]                     = 0x08;
+       bcb->CDB[4]                     = (BYTE)(oldphy);
+       bcb->CDB[3]                     = (BYTE)(oldphy>>8);
+       bcb->CDB[2]                     = (BYTE)(oldphy>>16);
+       bcb->CDB[7]                     = (BYTE)(newphy);
+       bcb->CDB[6]                     = (BYTE)(newphy>>8);
+       bcb->CDB[5]                     = (BYTE)(newphy>>16);
+       bcb->CDB[9]                     = (BYTE)(PhyBlockAddr);
+       bcb->CDB[8]                     = (BYTE)(PhyBlockAddr>>8);
+       bcb->CDB[10]            = PageNum;
+
+       result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- MS_ReaderReadPage() ------------------------------------------
+int MS_ReaderReadPage(struct us_data *us, DWORD PhyBlockAddr, BYTE PageNum, PDWORD PageBuf, MS_LibTypeExtdat *ExtraDat)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+       BYTE    ExtBuf[4];
+       DWORD   bn = PhyBlockAddr * 0x20 + PageNum;
+
+       //printk("MS --- MS_ReaderReadPage,  PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum);
+
+       result = ENE_LoadBinCode(us, MS_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       // Read Page Data
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x200;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF1;
+       bcb->CDB[1]                     = 0x02;
+       bcb->CDB[5]                     = (BYTE)(bn);
+       bcb->CDB[4]                     = (BYTE)(bn>>8);
+       bcb->CDB[3]                     = (BYTE)(bn>>16);
+       bcb->CDB[2]                     = (BYTE)(bn>>24);
+       
+       result = ENE_SendScsiCmd(us, FDIR_READ, PageBuf, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       // Read Extra Data
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x4;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF1;
+       bcb->CDB[1]                     = 0x03;
+       bcb->CDB[5]                     = (BYTE)(PageNum);
+       bcb->CDB[4]                     = (BYTE)(PhyBlockAddr);
+       bcb->CDB[3]                     = (BYTE)(PhyBlockAddr>>8);
+       bcb->CDB[2]                     = (BYTE)(PhyBlockAddr>>16);
+       bcb->CDB[6]                     = 0x01;
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, &ExtBuf, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       ExtraDat->reserved = 0;
+       ExtraDat->intr     = 0x80;  // Not yet, Â¥Ã½Â°Â²Â³], ÂµÂ¥ fireware support
+       ExtraDat->status0  = 0x10;  // Not yet, Â¥Ã½Â°Â²Â³], ÂµÂ¥ fireware support
+       ExtraDat->status1  = 0x00;  // Not yet, Â¥Ã½Â°Â²Â³], ÂµÂ¥ fireware support
+       ExtraDat->ovrflg   = ExtBuf[0];
+       ExtraDat->mngflg   = ExtBuf[1];
+       ExtraDat->logadr   = MemStickLogAddr(ExtBuf[2], ExtBuf[3]);
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- MS_ReaderEraseBlock() ----------------------------------------
+int MS_ReaderEraseBlock(struct us_data *us, DWORD PhyBlockAddr)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+       DWORD   bn = PhyBlockAddr;
+
+       //printk("MS --- MS_ReaderEraseBlock,  PhyBlockAddr = %x\n", PhyBlockAddr);
+       result = ENE_LoadBinCode(us, MS_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x200;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF2;
+       bcb->CDB[1]                     = 0x06;
+       bcb->CDB[4]                     = (BYTE)(bn);
+       bcb->CDB[3]                     = (BYTE)(bn>>8);
+       bcb->CDB[2]                     = (BYTE)(bn>>16);
+       
+       result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- MS_CardInit() ------------------------------------------------
+int MS_CardInit(struct us_data *us)
+{
+       DWORD                   result=0;
+       WORD                    TmpBlock;
+       PBYTE                   PageBuffer0 = NULL, PageBuffer1 = NULL;
+       MS_LibTypeExtdat        extdat;
+       WORD                    btBlk1st, btBlk2nd;
+       DWORD                   btBlk1stErred;
+
+       printk("MS_CardInit start\n");
+
+       MS_LibFreeAllocatedArea(us);
+
+       if (((PageBuffer0 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL)) == NULL) ||
+           ((PageBuffer1 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL)) == NULL))
+       {
+               result = MS_NO_MEMORY_ERROR;
+               goto exit;
+       }
+
+       btBlk1st = btBlk2nd = MS_LB_NOT_USED;
+       btBlk1stErred = 0;
+
+       for (TmpBlock=0; TmpBlock < MS_MAX_INITIAL_ERROR_BLOCKS+2; TmpBlock++)
+       {
+               switch (MS_ReaderReadPage(us, TmpBlock, 0, (DWORD *)PageBuffer0, &extdat))
+               {
+                       case MS_STATUS_SUCCESS:
+                       break;
+                       case MS_STATUS_INT_ERROR:
+                       break;
+                       case MS_STATUS_ERROR:
+                       default:
+                       continue;
+               }
+
+               if ((extdat.ovrflg & MS_REG_OVR_BKST) == MS_REG_OVR_BKST_NG)
+                       continue;
+
+               if (((extdat.mngflg & MS_REG_MNG_SYSFLG) == MS_REG_MNG_SYSFLG_USER) ||
+                       (BigEndianWORD(((MemStickBootBlockPage0 *)PageBuffer0)->header.wBlockID) != MS_BOOT_BLOCK_ID) ||
+                       (BigEndianWORD(((MemStickBootBlockPage0 *)PageBuffer0)->header.wFormatVersion) != MS_BOOT_BLOCK_FORMAT_VERSION) ||
+                       (((MemStickBootBlockPage0 *)PageBuffer0)->header.bNumberOfDataEntry != MS_BOOT_BLOCK_DATA_ENTRIES))
+                               continue;
+
+               if (btBlk1st != MS_LB_NOT_USED)
+               {
+                       btBlk2nd = TmpBlock;
+                       break;
+               }
+
+               btBlk1st = TmpBlock;
+               memcpy(PageBuffer1, PageBuffer0, MS_BYTES_PER_PAGE);
+               if (extdat.status1 & (MS_REG_ST1_DTER | MS_REG_ST1_EXER | MS_REG_ST1_FGER))
+                       btBlk1stErred = 1;
+       }
+
+       if (btBlk1st == MS_LB_NOT_USED)
+       {
+               result = MS_STATUS_ERROR;
+               goto exit;
+       }
+
+       // write protect
+       if ((extdat.status0 & MS_REG_ST0_WP) == MS_REG_ST0_WP_ON)
+               MS_LibCtrlSet(us, MS_LIB_CTRL_WRPROTECT);
+
+       result = MS_STATUS_ERROR;
+       // 1st Boot Block
+       if (btBlk1stErred == 0)
+               result = MS_LibProcessBootBlock(us, btBlk1st, PageBuffer1);   // 1st
+       // 2nd Boot Block
+       if (result && (btBlk2nd != MS_LB_NOT_USED))
+               result = MS_LibProcessBootBlock(us, btBlk2nd, PageBuffer0);
+
+       if (result)
+       {
+               result = MS_STATUS_ERROR;
+               goto exit;
+       }
+
+       for (TmpBlock = 0; TmpBlock < btBlk1st; TmpBlock++)
+               us->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR;
+
+       us->MS_Lib.Phy2LogMap[btBlk1st] = MS_LB_BOOT_BLOCK;
+
+       if (btBlk2nd != MS_LB_NOT_USED)
+       {
+               for (TmpBlock = btBlk1st + 1; TmpBlock < btBlk2nd; TmpBlock++)
+                       us->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR;
+               us->MS_Lib.Phy2LogMap[btBlk2nd] = MS_LB_BOOT_BLOCK;
+       }
+
+       result = MS_LibScanLogicalBlockNumber(us, btBlk1st);
+       if (result)
+               goto exit;
+
+       for (TmpBlock=MS_PHYSICAL_BLOCKS_PER_SEGMENT; TmpBlock<us->MS_Lib.NumberOfPhyBlock; TmpBlock+=MS_PHYSICAL_BLOCKS_PER_SEGMENT)
+       {
+               if (MS_CountFreeBlock(us, TmpBlock) == 0)
+               {
+                       MS_LibCtrlSet(us, MS_LIB_CTRL_WRPROTECT);
+                       break;
+               }
+       }
+
+       // write
+       if (MS_LibAllocWriteBuf(us))
+       {
+               result = MS_NO_MEMORY_ERROR;
+               goto exit;
+       }
+
+       result = MS_STATUS_SUCCESS;
+
+exit:
+       if (PageBuffer1)                kfree(PageBuffer1);
+       if (PageBuffer0)                kfree(PageBuffer0);
+
+       printk("MS_CardInit end\n");
+       return result;
+}
+
+//----- MS_LibCheckDisableBlock() ------------------------------------
+int MS_LibCheckDisableBlock(struct us_data *us, WORD PhyBlock)
+{
+       PWORD                   PageBuf=NULL;
+       DWORD                   result=MS_STATUS_SUCCESS;
+       DWORD                   blk, index=0;
+       MS_LibTypeExtdat        extdat;
+
+       if (((PageBuf = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL)) == NULL))
+       {
+               result = MS_NO_MEMORY_ERROR;
+               goto exit;
+       }
+
+       MS_ReaderReadPage(us, PhyBlock, 1, (DWORD *)PageBuf, &extdat);
+       do
+       {
+               blk = BigEndianWORD(PageBuf[index]);
+               if (blk == MS_LB_NOT_USED)
+                       break;
+               if (blk == us->MS_Lib.Log2PhyMap[0])
+               {
+                       result = MS_ERROR_FLASH_READ;
+                       break;
+               }
+               index++;
+       } while(1);
+
+exit:
+       if (PageBuf)    kfree(PageBuf);
+       return result;
+}
+
+//----- MS_LibFreeAllocatedArea() ------------------------------------
+void MS_LibFreeAllocatedArea(struct us_data *us)
+{
+       MS_LibFreeWriteBuf(us);
+       MS_LibFreeLogicalMap(us);
+
+       us->MS_Lib.flags                        = 0;
+       us->MS_Lib.BytesPerSector       = 0;
+       us->MS_Lib.SectorsPerCylinder   = 0;
+
+       us->MS_Lib.cardType             = 0;
+       us->MS_Lib.blockSize            = 0;
+       us->MS_Lib.PagesPerBlock        = 0;
+
+       us->MS_Lib.NumberOfPhyBlock     = 0;
+       us->MS_Lib.NumberOfLogBlock     = 0;
+}
+
+//----- MS_LibFreeWriteBuf() -----------------------------------------
+void MS_LibFreeWriteBuf(struct us_data *us)
+{
+       us->MS_Lib.wrtblk = (WORD)-1; //set to -1
+       MS_LibClearPageMap(us); // memset((fdoExt)->MS_Lib.pagemap, 0, sizeof((fdoExt)->MS_Lib.pagemap))
+
+       if (us->MS_Lib.blkpag)
+       {
+               kfree((BYTE *)(us->MS_Lib.blkpag));  // Arnold test ...
+               us->MS_Lib.blkpag = NULL;
+       }
+
+       if (us->MS_Lib.blkext)
+       {
+               kfree((BYTE *)(us->MS_Lib.blkext));  // Arnold test ...
+               us->MS_Lib.blkext = NULL;
+       }
+}
+
+//----- MS_LibFreeLogicalMap() ---------------------------------------
+int MS_LibFreeLogicalMap(struct us_data *us)
+{
+       if (us->MS_Lib.Phy2LogMap)
+       {
+               kfree(us->MS_Lib.Phy2LogMap);
+               us->MS_Lib.Phy2LogMap = NULL;
+       }
+
+       if (us->MS_Lib.Log2PhyMap)
+       {
+               kfree(us->MS_Lib.Log2PhyMap);
+               us->MS_Lib.Log2PhyMap = NULL;
+       }
+
+    return 0;
+}
+
+//----- MS_LibProcessBootBlock() -------------------------------------
+int MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData)
+{
+       MemStickBootBlockSysEnt  *SysEntry;
+       MemStickBootBlockSysInf  *SysInfo;
+       DWORD                    i, result;
+       BYTE                     PageNumber;
+       BYTE                     *PageBuffer;
+       MS_LibTypeExtdat         ExtraData;
+
+       if ((PageBuffer = (BYTE *)kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL))==NULL)
+               return (DWORD)-1;
+
+       result = (DWORD)-1;
+
+       SysInfo= &(((MemStickBootBlockPage0 *)PageData)->sysinf);
+
+       if ((SysInfo->bMsClass != MS_SYSINF_MSCLASS_TYPE_1)                                   ||
+               (BigEndianWORD(SysInfo->wPageSize) != MS_SYSINF_PAGE_SIZE)                       ||
+               ((SysInfo->bSecuritySupport & MS_SYSINF_SECURITY) == MS_SYSINF_SECURITY_SUPPORT) ||
+               (SysInfo->bReserved1 != MS_SYSINF_RESERVED1)                                     ||
+               (SysInfo->bReserved2 != MS_SYSINF_RESERVED2)                                     ||
+               (SysInfo->bFormatType!= MS_SYSINF_FORMAT_FAT)                                    ||
+               (SysInfo->bUsage != MS_SYSINF_USAGE_GENERAL))
+               goto exit;
+
+       switch (us->MS_Lib.cardType = SysInfo->bCardType)
+       {
+               case MS_SYSINF_CARDTYPE_RDONLY:
+                       MS_LibCtrlSet(us, MS_LIB_CTRL_RDONLY);
+                       break;
+               case MS_SYSINF_CARDTYPE_RDWR:
+                       MS_LibCtrlReset(us, MS_LIB_CTRL_RDONLY);
+                       break;
+               case MS_SYSINF_CARDTYPE_HYBRID:
+               default:
+                       goto exit;
+       }
+
+       us->MS_Lib.blockSize        = BigEndianWORD(SysInfo->wBlockSize);
+       us->MS_Lib.NumberOfPhyBlock = BigEndianWORD(SysInfo->wBlockNumber);
+       us->MS_Lib.NumberOfLogBlock = BigEndianWORD(SysInfo->wTotalBlockNumber)- 2;
+       us->MS_Lib.PagesPerBlock    = us->MS_Lib.blockSize * SIZE_OF_KIRO / MS_BYTES_PER_PAGE;
+       us->MS_Lib.NumberOfSegment  = us->MS_Lib.NumberOfPhyBlock / MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+       us->MS_Model                = BigEndianWORD(SysInfo->wMemorySize);
+
+       if (MS_LibAllocLogicalMap(us))                  //Allocate to all number of logicalblock and physicalblock
+               goto exit;
+
+       MS_LibSetBootBlockMark(us, PhyBlock);           //Mark the book block
+
+       SysEntry = &(((MemStickBootBlockPage0 *)PageData)->sysent);
+
+       for (i=0; i<MS_NUMBER_OF_SYSTEM_ENTRY; i++)
+       {
+               DWORD  EntryOffset, EntrySize;
+
+               if ((EntryOffset = BigEndianDWORD(SysEntry->entry[i].dwStart)) == 0xffffff)
+                       continue;
+
+               if ((EntrySize = BigEndianDWORD(SysEntry->entry[i].dwSize)) == 0)
+                       continue;
+
+               if (EntryOffset + MS_BYTES_PER_PAGE + EntrySize > us->MS_Lib.blockSize * (DWORD)SIZE_OF_KIRO)
+                       continue;
+
+               if (i == 0)
+               {
+                       BYTE  PrevPageNumber = 0;
+                       WORD  phyblk;
+
+                       if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_INVALID_BLOCK)
+                               goto exit;
+
+                       while (EntrySize > 0)
+                       {
+                               if ((PageNumber = (BYTE)(EntryOffset / MS_BYTES_PER_PAGE + 1)) != PrevPageNumber)
+                               {
+                                       switch (MS_ReaderReadPage(us, PhyBlock, PageNumber, (DWORD *)PageBuffer, &ExtraData))
+                                       {
+                                               case MS_STATUS_SUCCESS:
+                                                       break;
+                                               case MS_STATUS_WRITE_PROTECT:
+                                               case MS_ERROR_FLASH_READ:
+                                               case MS_STATUS_ERROR:
+                                               default:
+                                                       goto exit;
+                                       }
+
+                                       PrevPageNumber = PageNumber;
+                               }
+
+                               if ((phyblk = BigEndianWORD(*(WORD *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)))) < 0x0fff)
+                                       MS_LibSetInitialErrorBlock(us, phyblk);
+
+                               EntryOffset += 2;
+                               EntrySize -= 2;
+                       }
+               }
+               else if (i == 1)
+               {  // CIS/IDI
+                       MemStickBootBlockIDI  *idi;
+
+                       if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_CIS_IDI)
+                               goto exit;
+
+                       switch (MS_ReaderReadPage(us, PhyBlock, (BYTE)(EntryOffset / MS_BYTES_PER_PAGE + 1), (DWORD *)PageBuffer, &ExtraData))
+                       {
+                               case MS_STATUS_SUCCESS:
+                                       break;
+                               case MS_STATUS_WRITE_PROTECT:
+                               case MS_ERROR_FLASH_READ:
+                               case MS_STATUS_ERROR:
+                               default:
+                                       goto exit;
+                       }
+
+                       idi = &((MemStickBootBlockCIS_IDI *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)))->idi.idi;
+                       if (LittleEndianWORD(idi->wIDIgeneralConfiguration) != MS_IDI_GENERAL_CONF)
+                               goto exit;
+
+                       us->MS_Lib.BytesPerSector = LittleEndianWORD(idi->wIDIbytesPerSector);
+                       if (us->MS_Lib.BytesPerSector != MS_BYTES_PER_PAGE)
+                               goto exit;
+               }
+       } // End for ..
+
+       result = 0;
+
+exit:
+       if (result)             MS_LibFreeLogicalMap(us);
+       if (PageBuffer) kfree(PageBuffer);
+
+       result = 0;
+       return result;
+}
+
+//----- MS_LibAllocLogicalMap() --------------------------------------
+int MS_LibAllocLogicalMap(struct us_data *us)
+{
+       DWORD  i;
+
+
+       us->MS_Lib.Phy2LogMap = (WORD *)kmalloc(us->MS_Lib.NumberOfPhyBlock * sizeof(WORD), GFP_KERNEL);
+       us->MS_Lib.Log2PhyMap = (WORD *)kmalloc(us->MS_Lib.NumberOfLogBlock * sizeof(WORD), GFP_KERNEL);
+
+       if ((us->MS_Lib.Phy2LogMap == NULL) || (us->MS_Lib.Log2PhyMap == NULL))
+       {
+               MS_LibFreeLogicalMap(us);
+               return (DWORD)-1;
+       }
+
+       for (i = 0; i < us->MS_Lib.NumberOfPhyBlock; i++)
+               us->MS_Lib.Phy2LogMap[i] = MS_LB_NOT_USED;
+
+       for (i = 0; i < us->MS_Lib.NumberOfLogBlock; i++)
+       us->MS_Lib.Log2PhyMap[i] = MS_LB_NOT_USED;
+
+       return 0;
+}
+
+//----- MS_LibSetBootBlockMark() -------------------------------------
+int MS_LibSetBootBlockMark(struct us_data *us, WORD phyblk)
+{
+    return MS_LibSetLogicalBlockMark(us, phyblk, MS_LB_BOOT_BLOCK);
+}
+
+//----- MS_LibSetLogicalBlockMark() ----------------------------------
+int MS_LibSetLogicalBlockMark(struct us_data *us, WORD phyblk, WORD mark)
+{
+    if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
+        return (DWORD)-1;
+
+    us->MS_Lib.Phy2LogMap[phyblk] = mark;
+
+    return 0;
+}
+
+//----- MS_LibSetInitialErrorBlock() ---------------------------------
+int MS_LibSetInitialErrorBlock(struct us_data *us, WORD phyblk)
+{
+    return MS_LibSetLogicalBlockMark(us, phyblk, MS_LB_INITIAL_ERROR);
+}
+
+//----- MS_LibScanLogicalBlockNumber() -------------------------------
+int MS_LibScanLogicalBlockNumber(struct us_data *us, WORD btBlk1st)
+{
+       WORD                    PhyBlock, newblk, i;
+       WORD                    LogStart, LogEnde;
+       MS_LibTypeExtdat        extdat;
+       BYTE                    buf[0x200];
+       DWORD                   count=0, index=0;
+
+       for (PhyBlock = 0; PhyBlock < us->MS_Lib.NumberOfPhyBlock;)
+       {
+               MS_LibPhy2LogRange(PhyBlock, &LogStart, &LogEnde);
+
+               for (i=0; i<MS_PHYSICAL_BLOCKS_PER_SEGMENT; i++, PhyBlock++)
+               {
+                       switch (MS_LibConv2Logical(us, PhyBlock))
+                       {
+                               case MS_STATUS_ERROR:
+                                       continue;
+                               default:
+                                       break;
+                       }
+
+                       if (count == PhyBlock)
+                       {
+                               MS_LibReadExtraBlock(us, PhyBlock, 0, 0x80, &buf);
+                               count += 0x80;
+                       }
+                       index = (PhyBlock % 0x80) * 4;
+
+                       extdat.ovrflg = buf[index];
+                       extdat.mngflg = buf[index+1];
+                       extdat.logadr = MemStickLogAddr(buf[index+2], buf[index+3]);
+
+                       if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK)
+                       {
+                               MS_LibSetAcquiredErrorBlock(us, PhyBlock);
+                               continue;
+                       }
+
+                       if ((extdat.mngflg & MS_REG_MNG_ATFLG) == MS_REG_MNG_ATFLG_ATTBL)
+                       {
+                               MS_LibErasePhyBlock(us, PhyBlock);
+                               continue;
+                       }
+
+                       if (extdat.logadr != MS_LB_NOT_USED)
+                       {
+                               if ((extdat.logadr < LogStart) || (LogEnde <= extdat.logadr))
+                               {
+                                       MS_LibErasePhyBlock(us, PhyBlock);
+                                       continue;
+                               }
+
+                               if ((newblk = MS_LibConv2Physical(us, extdat.logadr)) != MS_LB_NOT_USED)
+                               {
+                                       if (extdat.logadr==0)
+                                       {
+                                               MS_LibSetLogicalPair(us, extdat.logadr, PhyBlock);
+                                               if ( MS_LibCheckDisableBlock(us, btBlk1st) )
+                                               {
+                                                       MS_LibSetLogicalPair(us, extdat.logadr, newblk);
+                                                       continue;
+                                               }
+                                       }
+
+                                       MS_LibReadExtra(us, newblk, 0, &extdat);
+                                       if ((extdat.ovrflg & MS_REG_OVR_UDST) == MS_REG_OVR_UDST_UPDATING)
+                                       {
+                                               MS_LibErasePhyBlock(us, PhyBlock);
+                                               continue;
+                                       }
+                                       else
+                                               MS_LibErasePhyBlock(us, newblk);
+                               }
+
+                               MS_LibSetLogicalPair(us, extdat.logadr, PhyBlock);
+                       }
+               }
+       } //End for ...
+
+       return MS_STATUS_SUCCESS;
+}
+
+//----- MS_LibAllocWriteBuf() ----------------------------------------
+int MS_LibAllocWriteBuf(struct us_data *us)
+{
+       us->MS_Lib.wrtblk = (WORD)-1;
+
+       us->MS_Lib.blkpag = (BYTE *)kmalloc(us->MS_Lib.PagesPerBlock * us->MS_Lib.BytesPerSector, GFP_KERNEL);
+       us->MS_Lib.blkext = (MS_LibTypeExtdat *)kmalloc(us->MS_Lib.PagesPerBlock * sizeof(MS_LibTypeExtdat), GFP_KERNEL);
+
+       if ((us->MS_Lib.blkpag == NULL) || (us->MS_Lib.blkext == NULL))
+       {
+               MS_LibFreeWriteBuf(us);
+               return (DWORD)-1;
+       }
+
+       MS_LibClearWriteBuf(us);
+
+       return 0;
+}
+
+//----- MS_LibClearWriteBuf() ----------------------------------------
+void MS_LibClearWriteBuf(struct us_data *us)
+{
+       int i;
+
+       us->MS_Lib.wrtblk = (WORD)-1;
+       MS_LibClearPageMap(us);
+
+       if (us->MS_Lib.blkpag)
+               memset(us->MS_Lib.blkpag, 0xff, us->MS_Lib.PagesPerBlock * us->MS_Lib.BytesPerSector);
+
+       if (us->MS_Lib.blkext)
+       {
+               for (i = 0; i < us->MS_Lib.PagesPerBlock; i++)
+               {
+                       us->MS_Lib.blkext[i].status1 = MS_REG_ST1_DEFAULT;
+                       us->MS_Lib.blkext[i].ovrflg = MS_REG_OVR_DEFAULT;
+                       us->MS_Lib.blkext[i].mngflg = MS_REG_MNG_DEFAULT;
+                       us->MS_Lib.blkext[i].logadr = MS_LB_NOT_USED;
+               }
+       }
+}
+
+//----- MS_LibPhy2LogRange() -----------------------------------------
+void MS_LibPhy2LogRange(WORD PhyBlock, WORD *LogStart, WORD *LogEnde)
+{
+       PhyBlock /= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+
+       if (PhyBlock)
+       {
+               *LogStart = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT + (PhyBlock - 1) * MS_LOGICAL_BLOCKS_PER_SEGMENT;//496
+               *LogEnde = *LogStart + MS_LOGICAL_BLOCKS_PER_SEGMENT;//496
+       }
+       else
+       {
+               *LogStart = 0;
+               *LogEnde = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT;//494
+       }
+}
+
+//----- MS_LibReadExtraBlock() --------------------------------------------
+int MS_LibReadExtraBlock(struct us_data *us, DWORD PhyBlock, BYTE PageNum, BYTE blen, void *buf)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+
+       //printk("MS_LibReadExtraBlock --- PhyBlock = %x, PageNum = %x, blen = %x\n", PhyBlock, PageNum, blen);
+
+       // Read Extra Data
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x4 * blen;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF1;
+       bcb->CDB[1]                     = 0x03;
+       bcb->CDB[5]                     = (BYTE)(PageNum);
+       bcb->CDB[4]                     = (BYTE)(PhyBlock);
+       bcb->CDB[3]                     = (BYTE)(PhyBlock>>8);
+       bcb->CDB[2]                     = (BYTE)(PhyBlock>>16);
+       bcb->CDB[6]                     = blen;
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- MS_LibReadExtra() --------------------------------------------
+int MS_LibReadExtra(struct us_data *us, DWORD PhyBlock, BYTE PageNum, MS_LibTypeExtdat *ExtraDat)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+       BYTE    ExtBuf[4];
+
+       //printk("MS_LibReadExtra --- PhyBlock = %x, PageNum = %x\n", PhyBlock, PageNum);
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x4;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF1;
+       bcb->CDB[1]                     = 0x03;
+       bcb->CDB[5]                     = (BYTE)(PageNum);
+       bcb->CDB[4]                     = (BYTE)(PhyBlock);
+       bcb->CDB[3]                     = (BYTE)(PhyBlock>>8);
+       bcb->CDB[2]                     = (BYTE)(PhyBlock>>16);
+       bcb->CDB[6]                     = 0x01;
+       
+       result = ENE_SendScsiCmd(us, FDIR_READ, &ExtBuf, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       ExtraDat->reserved = 0;
+       ExtraDat->intr     = 0x80;  // Not yet, waiting for fireware support
+       ExtraDat->status0  = 0x10;  // Not yet, waiting for fireware support
+       ExtraDat->status1  = 0x00;  // Not yet, waiting for fireware support
+       ExtraDat->ovrflg   = ExtBuf[0];
+       ExtraDat->mngflg   = ExtBuf[1];
+       ExtraDat->logadr   = MemStickLogAddr(ExtBuf[2], ExtBuf[3]);
+       
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- MS_LibSetAcquiredErrorBlock() --------------------------------
+int MS_LibSetAcquiredErrorBlock(struct us_data *us, WORD phyblk)
+{
+       WORD log;
+
+       if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
+               return (DWORD)-1;
+
+       if ((log = us->MS_Lib.Phy2LogMap[phyblk]) < us->MS_Lib.NumberOfLogBlock)
+               us->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED;
+
+       if (us->MS_Lib.Phy2LogMap[phyblk] != MS_LB_INITIAL_ERROR)
+               us->MS_Lib.Phy2LogMap[phyblk] = MS_LB_ACQUIRED_ERROR;
+
+       return 0;
+}
+
+//----- MS_LibErasePhyBlock() ----------------------------------------
+int MS_LibErasePhyBlock(struct us_data *us, WORD phyblk)
+{
+       WORD  log;
+
+       if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
+               return MS_STATUS_ERROR;
+
+       if ((log = us->MS_Lib.Phy2LogMap[phyblk]) < us->MS_Lib.NumberOfLogBlock)
+               us->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED;
+
+       us->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED;
+
+       if (MS_LibIsWritable(us))
+       {
+               switch (MS_ReaderEraseBlock(us, phyblk))
+               {
+                       case MS_STATUS_SUCCESS:
+                               us->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED_ERASED;
+                               return MS_STATUS_SUCCESS;
+                       case MS_ERROR_FLASH_ERASE:
+                       case MS_STATUS_INT_ERROR :
+                               MS_LibErrorPhyBlock(us, phyblk);
+                               return MS_ERROR_FLASH_ERASE;
+                       case MS_STATUS_ERROR:
+                       default:
+                               MS_LibCtrlSet(us, MS_LIB_CTRL_RDONLY);
+                               MS_LibSetAcquiredErrorBlock(us, phyblk);
+                               return MS_STATUS_ERROR;
+               }
+       }
+
+       MS_LibSetAcquiredErrorBlock(us, phyblk);
+
+       return MS_STATUS_SUCCESS;
+}
+
+//----- MS_LibErrorPhyBlock() ----------------------------------------
+int MS_LibErrorPhyBlock(struct us_data *us, WORD phyblk)
+{
+    if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
+        return MS_STATUS_ERROR;
+
+    MS_LibSetAcquiredErrorBlock(us, phyblk);
+
+    if (MS_LibIsWritable(us))
+        return MS_LibOverwriteExtra(us, phyblk, 0, (BYTE)(~MS_REG_OVR_BKST));
+
+
+    return MS_STATUS_SUCCESS;
+}
+
+//----- MS_LibOverwriteExtra() ---------------------------------------
+int MS_LibOverwriteExtra(struct us_data *us, DWORD PhyBlockAddr, BYTE PageNum, BYTE OverwriteFlag)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+
+       //printk("MS --- MS_LibOverwriteExtra,  PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum);
+       result = ENE_LoadBinCode(us, MS_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x4;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF2;
+       bcb->CDB[1]                     = 0x05;
+       bcb->CDB[5]                     = (BYTE)(PageNum);
+       bcb->CDB[4]                     = (BYTE)(PhyBlockAddr);
+       bcb->CDB[3]                     = (BYTE)(PhyBlockAddr>>8);
+       bcb->CDB[2]                     = (BYTE)(PhyBlockAddr>>16);
+       bcb->CDB[6]                     = OverwriteFlag;
+       bcb->CDB[7]                     = 0xFF;
+       bcb->CDB[8]                     = 0xFF;
+       bcb->CDB[9]                     = 0xFF;
+       
+       result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- MS_LibForceSetLogicalPair() ----------------------------------
+int MS_LibForceSetLogicalPair(struct us_data *us, WORD logblk, WORD phyblk)
+{
+       if (logblk == MS_LB_NOT_USED)
+               return 0;
+
+       if ((logblk >= us->MS_Lib.NumberOfLogBlock) || (phyblk >= us->MS_Lib.NumberOfPhyBlock))
+               return (DWORD)-1;
+
+       us->MS_Lib.Phy2LogMap[phyblk] = logblk;
+       us->MS_Lib.Log2PhyMap[logblk] = phyblk;
+
+       return 0;
+}
+
+//----- MS_LibSetLogicalPair() ---------------------------------------
+int MS_LibSetLogicalPair(struct us_data *us, WORD logblk, WORD phyblk)
+{
+       if ((logblk >= us->MS_Lib.NumberOfLogBlock) || (phyblk >= us->MS_Lib.NumberOfPhyBlock))
+               return (DWORD)-1;
+
+       us->MS_Lib.Phy2LogMap[phyblk] = logblk;
+       us->MS_Lib.Log2PhyMap[logblk] = phyblk;
+
+       return 0;
+}
+
+//----- MS_CountFreeBlock() ------------------------------------------
+int MS_CountFreeBlock(struct us_data *us, WORD PhyBlock)
+{
+       DWORD Ende, Count;
+
+       Ende = PhyBlock + MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+       for (Count = 0; PhyBlock < Ende; PhyBlock++)
+       {
+               switch (us->MS_Lib.Phy2LogMap[PhyBlock])
+               {
+                       case MS_LB_NOT_USED:
+                       case MS_LB_NOT_USED_ERASED:
+                               Count++;
+                       default:
+                               break;
+               }
+       }
+
+       return Count;
+}
+
+//----- MS_LibSearchBlockFromPhysical() ------------------------------
+int MS_LibSearchBlockFromPhysical(struct us_data *us, WORD phyblk)
+{
+       WORD                    Newblk;
+       WORD                    blk;
+       MS_LibTypeExtdat        extdat;
+
+       if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
+               return MS_LB_ERROR;
+
+       for (blk = phyblk + 1; blk != phyblk; blk++)
+       {
+               if ((blk & MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK) == 0)
+                       blk -= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+
+               Newblk = us->MS_Lib.Phy2LogMap[blk];
+               if (us->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED_ERASED)
+                       return blk;
+               else if (us->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED)
+               {
+                       switch (MS_LibReadExtra(us, blk, 0, &extdat))
+                       {
+                               case MS_STATUS_SUCCESS :
+                               case MS_STATUS_SUCCESS_WITH_ECC:
+                                       break;
+                               case MS_NOCARD_ERROR:
+                                       return MS_NOCARD_ERROR;
+                               case MS_STATUS_INT_ERROR:
+                                       return MS_LB_ERROR;
+                               case MS_ERROR_FLASH_READ:
+                               default:
+                                       MS_LibSetAcquiredErrorBlock(us, blk);     // MS_LibErrorPhyBlock(fdoExt, blk);
+                                       continue;
+                       } // End switch
+
+                       if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK)
+                       {
+                               MS_LibSetAcquiredErrorBlock(us, blk);
+                               continue;
+                       }
+
+                       switch (MS_LibErasePhyBlock(us, blk))
+                       {
+                               case MS_STATUS_SUCCESS:
+                                       return blk;
+                               case MS_STATUS_ERROR:
+                                       return MS_LB_ERROR;
+                               case MS_ERROR_FLASH_ERASE:
+                               default:
+                                       MS_LibErrorPhyBlock(us, blk);
+                                       break;
+                       }
+               }
+       } // End for
+
+       return MS_LB_ERROR;
+}
+
+//----- MS_LibSearchBlockFromLogical() -------------------------------
+int MS_LibSearchBlockFromLogical(struct us_data *us, WORD logblk)
+{
+       WORD phyblk;
+
+       if ((phyblk=MS_LibConv2Physical(us, logblk)) >= MS_LB_ERROR)
+       {
+               if (logblk >= us->MS_Lib.NumberOfLogBlock)
+                       return MS_LB_ERROR;
+
+               phyblk = (logblk + MS_NUMBER_OF_BOOT_BLOCK) / MS_LOGICAL_BLOCKS_PER_SEGMENT;
+               phyblk *= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+               phyblk += MS_PHYSICAL_BLOCKS_PER_SEGMENT - 1;
+       }
+
+       return MS_LibSearchBlockFromPhysical(us, phyblk);
+}
+
+
diff --git a/drivers/staging/keucr/ms.h b/drivers/staging/keucr/ms.h
new file mode 100644 (file)
index 0000000..80b168e
--- /dev/null
@@ -0,0 +1,383 @@
+#ifndef MS_INCD
+#define MS_INCD
+
+#include <linux/blkdev.h>
+#include "common.h"
+
+// MemoryStick Register
+// Status Register 0
+#define MS_REG_ST0_MB                           0x80    // media busy
+#define MS_REG_ST0_FB0                          0x40    // flush busy 0
+#define MS_REG_ST0_BE                           0x20    // buffer empty
+#define MS_REG_ST0_BF                           0x10    // buffer full
+#define MS_REG_ST0_SL                           0x02    // sleep
+#define MS_REG_ST0_WP                           0x01    // write protected
+#define MS_REG_ST0_WP_ON                        MS_REG_ST0_WP
+#define MS_REG_ST0_WP_OFF                       0x00
+
+// Status Register 1
+#define MS_REG_ST1_MB                           0x80    // media busy
+#define MS_REG_ST1_FB1                          0x40    // flush busy 1
+#define MS_REG_ST1_DTER                         0x20    // error on data(corrected)
+#define MS_REG_ST1_UCDT                         0x10    // unable to correct data
+#define MS_REG_ST1_EXER                         0x08    // error on extra(corrected)
+#define MS_REG_ST1_UCEX                         0x04    // unable to correct extra
+#define MS_REG_ST1_FGER                         0x02    // error on overwrite flag(corrected)
+#define MS_REG_ST1_UCFG                         0x01    // unable to correct overwrite flag
+#define MS_REG_ST1_DEFAULT                      (MS_REG_ST1_MB   | MS_REG_ST1_FB1  | \
+                                                 MS_REG_ST1_DTER | MS_REG_ST1_UCDT | \
+                                                 MS_REG_ST1_EXER | MS_REG_ST1_UCEX | \
+                                                 MS_REG_ST1_FGER | MS_REG_ST1_UCFG)
+
+// System Parameter
+#define MS_REG_SYSPAR_BAMD                      0x80                // block address mode
+#define MS_REG_SYSPAR_BAND_LINEAR               MS_REG_SYSPAR_BAMD  //   linear mode
+#define MS_REG_SYSPAR_BAND_CHIP                 0x00                //  chip mode
+#define MS_REG_SYSPAR_ATEN                      0x40                // attribute ROM enable
+#define MS_REG_SYSPAR_ATEN_ENABLE               MS_REG_SYSPAR_ATEN  //  enable
+#define MS_REG_SYSPAR_ATEN_DISABLE              0x00                //  disable
+#define MS_REG_SYSPAR_RESERVED                  0x2f
+
+// Command Parameter
+#define MS_REG_CMDPAR_CP2                       0x80
+#define MS_REG_CMDPAR_CP1                       0x40
+#define MS_REG_CMDPAR_CP0                       0x20
+#define MS_REG_CMDPAR_BLOCK_ACCESS              0
+#define MS_REG_CMDPAR_PAGE_ACCESS               MS_REG_CMDPAR_CP0
+#define MS_REG_CMDPAR_EXTRA_DATA                MS_REG_CMDPAR_CP1
+#define MS_REG_CMDPAR_OVERWRITE                 MS_REG_CMDPAR_CP2
+#define MS_REG_CMDPAR_RESERVED                  0x1f
+
+// Overwrite Area
+#define MS_REG_OVR_BKST                         0x80            // block status
+#define MS_REG_OVR_BKST_OK                      MS_REG_OVR_BKST     // OK
+#define MS_REG_OVR_BKST_NG                      0x00            // NG
+#define MS_REG_OVR_PGST0                        0x40            // page status
+#define MS_REG_OVR_PGST1                        0x20
+#define MS_REG_OVR_PGST_MASK                    (MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1)
+#define MS_REG_OVR_PGST_OK                      (MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1) // OK
+#define MS_REG_OVR_PGST_NG                      MS_REG_OVR_PGST1                      // NG
+#define MS_REG_OVR_PGST_DATA_ERROR              0x00        // data error
+#define MS_REG_OVR_UDST                         0x10        // update status
+#define MS_REG_OVR_UDST_UPDATING                0x00        // updating
+#define MS_REG_OVR_UDST_NO_UPDATE               MS_REG_OVR_UDST
+#define MS_REG_OVR_RESERVED                     0x08
+#define MS_REG_OVR_DEFAULT                      (MS_REG_OVR_BKST_OK |      \
+                                                 MS_REG_OVR_PGST_OK |      \
+                                                 MS_REG_OVR_UDST_NO_UPDATE |   \
+                                                 MS_REG_OVR_RESERVED)
+// Management Flag
+#define MS_REG_MNG_SCMS0                        0x20    // serial copy management system
+#define MS_REG_MNG_SCMS1                        0x10
+#define MS_REG_MNG_SCMS_MASK                    (MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1)
+#define MS_REG_MNG_SCMS_COPY_OK                 (MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1)
+#define MS_REG_MNG_SCMS_ONE_COPY                MS_REG_MNG_SCMS1
+#define MS_REG_MNG_SCMS_NO_COPY                 0x00
+#define MS_REG_MNG_ATFLG                        0x08    // address transfer table flag
+#define MS_REG_MNG_ATFLG_OTHER                  MS_REG_MNG_ATFLG    // other
+#define MS_REG_MNG_ATFLG_ATTBL                  0x00    // address transfer table
+#define MS_REG_MNG_SYSFLG                       0x04    // system flag
+#define MS_REG_MNG_SYSFLG_USER                  MS_REG_MNG_SYSFLG   // user block
+#define MS_REG_MNG_SYSFLG_BOOT                  0x00            // system block
+#define MS_REG_MNG_RESERVED                     0xc3
+#define MS_REG_MNG_DEFAULT                      (MS_REG_MNG_SCMS_COPY_OK |     \
+                                                MS_REG_MNG_ATFLG_OTHER |  \
+                                                MS_REG_MNG_SYSFLG_USER |  \
+                                                MS_REG_MNG_RESERVED)
+
+// Error codes
+#define MS_STATUS_SUCCESS                       0x0000
+#define MS_ERROR_OUT_OF_SPACE                   0x0103
+#define MS_STATUS_WRITE_PROTECT                 0x0106
+#define MS_ERROR_READ_DATA                      0x8002
+#define MS_ERROR_FLASH_READ                     0x8003
+#define MS_ERROR_FLASH_WRITE                    0x8004
+#define MS_ERROR_FLASH_ERASE                    0x8005
+#define MS_ERROR_FLASH_COPY                     0x8006
+
+#define MS_STATUS_ERROR                         0xfffe
+#define MS_FIFO_ERROR                           0xfffd
+#define MS_UNDEFINED_ERROR                      0xfffc
+#define MS_KETIMEOUT_ERROR                      0xfffb
+#define MS_STATUS_INT_ERROR                     0xfffa
+#define MS_NO_MEMORY_ERROR                      0xfff9
+#define MS_NOCARD_ERROR                         0xfff8
+#define MS_LB_NOT_USED                          0xffff
+#define MS_LB_ERROR                             0xfff0
+#define MS_LB_BOOT_BLOCK                        0xfff1
+#define MS_LB_INITIAL_ERROR                     0xfff2
+#define MS_STATUS_SUCCESS_WITH_ECC              0xfff3
+#define MS_LB_ACQUIRED_ERROR                    0xfff4
+#define MS_LB_NOT_USED_ERASED                   0xfff5
+
+#define MS_LibConv2Physical(pdx, LogBlock)      (((LogBlock) >= (pdx)->MS_Lib.NumberOfLogBlock) ? MS_STATUS_ERROR : (pdx)->MS_Lib.Log2PhyMap[LogBlock])
+#define MS_LibConv2Logical(pdx, PhyBlock)       (((PhyBlock) >= (pdx)->MS_Lib.NumberOfPhyBlock) ? MS_STATUS_ERROR : (pdx)->MS_Lib.Phy2LogMap[PhyBlock]) //¬dphy->log table
+
+#define MS_LIB_CTRL_RDONLY                      0
+#define MS_LIB_CTRL_WRPROTECT                   1
+#define MS_LibCtrlCheck(pdx, Flag)              ((pdx)->MS_Lib.flags & (1 << (Flag)))
+
+#define MS_LibCtrlSet(pdx, Flag)                (pdx)->MS_Lib.flags |= (1 << (Flag))
+#define MS_LibCtrlReset(pdx, Flag)              (pdx)->MS_Lib.flags &= ~(1 << (Flag))
+#define MS_LibIsWritable(pdx)                   ((MS_LibCtrlCheck((pdx), MS_LIB_CTRL_RDONLY) == 0) && (MS_LibCtrlCheck(pdx, MS_LIB_CTRL_WRPROTECT) == 0))
+
+#define MS_MAX_PAGES_PER_BLOCK                  32
+#define MS_LIB_BITS_PER_BYTE                    8
+
+#define MS_LibPageMapIdx(n)                     ((n) / MS_LIB_BITS_PER_BYTE)
+#define MS_LibPageMapBit(n)                     (1 << ((n) % MS_LIB_BITS_PER_BYTE))
+#define MS_LibCheckPageMapBit(pdx, n)           ((pdx)->MS_Lib.pagemap[MS_LibPageMapIdx(n)] & MS_LibPageMapBit(n))
+#define MS_LibSetPageMapBit(pdx, n)             ((pdx)->MS_Lib.pagemap[MS_LibPageMapIdx(n)] |= MS_LibPageMapBit(n))
+#define MS_LibResetPageMapBit(pdx, n)           ((pdx)->MS_Lib.pagemap[MS_LibPageMapIdx(n)] &= ~MS_LibPageMapBit(n))
+#define MS_LibClearPageMap(pdx)                 memset((pdx)->MS_Lib.pagemap, 0, sizeof((pdx)->MS_Lib.pagemap))
+
+
+#define MemStickLogAddr(logadr1, logadr0)       ((((WORD)(logadr1)) << 8) | (logadr0))
+
+#define MS_BYTES_PER_PAGE                       512
+
+#define MS_MAX_INITIAL_ERROR_BLOCKS             10
+#define MS_NUMBER_OF_PAGES_FOR_BOOT_BLOCK       3
+#define MS_NUMBER_OF_PAGES_FOR_LPCTBL           2
+
+#define MS_NUMBER_OF_BOOT_BLOCK                 2
+#define MS_NUMBER_OF_SYSTEM_BLOCK               4
+#define MS_LOGICAL_BLOCKS_PER_SEGMENT           496
+#define MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT        494
+#define MS_PHYSICAL_BLOCKS_PER_SEGMENT          0x200   // 512
+#define MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK     0x1ff
+
+#define MS_SECTOR_SIZE                          512
+#define MBR_SIGNATURE                           0xAA55
+#define PBR_SIGNATURE                           0xAA55
+
+#define PARTITION_FAT_12                        1
+#define PARTITION_FAT_16                        2
+
+#define MS_BOOT_BLOCK_ID                        0x0001
+#define MS_BOOT_BLOCK_FORMAT_VERSION            0x0100
+#define MS_BOOT_BLOCK_DATA_ENTRIES              2
+
+#define MS_SYSINF_MSCLASS_TYPE_1                1
+#define MS_SYSINF_CARDTYPE_RDONLY               1
+#define MS_SYSINF_CARDTYPE_RDWR                 2
+#define MS_SYSINF_CARDTYPE_HYBRID               3
+#define MS_SYSINF_SECURITY                      0x01
+#define MS_SYSINF_SECURITY_NO_SUPPORT           MS_SYSINF_SECURITY
+#define MS_SYSINF_SECURITY_SUPPORT              0
+#define MS_SYSINF_FORMAT_MAT                    0   // ?
+#define MS_SYSINF_FORMAT_FAT                    1
+#define MS_SYSINF_USAGE_GENERAL                 0
+#define MS_SYSINF_PAGE_SIZE                     MS_BYTES_PER_PAGE // fixed
+#define MS_SYSINF_RESERVED1                     1
+#define MS_SYSINF_RESERVED2                     1
+
+#define MS_SYSENT_TYPE_INVALID_BLOCK            0x01
+#define MS_SYSENT_TYPE_CIS_IDI                  0x0a    // CIS/IDI
+
+#define SIZE_OF_KIRO                            1024
+
+// BOOT BLOCK
+#define MS_NUMBER_OF_SYSTEM_ENTRY               4
+
+//----- MemStickRegisters --------------------------------------------
+// Status registers (16 bytes)
+typedef struct {
+    BYTE   Reserved0;          // 00
+    BYTE   INTRegister;        // 01
+    BYTE   StatusRegister0;    // 02
+    BYTE   StatusRegister1;    // 03
+    BYTE   Reserved1[12];      // 04-0F
+} MemStickStatusRegisters;
+
+// Parameter registers (6 bytes)
+typedef struct {
+    BYTE   SystemParameter;    // 10
+    BYTE   BlockAddress2;      // 11
+    BYTE   BlockAddress1;      // 12
+    BYTE   BlockAddress0;      // 13
+    BYTE   CMDParameter;       // 14
+    BYTE   PageAddress;        // 15
+} MemStickParameterRegisters;
+
+// Extra registers (9 bytes)
+typedef struct {
+    BYTE   OverwriteFlag;      // 16
+    BYTE   ManagementFlag;     // 17
+    BYTE   LogicalAddress1;    // 18
+    BYTE   LogicalAddress0;    // 19
+    BYTE   ReservedArea[5];    // 1A-1E
+} MemStickExtraDataRegisters;
+
+// All registers in Memory Stick (32 bytes, includes 1 byte padding)
+typedef struct {
+    MemStickStatusRegisters     status;
+    MemStickParameterRegisters  param;
+    MemStickExtraDataRegisters  extra;
+    BYTE                        padding;
+} MemStickRegisters, *PMemStickRegisters;
+
+//----- MemStickBootBlockPage0 ---------------------------------------
+typedef struct {
+    WORD   wBlockID;
+    WORD   wFormatVersion;
+    BYTE   bReserved1[184];
+    BYTE   bNumberOfDataEntry;
+    BYTE   bReserved2[179];
+} MemStickBootBlockHeader;
+
+typedef struct {
+    DWORD   dwStart;
+    DWORD   dwSize;
+    BYTE    bType;
+    BYTE    bReserved[3];
+} MemStickBootBlockSysEntRec;
+
+typedef struct {
+    MemStickBootBlockSysEntRec  entry[MS_NUMBER_OF_SYSTEM_ENTRY];
+} MemStickBootBlockSysEnt;
+
+typedef struct {
+    BYTE   bMsClass;       // must be 1
+    BYTE   bCardType;      // see below
+    WORD   wBlockSize;     // n KB
+    WORD   wBlockNumber;       // number of physical block
+    WORD   wTotalBlockNumber;  // number of logical block
+    WORD   wPageSize;      // must be 0x200
+    BYTE   bExtraSize;     // 0x10
+    BYTE   bSecuritySupport;
+    BYTE   bAssemblyDate[8];
+    BYTE   bFactoryArea[4];
+    BYTE   bAssemblyMakerCode;
+    BYTE   bAssemblyMachineCode[3];
+    WORD   wMemoryMakerCode;
+    WORD   wMemoryDeviceCode;
+    WORD   wMemorySize;
+    BYTE   bReserved1;
+    BYTE   bReserved2;
+    BYTE   bVCC;
+    BYTE   bVPP;
+    WORD   wControllerChipNumber;
+    WORD   wControllerFunction;  // New MS
+    BYTE   bReserved3[9];        // New MS
+    BYTE   bParallelSupport;     // New MS
+    WORD   wFormatValue;         // New MS
+    BYTE   bFormatType;
+    BYTE   bUsage;
+    BYTE   bDeviceType;
+    BYTE   bReserved4[22];
+    BYTE   bFUValue3;
+    BYTE   bFUValue4;
+    BYTE   bReserved5[15];
+} MemStickBootBlockSysInf;
+
+typedef struct {
+    MemStickBootBlockHeader header;
+    MemStickBootBlockSysEnt sysent;
+    MemStickBootBlockSysInf sysinf;
+} MemStickBootBlockPage0;
+
+//----- MemStickBootBlockCIS_IDI -------------------------------------
+typedef struct {
+    BYTE   bCistplDEVICE[6];            // 0
+    BYTE   bCistplDEVICE0C[6];          // 6
+    BYTE   bCistplJEDECC[4];            // 12
+    BYTE   bCistplMANFID[6];            // 16
+    BYTE   bCistplVER1[32];             // 22
+    BYTE   bCistplFUNCID[4];            // 54
+    BYTE   bCistplFUNCE0[4];            // 58
+    BYTE   bCistplFUNCE1[5];            // 62
+    BYTE   bCistplCONF[7];              // 67
+    BYTE   bCistplCFTBLENT0[10];        // 74
+    BYTE   bCistplCFTBLENT1[8];         // 84
+    BYTE   bCistplCFTBLENT2[12];        // 92
+    BYTE   bCistplCFTBLENT3[8];         // 104
+    BYTE   bCistplCFTBLENT4[17];        // 112
+    BYTE   bCistplCFTBLENT5[8];         // 129
+    BYTE   bCistplCFTBLENT6[17];        // 137
+    BYTE   bCistplCFTBLENT7[8];         // 154
+    BYTE   bCistplNOLINK[3];            // 162
+} MemStickBootBlockCIS;
+
+typedef struct {
+    #define MS_IDI_GENERAL_CONF         0x848A
+    WORD  wIDIgeneralConfiguration;     // 0
+    WORD  wIDInumberOfCylinder;         // 1
+    WORD  wIDIreserved0;                // 2
+    WORD  wIDInumberOfHead;             // 3
+    WORD  wIDIbytesPerTrack;            // 4
+    WORD  wIDIbytesPerSector;           // 5
+    WORD  wIDIsectorsPerTrack;          // 6
+    WORD  wIDItotalSectors[2];          // 7-8  high,low
+    WORD  wIDIreserved1[11];            // 9-19
+    WORD  wIDIbufferType;               // 20
+    WORD  wIDIbufferSize;               // 21
+    WORD  wIDIlongCmdECC;               // 22
+    WORD  wIDIfirmVersion[4];           // 23-26
+    WORD  wIDImodelName[20];            // 27-46
+    WORD  wIDIreserved2;                // 47
+    WORD  wIDIlongWordSupported;        // 48
+    WORD  wIDIdmaSupported;             // 49
+    WORD  wIDIreserved3;                // 50
+    WORD  wIDIpioTiming;                // 51
+    WORD  wIDIdmaTiming;                // 52
+    WORD  wIDItransferParameter;        // 53
+    WORD  wIDIformattedCylinder;        // 54
+    WORD  wIDIformattedHead;            // 55
+    WORD  wIDIformattedSectorsPerTrack; // 56
+    WORD  wIDIformattedTotalSectors[2]; // 57-58
+    WORD  wIDImultiSector;              // 59
+    WORD  wIDIlbaSectors[2];            // 60-61
+    WORD  wIDIsingleWordDMA;            // 62
+    WORD  wIDImultiWordDMA;             // 63
+    WORD  wIDIreserved4[192];           // 64-255
+} MemStickBootBlockIDI;
+
+typedef struct {
+
+    union
+    {
+        MemStickBootBlockCIS    cis;
+        BYTE                    dmy[256];
+    } cis;
+
+    union
+    {
+        MemStickBootBlockIDI    idi;
+        BYTE                    dmy[256];
+    } idi;
+
+} MemStickBootBlockCIS_IDI;
+
+//----- MS_LibControl ------------------------------------------------
+typedef struct {
+    BYTE  reserved;
+    BYTE  intr;
+    BYTE  status0;
+    BYTE  status1;
+    BYTE  ovrflg;
+    BYTE  mngflg;
+    WORD  logadr;
+} MS_LibTypeExtdat;
+
+typedef struct {
+    DWORD               flags;
+    DWORD               BytesPerSector;
+    DWORD               NumberOfCylinder;
+    DWORD               SectorsPerCylinder;
+    WORD                cardType;               // R/W, RO, Hybrid
+    WORD                blockSize;
+    WORD                PagesPerBlock;
+    WORD                NumberOfPhyBlock;
+    WORD                NumberOfLogBlock;
+    WORD                NumberOfSegment;
+    WORD                *Phy2LogMap;            //phy2log table
+    WORD                *Log2PhyMap;            //log2phy table
+    WORD                wrtblk;
+    BYTE                pagemap[(MS_MAX_PAGES_PER_BLOCK+(MS_LIB_BITS_PER_BYTE-1))/MS_LIB_BITS_PER_BYTE];
+    BYTE                *blkpag;
+    MS_LibTypeExtdat    *blkext;
+    BYTE               copybuf[512];
+} MS_LibControl;
+
+#endif
diff --git a/drivers/staging/keucr/msscsi.c b/drivers/staging/keucr/msscsi.c
new file mode 100644 (file)
index 0000000..b908a23
--- /dev/null
@@ -0,0 +1,320 @@
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+
+#include "usb.h"
+#include "scsiglue.h"
+#include "transport.h"
+
+int MS_SCSI_Test_Unit_Ready (struct us_data *us, struct scsi_cmnd *srb);
+int MS_SCSI_Inquiry         (struct us_data *us, struct scsi_cmnd *srb);
+int MS_SCSI_Mode_Sense      (struct us_data *us, struct scsi_cmnd *srb);
+int MS_SCSI_Start_Stop      (struct us_data *us, struct scsi_cmnd *srb);
+int MS_SCSI_Read_Capacity   (struct us_data *us, struct scsi_cmnd *srb);
+int MS_SCSI_Read            (struct us_data *us, struct scsi_cmnd *srb);
+int MS_SCSI_Write           (struct us_data *us, struct scsi_cmnd *srb);
+
+//----- MS_SCSIIrp() --------------------------------------------------
+int MS_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb)
+{
+       int    result;
+
+       us->SrbStatus = SS_SUCCESS;
+       switch (srb->cmnd[0])
+       {
+               case TEST_UNIT_READY :  result = MS_SCSI_Test_Unit_Ready (us, srb);  break; //0x00
+               case INQUIRY         :  result = MS_SCSI_Inquiry         (us, srb);  break; //0x12
+               case MODE_SENSE      :  result = MS_SCSI_Mode_Sense      (us, srb);  break; //0x1A
+               case READ_CAPACITY   :  result = MS_SCSI_Read_Capacity   (us, srb);  break; //0x25
+               case READ_10         :  result = MS_SCSI_Read            (us, srb);  break; //0x28
+               case WRITE_10        :  result = MS_SCSI_Write           (us, srb);  break; //0x2A
+
+               default:
+                       us->SrbStatus = SS_ILLEGAL_REQUEST;
+                       result = USB_STOR_TRANSPORT_FAILED;
+                       break;
+       }
+       return result;
+}
+
+//----- MS_SCSI_Test_Unit_Ready() --------------------------------------------------
+int MS_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb)
+{
+       //printk("MS_SCSI_Test_Unit_Ready\n");
+       if (us->MS_Status.Insert && us->MS_Status.Ready)
+               return USB_STOR_TRANSPORT_GOOD;
+       else
+       {
+               ENE_MSInit(us);
+               return USB_STOR_TRANSPORT_GOOD;
+       }
+               
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- MS_SCSI_Inquiry() --------------------------------------------------
+int MS_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb)
+{
+       //printk("MS_SCSI_Inquiry\n");
+       BYTE data_ptr[36] = {0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
+
+       usb_stor_set_xfer_buf(us, data_ptr, 36, srb, TO_XFER_BUF);
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+
+//----- MS_SCSI_Mode_Sense() --------------------------------------------------
+int MS_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb)
+{
+       BYTE    mediaNoWP[12] = {0x0b,0x00,0x00,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
+       BYTE    mediaWP[12]   = {0x0b,0x00,0x80,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
+
+       if (us->MS_Status.WtP)
+               usb_stor_set_xfer_buf(us, mediaWP, 12, srb, TO_XFER_BUF);
+       else
+               usb_stor_set_xfer_buf(us, mediaNoWP, 12, srb, TO_XFER_BUF);
+
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- MS_SCSI_Read_Capacity() --------------------------------------------------
+int MS_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb)
+{
+       unsigned int offset = 0;
+       struct scatterlist *sg = NULL;
+       DWORD   bl_num;
+       WORD    bl_len;
+       BYTE    buf[8];
+
+       printk("MS_SCSI_Read_Capacity\n");
+
+       bl_len = 0x200;
+       if ( us->MS_Status.IsMSPro )
+               bl_num = us->MSP_TotalBlock - 1;
+       else
+               bl_num = us->MS_Lib.NumberOfLogBlock * us->MS_Lib.blockSize * 2 - 1;
+
+       us->bl_num = bl_num;
+       printk("bl_len = %x\n", bl_len);
+       printk("bl_num = %x\n", bl_num);
+
+       //srb->request_bufflen = 8;
+       buf[0] = (bl_num>>24) & 0xff;
+       buf[1] = (bl_num>>16) & 0xff;
+       buf[2] = (bl_num>> 8) & 0xff;
+       buf[3] = (bl_num>> 0) & 0xff;
+       buf[4] = (bl_len>>24) & 0xff;
+       buf[5] = (bl_len>>16) & 0xff;
+       buf[6] = (bl_len>> 8) & 0xff;
+       buf[7] = (bl_len>> 0) & 0xff;
+       
+       usb_stor_access_xfer_buf(us, buf, 8, srb, &sg, &offset, TO_XFER_BUF);
+       //usb_stor_set_xfer_buf(us, buf, srb->request_bufflen, srb, TO_XFER_BUF);
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- MS_SCSI_Read() --------------------------------------------------
+int MS_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int result=0;
+       PBYTE   Cdb = srb->cmnd;
+       DWORD bn  =  ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
+                   ((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
+       WORD  blen = ((Cdb[7]<< 8) & 0xff00)     | ((Cdb[8]<< 0) & 0x00ff);
+       DWORD   blenByte = blen * 0x200;
+
+       //printk("SCSIOP_READ --- bn = %X, blen = %X, srb->use_sg = %X\n", bn, blen, srb->use_sg);
+       
+       if (bn > us->bl_num)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       if (us->MS_Status.IsMSPro)
+       {
+               result = ENE_LoadBinCode(us, MSP_RW_PATTERN);
+               if (result != USB_STOR_XFER_GOOD)
+               {
+                       printk("Load MSP RW pattern Fail !!\n");
+                       return USB_STOR_TRANSPORT_ERROR;
+               }
+
+               // set up the command wrapper
+               memset(bcb, 0, sizeof(bcb));
+               bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+               bcb->DataTransferLength = blenByte;
+               bcb->Flags  = 0x80;
+               bcb->CDB[0] = 0xF1;
+               bcb->CDB[1] = 0x02;
+               bcb->CDB[5] = (BYTE)(bn);
+               bcb->CDB[4] = (BYTE)(bn>>8);
+               bcb->CDB[3] = (BYTE)(bn>>16);
+               bcb->CDB[2] = (BYTE)(bn>>24);
+
+               result = ENE_SendScsiCmd(us, FDIR_READ, scsi_sglist(srb), 1);
+       }
+       else
+       {
+               void    *buf;
+               int     offset=0;
+               WORD    phyblk, logblk;
+               BYTE    PageNum;
+               WORD    len;
+               DWORD   blkno;
+
+               buf = kmalloc(blenByte, GFP_KERNEL);
+
+               result = ENE_LoadBinCode(us, MS_RW_PATTERN);
+               if (result != USB_STOR_XFER_GOOD)
+               {
+                       printk("Load MS RW pattern Fail !!\n");
+                       result = USB_STOR_TRANSPORT_ERROR;
+                       goto exit;
+               }
+
+               logblk  = (WORD)(bn / us->MS_Lib.PagesPerBlock);
+               PageNum = (BYTE)(bn % us->MS_Lib.PagesPerBlock);
+
+               while(1)
+               {
+                       if (blen > (us->MS_Lib.PagesPerBlock-PageNum) )
+                               len = us->MS_Lib.PagesPerBlock-PageNum;
+                       else
+                               len = blen;
+
+                       phyblk = MS_LibConv2Physical(us, logblk);
+                       blkno  = phyblk * 0x20 + PageNum;
+
+                       // set up the command wrapper
+                       memset(bcb, 0, sizeof(bcb));
+                       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+                       bcb->DataTransferLength = 0x200 * len;
+                       bcb->Flags  = 0x80;
+                       bcb->CDB[0] = 0xF1;
+                       bcb->CDB[1] = 0x02;
+                       bcb->CDB[5] = (BYTE)(blkno);
+                       bcb->CDB[4] = (BYTE)(blkno>>8);
+                       bcb->CDB[3] = (BYTE)(blkno>>16);
+                       bcb->CDB[2] = (BYTE)(blkno>>24);
+
+                       result = ENE_SendScsiCmd(us, FDIR_READ, buf+offset, 0);
+                       if (result != USB_STOR_XFER_GOOD)
+                       {
+                               printk("MS_SCSI_Read --- result = %x\n", result);
+                               result =  USB_STOR_TRANSPORT_ERROR;
+                               goto exit;
+                       }
+
+                       blen -= len;
+                       if (blen<=0)
+                               break;
+                       logblk++;
+                       PageNum = 0;
+                       offset += MS_BYTES_PER_PAGE*len;
+               }
+               usb_stor_set_xfer_buf(us, buf, blenByte, srb, TO_XFER_BUF);
+exit:
+               kfree(buf);
+       }
+       return result;
+}
+
+//----- MS_SCSI_Write() --------------------------------------------------
+int MS_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int result=0;
+       PBYTE   Cdb = srb->cmnd;
+       DWORD bn  =  ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
+                   ((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
+       WORD  blen = ((Cdb[7]<< 8) & 0xff00)     | ((Cdb[8]<< 0) & 0x00ff);
+       DWORD   blenByte = blen * 0x200;
+
+       if (bn > us->bl_num)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       if (us->MS_Status.IsMSPro)
+       {
+               result = ENE_LoadBinCode(us, MSP_RW_PATTERN);
+               if (result != USB_STOR_XFER_GOOD)
+               {
+                       printk("Load MSP RW pattern Fail !!\n");
+                       return USB_STOR_TRANSPORT_ERROR;
+               }
+
+               // set up the command wrapper
+               memset(bcb, 0, sizeof(bcb));
+               bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+               bcb->DataTransferLength = blenByte;
+               bcb->Flags  = 0x00;
+               bcb->CDB[0] = 0xF0;
+               bcb->CDB[1] = 0x04;
+               bcb->CDB[5] = (BYTE)(bn);
+               bcb->CDB[4] = (BYTE)(bn>>8);
+               bcb->CDB[3] = (BYTE)(bn>>16);
+               bcb->CDB[2] = (BYTE)(bn>>24);
+
+               result = ENE_SendScsiCmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
+       }
+       else
+       {
+               void    *buf;
+               int     offset=0;
+               WORD    PhyBlockAddr;
+               BYTE    PageNum;
+               DWORD   result;
+               WORD    len, oldphy, newphy;
+
+               buf = kmalloc(blenByte, GFP_KERNEL);
+               usb_stor_set_xfer_buf(us, buf, blenByte, srb, FROM_XFER_BUF);
+
+               result = ENE_LoadBinCode(us, MS_RW_PATTERN);
+               if (result != USB_STOR_XFER_GOOD)
+               {
+                       printk("Load MS RW pattern Fail !!\n");
+                       result = USB_STOR_TRANSPORT_ERROR;
+                       goto exit;
+               }
+
+               PhyBlockAddr = (WORD)(bn / us->MS_Lib.PagesPerBlock);
+               PageNum      = (BYTE)(bn % us->MS_Lib.PagesPerBlock);
+
+               while(1)
+               {
+                       if (blen > (us->MS_Lib.PagesPerBlock-PageNum) )
+                               len = us->MS_Lib.PagesPerBlock-PageNum;
+                       else
+                               len = blen;
+
+                       oldphy = MS_LibConv2Physical(us, PhyBlockAddr);
+                       newphy = MS_LibSearchBlockFromLogical(us, PhyBlockAddr);
+
+                       result = MS_ReaderCopyBlock(us, oldphy, newphy, PhyBlockAddr, PageNum, buf+offset, len);
+                       if (result != USB_STOR_XFER_GOOD)
+                       {
+                               printk("MS_SCSI_Write --- result = %x\n", result);
+                               result =  USB_STOR_TRANSPORT_ERROR;
+                               goto exit;
+                       }
+
+                       us->MS_Lib.Phy2LogMap[oldphy] = MS_LB_NOT_USED_ERASED;
+                       MS_LibForceSetLogicalPair(us, PhyBlockAddr, newphy);
+
+                       blen -= len;
+                       if (blen<=0)
+                               break;
+                       PhyBlockAddr++;
+                       PageNum = 0;
+                       offset += MS_BYTES_PER_PAGE*len;
+               }
+exit:
+               kfree(buf);
+       }
+       return result;
+}
+
diff --git a/drivers/staging/keucr/scsiglue.c b/drivers/staging/keucr/scsiglue.c
new file mode 100644 (file)
index 0000000..d830348
--- /dev/null
@@ -0,0 +1,448 @@
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_devinfo.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+
+#include "usb.h"
+#include "scsiglue.h"
+#include "transport.h"
+
+/* Host functions */
+//----- host_info() ---------------------
+static const char* host_info(struct Scsi_Host *host)
+{
+       //printk("scsiglue --- host_info\n");
+       return "SCSI emulation for USB Mass Storage devices";
+}
+
+//----- slave_alloc() ---------------------
+static int slave_alloc(struct scsi_device *sdev)
+{
+       struct us_data *us = host_to_us(sdev->host);
+
+       //printk("scsiglue --- slave_alloc\n");
+       sdev->inquiry_len = 36;
+
+       blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
+
+       if (us->subclass == US_SC_UFI)
+               sdev->sdev_target->pdt_1f_for_no_lun = 1;
+
+       return 0;
+}
+
+//----- slave_configure() ---------------------
+static int slave_configure(struct scsi_device *sdev)
+{
+       struct us_data *us = host_to_us(sdev->host);
+
+       //printk("scsiglue --- slave_configure\n");
+       if (us->fflags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN))
+       {
+               unsigned int max_sectors = 64;
+
+               if (us->fflags & US_FL_MAX_SECTORS_MIN)
+                       max_sectors = PAGE_CACHE_SIZE >> 9;
+               if (queue_max_sectors(sdev->request_queue) > max_sectors)
+                       blk_queue_max_hw_sectors(sdev->request_queue,
+                                             max_sectors);
+       }
+
+       if (sdev->type == TYPE_DISK)
+       {
+               if (us->subclass != US_SC_SCSI && us->subclass != US_SC_CYP_ATACB)
+                       sdev->use_10_for_ms = 1;
+               sdev->use_192_bytes_for_3f = 1;
+               if (us->fflags & US_FL_NO_WP_DETECT)
+                       sdev->skip_ms_page_3f = 1;
+               sdev->skip_ms_page_8 = 1;
+               if (us->fflags & US_FL_FIX_CAPACITY)
+                       sdev->fix_capacity = 1;
+               if (us->fflags & US_FL_CAPACITY_HEURISTICS)
+                       sdev->guess_capacity = 1;
+               if (sdev->scsi_level > SCSI_2)
+                       sdev->sdev_target->scsi_level = sdev->scsi_level = SCSI_2;
+               sdev->retry_hwerror = 1;
+               sdev->allow_restart = 1;
+               sdev->last_sector_bug = 1;
+       }
+       else
+       {
+               sdev->use_10_for_ms = 1;
+       }
+
+       if ((us->protocol == US_PR_CB || us->protocol == US_PR_CBI) && sdev->scsi_level == SCSI_UNKNOWN)
+               us->max_lun = 0;
+
+       if (us->fflags & US_FL_NOT_LOCKABLE)
+               sdev->lockable = 0;
+
+       return 0;
+}
+
+/* This is always called with scsi_lock(host) held */
+//----- queuecommand() ---------------------
+static int queuecommand(struct scsi_cmnd *srb, void (*done)(struct scsi_cmnd *))
+{
+       struct us_data *us = host_to_us(srb->device->host);
+
+       //printk("scsiglue --- queuecommand\n");
+
+       /* check for state-transition errors */
+       if (us->srb != NULL)
+       {
+               printk("Error in %s: us->srb = %p\n", __FUNCTION__, us->srb);
+               return SCSI_MLQUEUE_HOST_BUSY;
+       }
+
+       /* fail the command if we are disconnecting */
+       if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags))
+       {
+               printk("Fail command during disconnect\n");
+               srb->result = DID_NO_CONNECT << 16;
+               done(srb);
+               return 0;
+       }
+
+       /* enqueue the command and wake up the control thread */
+       srb->scsi_done = done;
+       us->srb = srb;
+       complete(&us->cmnd_ready);
+
+       return 0;
+}
+
+/***********************************************************************
+ * Error handling functions
+ ***********************************************************************/
+
+/* Command timeout and abort */
+//----- command_abort() ---------------------
+static int command_abort(struct scsi_cmnd *srb)
+{
+       struct us_data *us = host_to_us(srb->device->host);
+
+       //printk("scsiglue --- command_abort\n");
+
+       scsi_lock(us_to_host(us));
+       if (us->srb != srb)
+       {
+               scsi_unlock(us_to_host(us));
+               printk ("-- nothing to abort\n");
+               return FAILED;
+       }
+
+       set_bit(US_FLIDX_TIMED_OUT, &us->dflags);
+       if (!test_bit(US_FLIDX_RESETTING, &us->dflags))
+       {
+               set_bit(US_FLIDX_ABORTING, &us->dflags);
+               usb_stor_stop_transport(us);
+       }
+       scsi_unlock(us_to_host(us));
+
+       /* Wait for the aborted command to finish */
+       wait_for_completion(&us->notify);
+       return SUCCESS;
+}
+
+/* This invokes the transport reset mechanism to reset the state of the device */
+//----- device_reset() ---------------------
+static int device_reset(struct scsi_cmnd *srb)
+{
+       struct us_data *us = host_to_us(srb->device->host);
+       int result;
+
+       //printk("scsiglue --- device_reset\n");
+
+       /* lock the device pointers and do the reset */
+       mutex_lock(&(us->dev_mutex));
+       result = us->transport_reset(us);
+       mutex_unlock(&us->dev_mutex);
+
+       return result < 0 ? FAILED : SUCCESS;
+}
+
+//----- bus_reset() ---------------------
+static int bus_reset(struct scsi_cmnd *srb)
+{
+       struct us_data *us = host_to_us(srb->device->host);
+       int result;
+
+       //printk("scsiglue --- bus_reset\n");
+       result = usb_stor_port_reset(us);
+       return result < 0 ? FAILED : SUCCESS;
+}
+
+//----- usb_stor_report_device_reset() ---------------------
+void usb_stor_report_device_reset(struct us_data *us)
+{
+       int i;
+       struct Scsi_Host *host = us_to_host(us);
+
+       //printk("scsiglue --- usb_stor_report_device_reset\n");
+       scsi_report_device_reset(host, 0, 0);
+       if (us->fflags & US_FL_SCM_MULT_TARG)
+       {
+               for (i = 1; i < host->max_id; ++i)
+                       scsi_report_device_reset(host, 0, i);
+       }
+}
+
+//----- usb_stor_report_bus_reset() ---------------------
+void usb_stor_report_bus_reset(struct us_data *us)
+{
+       struct Scsi_Host *host = us_to_host(us);
+
+       //printk("scsiglue --- usb_stor_report_bus_reset\n");
+       scsi_lock(host);
+       scsi_report_bus_reset(host, 0);
+       scsi_unlock(host);
+}
+
+/***********************************************************************
+ * /proc/scsi/ functions
+ ***********************************************************************/
+
+/* we use this macro to help us write into the buffer */
+#undef SPRINTF
+#define SPRINTF(args...) \
+       do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
+
+//----- proc_info() ---------------------
+static int proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout)
+{
+       struct us_data *us = host_to_us(host);
+       char *pos = buffer;
+       const char *string;
+
+       //printk("scsiglue --- proc_info\n");
+       if (inout)
+               return length;
+
+       /* print the controller name */
+       SPRINTF("   Host scsi%d: usb-storage\n", host->host_no);
+
+       /* print product, vendor, and serial number strings */
+       if (us->pusb_dev->manufacturer)
+               string = us->pusb_dev->manufacturer;
+       else if (us->unusual_dev->vendorName)
+               string = us->unusual_dev->vendorName;
+       else
+               string = "Unknown";
+       SPRINTF("       Vendor: %s\n", string);
+       if (us->pusb_dev->product)
+               string = us->pusb_dev->product;
+       else if (us->unusual_dev->productName)
+               string = us->unusual_dev->productName;
+       else
+               string = "Unknown";
+       SPRINTF("      Product: %s\n", string);
+       if (us->pusb_dev->serial)
+               string = us->pusb_dev->serial;
+       else
+               string = "None";
+       SPRINTF("Serial Number: %s\n", string);
+
+       /* show the protocol and transport */
+       SPRINTF("     Protocol: %s\n", us->protocol_name);
+       SPRINTF("    Transport: %s\n", us->transport_name);
+
+       /* show the device flags */
+       if (pos < buffer + length)
+       {
+               pos += sprintf(pos, "       Quirks:");
+
+#define US_FLAG(name, value) \
+       if (us->fflags & value) pos += sprintf(pos, " " #name);
+US_DO_ALL_FLAGS
+#undef US_FLAG
+
+               *(pos++) = '\n';
+       }
+
+       /* Calculate start of next buffer, and return value. */
+       *start = buffer + offset;
+
+       if ((pos - buffer) < offset)
+               return (0);
+       else if ((pos - buffer - offset) < length)
+               return (pos - buffer - offset);
+       else
+               return (length);
+}
+
+/***********************************************************************
+ * Sysfs interface
+ ***********************************************************************/
+
+/* Output routine for the sysfs max_sectors file */
+//----- show_max_sectors() ---------------------
+static ssize_t show_max_sectors(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+
+       //printk("scsiglue --- ssize_t show_max_sectors\n");
+       return sprintf(buf, "%u\n", queue_max_sectors(sdev->request_queue));
+}
+
+/* Input routine for the sysfs max_sectors file */
+//----- store_max_sectors() ---------------------
+static ssize_t store_max_sectors(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       unsigned short ms;
+
+       //printk("scsiglue --- ssize_t store_max_sectors\n");
+       if (sscanf(buf, "%hu", &ms) > 0 && ms <= SCSI_DEFAULT_MAX_SECTORS)
+       {
+               blk_queue_max_hw_sectors(sdev->request_queue, ms);
+               return strlen(buf);
+       }
+       return -EINVAL; 
+}
+
+static DEVICE_ATTR(max_sectors, S_IRUGO | S_IWUSR, show_max_sectors, store_max_sectors);
+static struct device_attribute *sysfs_device_attr_list[] = {&dev_attr_max_sectors, NULL, };
+
+/* this defines our host template, with which we'll allocate hosts */
+
+//----- usb_stor_host_template() ---------------------
+struct scsi_host_template usb_stor_host_template = {
+       /* basic userland interface stuff */
+       .name =                         "eucr-storage",
+       .proc_name =                    "eucr-storage",
+       .proc_info =                    proc_info,
+       .info =                         host_info,
+
+       /* command interface -- queued only */
+       .queuecommand =                 queuecommand,
+
+       /* error and abort handlers */
+       .eh_abort_handler =             command_abort,
+       .eh_device_reset_handler =      device_reset,
+       .eh_bus_reset_handler =         bus_reset,
+
+       /* queue commands only, only one command per LUN */
+       .can_queue =                    1,
+       .cmd_per_lun =                  1,
+
+       /* unknown initiator id */
+       .this_id =                      -1,
+
+       .slave_alloc =                  slave_alloc,
+       .slave_configure =              slave_configure,
+
+       /* lots of sg segments can be handled */
+       .sg_tablesize =                 SG_ALL,
+
+       /* limit the total size of a transfer to 120 KB */
+       .max_sectors =                  240,
+
+       /* merge commands... this seems to help performance, but
+        * periodically someone should test to see which setting is more
+        * optimal.
+        */
+       .use_clustering =               1,
+
+       /* emulated HBA */
+       .emulated =                     1,
+
+       /* we do our own delay after a device or bus reset */
+       .skip_settle_delay =            1,
+
+       /* sysfs device attributes */
+       .sdev_attrs =                   sysfs_device_attr_list,
+
+       /* module management */
+       .module =                       THIS_MODULE
+};
+
+/* To Report "Illegal Request: Invalid Field in CDB */
+unsigned char usb_stor_sense_invalidCDB[18] = {
+       [0]     = 0x70,                     /* current error */
+       [2]     = ILLEGAL_REQUEST,          /* Illegal Request = 0x05 */
+       [7]     = 0x0a,                     /* additional length */
+       [12]    = 0x24                      /* Invalid Field in CDB */
+};
+
+/***********************************************************************
+ * Scatter-gather transfer buffer access routines
+ ***********************************************************************/
+
+//----- usb_stor_access_xfer_buf() ---------------------
+unsigned int usb_stor_access_xfer_buf(struct us_data *us, unsigned char *buffer,
+       unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
+       unsigned int *offset, enum xfer_buf_dir dir)
+{
+       unsigned int cnt;
+
+       //printk("transport --- usb_stor_access_xfer_buf\n");
+       struct scatterlist *sg = *sgptr;
+
+       if (!sg)
+               sg = scsi_sglist(srb);
+
+       cnt = 0;
+       while (cnt < buflen && sg)
+       {
+               struct page *page = sg_page(sg) + ((sg->offset + *offset) >> PAGE_SHIFT);
+               unsigned int poff = (sg->offset + *offset) & (PAGE_SIZE-1);
+               unsigned int sglen = sg->length - *offset;
+
+               if (sglen > buflen - cnt)
+               {
+                       /* Transfer ends within this s-g entry */
+                       sglen = buflen - cnt;
+                       *offset += sglen;
+               }
+               else
+               {
+                       /* Transfer continues to next s-g entry */
+                       *offset = 0;
+                       sg = sg_next(sg);
+               }
+
+               while (sglen > 0)
+               {
+                       unsigned int plen = min(sglen, (unsigned int)PAGE_SIZE - poff);
+                       unsigned char *ptr = kmap(page);
+
+                       if (dir == TO_XFER_BUF)
+                               memcpy(ptr + poff, buffer + cnt, plen);
+                       else
+                               memcpy(buffer + cnt, ptr + poff, plen);
+                       kunmap(page);
+
+                       /* Start at the beginning of the next page */
+                       poff = 0;
+                       ++page;
+                       cnt += plen;
+                       sglen -= plen;
+               }
+       }
+       *sgptr = sg;
+
+       /* Return the amount actually transferred */
+       return cnt;
+}
+
+/* Store the contents of buffer into srb's transfer buffer and set the SCSI residue. */
+//----- usb_stor_set_xfer_buf() ---------------------
+void usb_stor_set_xfer_buf(struct us_data *us, unsigned char *buffer, unsigned int buflen, struct scsi_cmnd *srb,
+       unsigned int dir)
+{
+       unsigned int offset = 0;
+       struct scatterlist *sg = NULL;
+
+       //printk("transport --- usb_stor_set_xfer_buf\n");
+       // TO_XFER_BUF = 0, FROM_XFER_BUF = 1
+       buflen = min(buflen, scsi_bufflen(srb));
+       buflen = usb_stor_access_xfer_buf(us, buffer, buflen, srb, &sg, &offset, dir);
+       if (buflen < scsi_bufflen(srb))
+               scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
+}
diff --git a/drivers/staging/keucr/scsiglue.h b/drivers/staging/keucr/scsiglue.h
new file mode 100644 (file)
index 0000000..c7e59f0
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _SCSIGLUE_H_
+#define _SCSIGLUE_H_
+
+extern void usb_stor_report_device_reset(struct us_data *us);
+extern void usb_stor_report_bus_reset(struct us_data *us);
+
+extern unsigned char usb_stor_sense_invalidCDB[18];
+extern struct scsi_host_template usb_stor_host_template;
+
+#endif
diff --git a/drivers/staging/keucr/sdscsi.c b/drivers/staging/keucr/sdscsi.c
new file mode 100644 (file)
index 0000000..6c332f8
--- /dev/null
@@ -0,0 +1,210 @@
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+
+#include "usb.h"
+#include "scsiglue.h"
+#include "transport.h"
+
+int SD_SCSI_Test_Unit_Ready (struct us_data *us, struct scsi_cmnd *srb);
+int SD_SCSI_Inquiry         (struct us_data *us, struct scsi_cmnd *srb);
+int SD_SCSI_Mode_Sense      (struct us_data *us, struct scsi_cmnd *srb);
+int SD_SCSI_Start_Stop      (struct us_data *us, struct scsi_cmnd *srb);
+int SD_SCSI_Read_Capacity   (struct us_data *us, struct scsi_cmnd *srb);
+int SD_SCSI_Read            (struct us_data *us, struct scsi_cmnd *srb);
+int SD_SCSI_Write           (struct us_data *us, struct scsi_cmnd *srb);
+
+//----- SD_SCSIIrp() --------------------------------------------------
+int SD_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb)
+{
+       int    result;
+
+       us->SrbStatus = SS_SUCCESS;
+       switch (srb->cmnd[0])
+       {
+               case TEST_UNIT_READY :  result = SD_SCSI_Test_Unit_Ready (us, srb);  break; //0x00
+               case INQUIRY         :  result = SD_SCSI_Inquiry         (us, srb);  break; //0x12
+               case MODE_SENSE      :  result = SD_SCSI_Mode_Sense      (us, srb);  break; //0x1A
+//             case START_STOP      :  result = SD_SCSI_Start_Stop      (us, srb);  break; //0x1B
+               case READ_CAPACITY   :  result = SD_SCSI_Read_Capacity   (us, srb);  break; //0x25
+               case READ_10         :  result = SD_SCSI_Read            (us, srb);  break; //0x28
+               case WRITE_10        :  result = SD_SCSI_Write           (us, srb);  break; //0x2A
+
+               default:
+                       us->SrbStatus = SS_ILLEGAL_REQUEST;
+                       result = USB_STOR_TRANSPORT_FAILED;
+                       break;
+       }
+       return result;
+}
+
+//----- SD_SCSI_Test_Unit_Ready() --------------------------------------------------
+int SD_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb)
+{
+       //printk("SD_SCSI_Test_Unit_Ready\n");
+       if (us->SD_Status.Insert && us->SD_Status.Ready)
+               return USB_STOR_TRANSPORT_GOOD;
+       else
+       {
+               ENE_SDInit(us);
+               return USB_STOR_TRANSPORT_GOOD;
+       }
+               
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- SD_SCSI_Inquiry() --------------------------------------------------
+int SD_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb)
+{
+       //printk("SD_SCSI_Inquiry\n");
+       BYTE data_ptr[36] = {0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
+
+       usb_stor_set_xfer_buf(us, data_ptr, 36, srb, TO_XFER_BUF);
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+
+//----- SD_SCSI_Mode_Sense() --------------------------------------------------
+int SD_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb)
+{
+       BYTE    mediaNoWP[12] = {0x0b,0x00,0x00,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
+       BYTE    mediaWP[12]   = {0x0b,0x00,0x80,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
+
+       if (us->SD_Status.WtP)
+               usb_stor_set_xfer_buf(us, mediaWP, 12, srb, TO_XFER_BUF);
+       else
+               usb_stor_set_xfer_buf(us, mediaNoWP, 12, srb, TO_XFER_BUF);
+
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- SD_SCSI_Read_Capacity() --------------------------------------------------
+int SD_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb)
+{
+       unsigned int offset = 0;
+       struct scatterlist *sg = NULL;
+       DWORD   bl_num;
+       WORD    bl_len;
+       BYTE    buf[8];
+
+       printk("SD_SCSI_Read_Capacity\n");
+       if ( us->SD_Status.HiCapacity )
+       {
+               bl_len = 0x200;
+               if (us->SD_Status.IsMMC)
+                       bl_num = us->HC_C_SIZE-1;
+               else
+                       bl_num = (us->HC_C_SIZE + 1) * 1024 - 1;
+       }
+       else
+       {
+               bl_len = 1<<(us->SD_READ_BL_LEN);
+               bl_num = us->SD_Block_Mult*(us->SD_C_SIZE+1)*(1<<(us->SD_C_SIZE_MULT+2)) - 1;
+       }
+       us->bl_num = bl_num;
+       printk("bl_len = %x\n", bl_len);
+       printk("bl_num = %x\n", bl_num);
+
+       //srb->request_bufflen = 8;
+       buf[0] = (bl_num>>24) & 0xff;
+       buf[1] = (bl_num>>16) & 0xff;
+       buf[2] = (bl_num>> 8) & 0xff;
+       buf[3] = (bl_num>> 0) & 0xff;
+       buf[4] = (bl_len>>24) & 0xff;
+       buf[5] = (bl_len>>16) & 0xff;
+       buf[6] = (bl_len>> 8) & 0xff;
+       buf[7] = (bl_len>> 0) & 0xff;
+       
+       usb_stor_access_xfer_buf(us, buf, 8, srb, &sg, &offset, TO_XFER_BUF);
+       //usb_stor_set_xfer_buf(us, buf, srb->request_bufflen, srb, TO_XFER_BUF);
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- SD_SCSI_Read() --------------------------------------------------
+int SD_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int result;
+       PBYTE   Cdb = srb->cmnd;
+       DWORD bn  =  ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
+                   ((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
+       WORD  blen = ((Cdb[7]<< 8) & 0xff00)     | ((Cdb[8]<< 0) & 0x00ff);
+       DWORD bnByte = bn * 0x200;
+       DWORD   blenByte = blen * 0x200;
+
+       if (bn > us->bl_num)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       result = ENE_LoadBinCode(us, SD_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load SD RW pattern Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       if ( us->SD_Status.HiCapacity )
+               bnByte = bn;
+               
+       // set up the command wrapper
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = blenByte;
+       bcb->Flags  = 0x80;
+       bcb->CDB[0] = 0xF1;
+       bcb->CDB[5] = (BYTE)(bnByte);
+       bcb->CDB[4] = (BYTE)(bnByte>>8);
+       bcb->CDB[3] = (BYTE)(bnByte>>16);
+       bcb->CDB[2] = (BYTE)(bnByte>>24);
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, scsi_sglist(srb), 1);
+       return result;
+}
+
+//----- SD_SCSI_Write() --------------------------------------------------
+int SD_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int result;
+       PBYTE   Cdb = srb->cmnd;
+       DWORD bn  =  ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
+                   ((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
+       WORD  blen = ((Cdb[7]<< 8) & 0xff00)     | ((Cdb[8]<< 0) & 0x00ff);
+       DWORD bnByte = bn * 0x200;
+       DWORD   blenByte = blen * 0x200;
+
+       if (bn > us->bl_num)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       result = ENE_LoadBinCode(us, SD_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load SD RW pattern Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       if ( us->SD_Status.HiCapacity )
+               bnByte = bn;
+
+       // set up the command wrapper
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = blenByte;
+       bcb->Flags  = 0x00;
+       bcb->CDB[0] = 0xF0;
+       bcb->CDB[5] = (BYTE)(bnByte);
+       bcb->CDB[4] = (BYTE)(bnByte>>8);
+       bcb->CDB[3] = (BYTE)(bnByte>>16);
+       bcb->CDB[2] = (BYTE)(bnByte>>24);
+
+       result = ENE_SendScsiCmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
+       return result;
+}
+
+
+
diff --git a/drivers/staging/keucr/smcommon.h b/drivers/staging/keucr/smcommon.h
new file mode 100644 (file)
index 0000000..c20dbcf
--- /dev/null
@@ -0,0 +1,40 @@
+//----- < SMCommon.h> --------------------------------------------------
+#ifndef SMCOMMON_INCD
+#define SMCOMMON_INCD
+
+
+/***************************************************************************
+Define Difinetion
+***************************************************************************/
+#define SUCCESS             0x0000 /* SUCCESS */
+#define ERROR               0xFFFF /* ERROR */
+#define CORRECT             0x0001 /* CORRECTABLE */
+
+/***************************************************************************/
+#define NO_ERROR            0x0000 /* NO ERROR */
+#define ERR_WriteFault      0x0003 /* Peripheral Device Write Fault */
+#define ERR_HwError         0x0004 /* Hardware Error */
+#define ERR_DataStatus      0x0010 /* DataStatus Error */
+#define ERR_EccReadErr      0x0011 /* Unrecovered Read Error */
+#define ERR_CorReadErr      0x0018 /* Recovered Read Data with ECC */
+#define ERR_OutOfLBA        0x0021 /* Illegal Logical Block Address */
+#define ERR_WrtProtect      0x0027 /* Write Protected */
+#define ERR_ChangedMedia    0x0028 /* Medium Changed */
+#define ERR_UnknownMedia    0x0030 /* Incompatible Medium Installed */
+#define ERR_IllegalFmt      0x0031 /* Medium Format Corrupted */
+#define ERR_NoSmartMedia    0x003A /* Medium Not Present */
+
+
+
+/***************************************************************************/
+//#define SUCCESS   0 /* SUCCESS */
+//#define ERROR    -1 /* ERROR */
+
+/***************************************************************************/
+char Bit_D_Count     (BYTE);
+char Bit_D_CountWord (WORD);
+void StringCopy    (char *, char *, int);
+int  StringCmp     (char *, char *, int);
+
+
+#endif // already included
diff --git a/drivers/staging/keucr/smil.h b/drivers/staging/keucr/smil.h
new file mode 100644 (file)
index 0000000..b138888
--- /dev/null
@@ -0,0 +1,289 @@
+//----- < smil.h> ----------------------------------------------------
+#ifndef SMIL_INCD
+#define SMIL_INCD
+
+/***************************************************************************
+Define Definition
+***************************************************************************/
+#define K_BYTE              1024   /* Kilo Byte */
+#define SECTSIZE            512    /* Sector buffer size */
+#define REDTSIZE            16     /* Redundant buffer size */
+
+/***************************************************************************/
+#define DUMMY_DATA          0xFF   /* No Assign Sector Read Data */
+
+/***************************************************************************
+Max Zone/Block/Sectors Data Definition
+***************************************************************************/
+#define MAX_ZONENUM         128    /* Max Zone Numbers in a SmartMedia    */
+#define MAX_BLOCKNUM        0x0400 /* Max Block Numbers in a Zone         */
+#define MAX_SECTNUM         0x20   /* Max Sector Numbers in a Block       */
+#define MAX_LOGBLOCK        1000   /* Max Logical Block Numbers in a Zone */
+
+/***************************************************************************/
+#define CIS_SEARCH_SECT     0x08   /* Max CIS Search Sector Number */
+
+/***************************************************************************
+Logical to Physical Block Table Data Definition
+***************************************************************************/
+#define NO_ASSIGN           0xFFFF /* No Assign Logical Block Address */
+
+/***************************************************************************
+'SectCopyMode' Data
+***************************************************************************/
+#define COMPLETED           0      /* Sector Copy Completed */
+#define REQ_ERASE           1      /* Request Read Block Erase */
+#define REQ_FAIL            2      /* Request Read Block Failed */
+
+/***************************************************************************
+Retry Counter Definition
+***************************************************************************/
+#define RDERR_REASSIGN      1      /* Reassign with Read Error */
+#define L2P_ERR_ERASE       1      /* BlockErase for Contradicted L2P Table */
+
+/***************************************************************************
+Hardware ECC Definition
+***************************************************************************/
+#define HW_ECC_SUPPORTED    1      /* Hardware ECC Supported */  /* No difinition for Software ECC */
+
+/***************************************************************************
+SmartMedia Command & Status Definition
+***************************************************************************/
+/* SmartMedia Command */
+#define WRDATA        0x80
+//#define READ          0x00
+#define READ_REDT     0x50
+//#define WRITE         0x10
+#define RDSTATUS      0x70
+
+#define READ1         0x00 //NO
+#define READ2         0x01 //NO
+#define READ3         0x50 //NO
+#define RST_CHIP      0xFF
+#define ERASE1        0x60
+#define ERASE2        0xD0
+#define READ_ID_1     0x90
+#define READ_ID_2     0x91
+#define READ_ID_3     0x9A
+
+/* 712 SmartMedia Command */
+#define SM_CMD_RESET                0x00    // 0xFF
+#define SM_CMD_READ_ID_1            0x10    // 0x90
+#define SM_CMD_READ_ID_2            0x20    // 0x91
+#define SM_CMD_READ_STAT            0x30    // 0x70
+#define SM_CMD_RDMULTPL_STAT        0x40    // 0x71
+#define SM_CMD_READ_1               0x50    // 0x00
+#define SM_CMD_READ_2               0x60    // 0x01
+#define SM_CMD_READ_3               0x70    // 0x50
+#define SM_CMD_PAGPRGM_TRUE         0x80    // {0x80, 0x10}
+#define SM_CMD_PAGPRGM_DUMY         0x90    // {0x80, 0x11}
+#define SM_CMD_PAGPRGM_MBLK         0xA0    // {0x80, 0x15}
+#define SM_CMD_BLKERASE             0xB0    // {0x60, 0xD0}
+#define SM_CMD_BLKERASE_MULTPL      0xC0    // {0x60-0x60, 0xD0}
+
+#define SM_CRADDTCT_DEBNCETIMER_EN  0x02
+#define SM_CMD_START_BIT            0x01
+
+#define SM_WaitCmdDone { while (!SM_CmdDone); }
+#define SM_WaitDmaDone { while (!SM_DmaDone); }
+
+// SmartMedia Status
+#define WR_FAIL       0x01      // 0:Pass, 1:Fail
+#define SUSPENDED     0x20      // 0:Not Suspended, 1:Suspended
+#define READY         0x40      // 0:Busy, 1:Ready
+#define WR_PRTCT      0x80      // 0:Protect, 1:Not Protect
+
+// SmartMedia Busy Time (1bit:0.1ms)
+#define BUSY_PROG     200       // tPROG   : 20ms  ----- Program Time          old : 200
+#define BUSY_ERASE    4000      // tBERASE : 400ms ----- Block Erase Time      old : 4000
+//for 712 Test
+//#define BUSY_READ     1         // tR      : 100us ----- Data transfer Time   old : 1
+//#define BUSY_READ     10         // tR      : 100us ----- Data transfer Time   old : 1
+#define BUSY_READ     200       // tR      : 20ms   ----- Data transfer Time   old : 1
+//#define BUSY_RESET    60        // tRST    : 6ms   ----- Device Resetting Time old : 60
+#define BUSY_RESET    600        // tRST    : 60ms   ----- Device Resetting Time old : 60
+
+// Hardware Timer (1bit:0.1ms)
+#define TIME_PON      3000      // 300ms ------ Power On Wait Time
+#define TIME_CDCHK    200       // 20ms  ------ Card Check Interval Timer
+#define TIME_WPCHK    50        // 5ms   ------ WP Check Interval Timer
+#define TIME_5VCHK    10        // 1ms   ------ 5V Check Interval Timer
+
+/***************************************************************************
+Redundant Data
+***************************************************************************/
+#define REDT_DATA     0x04
+#define REDT_BLOCK    0x05
+#define REDT_ADDR1H   0x06
+#define REDT_ADDR1L   0x07
+#define REDT_ADDR2H   0x0B
+#define REDT_ADDR2L   0x0C
+#define REDT_ECC10    0x0D
+#define REDT_ECC11    0x0E
+#define REDT_ECC12    0x0F
+#define REDT_ECC20    0x08
+#define REDT_ECC21    0x09
+#define REDT_ECC22    0x0A
+
+/***************************************************************************
+SmartMedia Model & Attribute
+***************************************************************************/
+/* SmartMedia Attribute */
+#define NOWP          0x00 // 0... .... No Write Protect
+#define WP            0x80 // 1... .... Write Protected
+#define MASK          0x00 // .00. .... NAND MASK ROM Model
+#define FLASH         0x20 // .01. .... NAND Flash ROM Model
+#define AD3CYC        0x00 // ...0 .... Address 3-cycle
+#define AD4CYC        0x10 // ...1 .... Address 4-cycle
+#define BS16          0x00 // .... 00.. 16page/block
+#define BS32          0x04 // .... 01.. 32page/block
+#define PS256         0x00 // .... ..00 256byte/page
+#define PS512         0x01 // .... ..01 512byte/page
+#define MWP           0x80 // WriteProtect mask
+#define MFLASH        0x60 // Flash Rom mask
+#define MADC          0x10 // Address Cycle
+#define MBS           0x0C // BlockSize mask
+#define MPS           0x03 // PageSize mask
+
+/* SmartMedia Model */
+#define NOSSFDC       0x00 // NO   SmartMedia
+#define SSFDC1MB      0x01 // 1MB  SmartMedia
+#define SSFDC2MB      0x02 // 2MB  SmartMedia
+#define SSFDC4MB      0x03 // 4MB  SmartMedia
+#define SSFDC8MB      0x04 // 8MB  SmartMedia
+#define SSFDC16MB     0x05 // 16MB SmartMedia
+#define SSFDC32MB     0x06 // 32MB SmartMedia
+#define SSFDC64MB     0x07 // 64MB SmartMedia
+#define SSFDC128MB    0x08 //128MB SmartMedia
+#define SSFDC256MB    0x09
+#define SSFDC512MB    0x0A
+#define SSFDC1GB      0x0B
+#define SSFDC2GB      0x0C
+
+/***************************************************************************
+Struct Definition
+***************************************************************************/
+struct SSFDCTYPE
+{
+    BYTE    Model;
+    BYTE    Attribute;
+    BYTE    MaxZones;
+    BYTE    MaxSectors;
+    WORD    MaxBlocks;
+    WORD    MaxLogBlocks;
+};
+
+typedef struct SSFDCTYPE_T
+{
+    BYTE    Model;
+    BYTE    Attribute;
+    BYTE    MaxZones;
+    BYTE    MaxSectors;
+    WORD    MaxBlocks;
+    WORD    MaxLogBlocks;
+} *SSFDCTYPE_T;
+
+struct ADDRESS
+{
+    BYTE    Zone;     /* Zone Number */
+    BYTE    Sector;   /* Sector(512byte) Number on Block */
+    WORD    PhyBlock; /* Physical Block Number on Zone */
+    WORD    LogBlock; /* Logical Block Number of Zone */
+};
+typedef struct ADDRESS_T
+{
+    BYTE    Zone;     /* Zone Number */
+    BYTE    Sector;   /* Sector(512byte) Number on Block */
+    WORD    PhyBlock; /* Physical Block Number on Zone */
+    WORD    LogBlock; /* Logical Block Number of Zone */
+}*ADDRESS_T;
+
+struct CIS_AREA
+{
+    BYTE    Sector;   /* Sector(512byte) Number on Block */
+    WORD    PhyBlock; /* Physical Block Number on Zone 0 */
+};
+
+
+//----- SMILMain.c ---------------------------------------------------
+/******************************************/
+int         Init_D_SmartMedia           (void);
+int         Pwoff_D_SmartMedia          (void);
+int         Check_D_SmartMedia          (void);
+int         Check_D_Parameter           (struct us_data *,WORD *,BYTE *,BYTE *);
+int         Media_D_ReadSector          (struct us_data *,DWORD,WORD,BYTE *);
+int         Media_D_WriteSector         (struct us_data *,DWORD,WORD,BYTE *);
+int         Media_D_CopySector          (struct us_data *,DWORD,WORD,BYTE *);
+int         Media_D_EraseBlock          (struct us_data *,DWORD,WORD);
+int         Media_D_EraseAll            (struct us_data *);
+/******************************************/
+int         Media_D_OneSectWriteStart   (struct us_data *,DWORD,BYTE *);
+int         Media_D_OneSectWriteNext    (struct us_data *,BYTE *);
+int         Media_D_OneSectWriteFlush   (struct us_data *);
+
+/******************************************/
+void        SM_EnableLED                (struct us_data *,BOOLEAN);
+void        Led_D_TernOn                (void);
+void        Led_D_TernOff               (void);
+
+int         Media_D_EraseAllRedtData    (DWORD Index, BOOLEAN CheckBlock);
+//DWORD       Media_D_GetMediaInfo        (struct us_data * fdoExt, PIOCTL_MEDIA_INFO_IN pParamIn, PIOCTL_MEDIA_INFO_OUT pParamOut);
+
+//----- SMILSub.c ----------------------------------------------------
+/******************************************/
+int  Check_D_DataBlank            (BYTE *);
+int  Check_D_FailBlock            (BYTE *);
+int  Check_D_DataStatus           (BYTE *);
+int  Load_D_LogBlockAddr          (BYTE *);
+void Clr_D_RedundantData          (BYTE *);
+void Set_D_LogBlockAddr           (BYTE *);
+void Set_D_FailBlock              (BYTE *);
+void Set_D_DataStaus              (BYTE *);
+
+/******************************************/
+void Ssfdc_D_Reset                (struct us_data *);
+int  Ssfdc_D_ReadCisSect          (struct us_data *, BYTE *,BYTE *);
+void Ssfdc_D_WriteRedtMode        (void);
+void Ssfdc_D_ReadID               (BYTE *, BYTE);
+int  Ssfdc_D_ReadSect             (struct us_data *, BYTE *,BYTE *);
+int  Ssfdc_D_ReadBlock            (struct us_data *, WORD, BYTE *,BYTE *);
+int  Ssfdc_D_WriteSect            (struct us_data *, BYTE *,BYTE *);
+int  Ssfdc_D_WriteBlock           (struct us_data *, WORD, BYTE *,BYTE *);
+int  Ssfdc_D_CopyBlock            (struct us_data *, WORD, BYTE *,BYTE *);
+int  Ssfdc_D_WriteSectForCopy     (struct us_data *, BYTE *,BYTE *);
+int  Ssfdc_D_EraseBlock           (struct us_data *);
+int  Ssfdc_D_ReadRedtData         (struct us_data *, BYTE *);
+int  Ssfdc_D_WriteRedtData        (struct us_data *, BYTE *);
+int  Ssfdc_D_CheckStatus          (void);
+int  Set_D_SsfdcModel             (BYTE);
+void Cnt_D_Reset                  (void);
+int  Cnt_D_PowerOn                (void);
+void Cnt_D_PowerOff               (void);
+void Cnt_D_LedOn                  (void);
+void Cnt_D_LedOff                 (void);
+int  Check_D_CntPower             (void);
+int  Check_D_CardExist            (void);
+int  Check_D_CardStsChg           (void);
+int  Check_D_SsfdcWP              (void);
+int  SM_ReadBlock                 (struct us_data *, BYTE *,BYTE *);
+
+int  Ssfdc_D_ReadSect_DMA         (struct us_data *, BYTE *,BYTE *);
+int  Ssfdc_D_ReadSect_PIO         (struct us_data *, BYTE *,BYTE *);
+int  Ssfdc_D_WriteSect_DMA        (struct us_data *, BYTE *,BYTE *);
+int  Ssfdc_D_WriteSect_PIO        (struct us_data *, BYTE *,BYTE *);
+
+/******************************************/
+int  Check_D_ReadError            (BYTE *);
+int  Check_D_Correct              (BYTE *,BYTE *);
+int  Check_D_CISdata              (BYTE *,BYTE *);
+void Set_D_RightECC               (BYTE *);
+
+//----- SMILECC.c ----------------------------------------------------
+void calculate_ecc                (BYTE *, BYTE *, BYTE *, BYTE *, BYTE *);
+BYTE correct_data                 (BYTE *, BYTE *, BYTE,   BYTE,   BYTE);
+int  _Correct_D_SwECC             (BYTE *,BYTE *,BYTE *);
+void _Calculate_D_SwECC           (BYTE *,BYTE *);
+
+void SM_Init        (void);
+
+#endif // already included
diff --git a/drivers/staging/keucr/smilecc.c b/drivers/staging/keucr/smilecc.c
new file mode 100644 (file)
index 0000000..daf322a
--- /dev/null
@@ -0,0 +1,201 @@
+#include "usb.h"
+#include "scsiglue.h"
+#include "transport.h"
+//#include "stdlib.h"
+//#include "EUCR6SK.h"
+#include "smcommon.h"
+#include "smil.h"
+
+//#include <stdio.h>
+//#include <stdlib.h>
+//#include <string.h>
+//#include <dos.h>
+//
+//#include "EMCRIOS.h"
+
+// CP0-CP5 code table
+static BYTE ecctable[256] = {
+0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00,
+0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
+0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
+0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
+0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
+0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
+0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
+0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
+0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
+0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
+0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
+0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
+0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
+0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
+0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
+0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00
+};
+
+static void   trans_result  (BYTE,   BYTE,   BYTE *, BYTE *);
+
+#define BIT7        0x80
+#define BIT6        0x40
+#define BIT5        0x20
+#define BIT4        0x10
+#define BIT3        0x08
+#define BIT2        0x04
+#define BIT1        0x02
+#define BIT0        0x01
+#define BIT1BIT0    0x03
+#define BIT23       0x00800000L
+#define MASK_CPS    0x3f
+#define CORRECTABLE 0x00555554L
+
+static void trans_result(reg2,reg3,ecc1,ecc2)
+BYTE reg2; // LP14,LP12,LP10,...
+BYTE reg3; // LP15,LP13,LP11,...
+BYTE *ecc1; // LP15,LP14,LP13,...
+BYTE *ecc2; // LP07,LP06,LP05,...
+{
+    BYTE a; // Working for reg2,reg3
+    BYTE b; // Working for ecc1,ecc2
+    BYTE i; // For counting
+
+    a=BIT7; b=BIT7; // 80h=10000000b
+    *ecc1=*ecc2=0; // Clear ecc1,ecc2
+    for(i=0; i<4; ++i) {
+        if ((reg3&a)!=0)
+            *ecc1|=b; // LP15,13,11,9 -> ecc1
+        b=b>>1; // Right shift
+        if ((reg2&a)!=0)
+            *ecc1|=b; // LP14,12,10,8 -> ecc1
+        b=b>>1; // Right shift
+        a=a>>1; // Right shift
+    }
+
+    b=BIT7; // 80h=10000000b
+    for(i=0; i<4; ++i) {
+        if ((reg3&a)!=0)
+            *ecc2|=b; // LP7,5,3,1 -> ecc2
+        b=b>>1; // Right shift
+        if ((reg2&a)!=0)
+            *ecc2|=b; // LP6,4,2,0 -> ecc2
+        b=b>>1; // Right shift
+        a=a>>1; // Right shift
+    }
+}
+
+//static void calculate_ecc(table,data,ecc1,ecc2,ecc3)
+void calculate_ecc(table,data,ecc1,ecc2,ecc3)
+BYTE *table; // CP0-CP5 code table
+BYTE *data; // DATA
+BYTE *ecc1; // LP15,LP14,LP13,...
+BYTE *ecc2; // LP07,LP06,LP05,...
+BYTE *ecc3; // CP5,CP4,CP3,...,"1","1"
+{
+    DWORD  i;    // For counting
+    BYTE a;    // Working for table
+    BYTE reg1; // D-all,CP5,CP4,CP3,...
+    BYTE reg2; // LP14,LP12,L10,...
+    BYTE reg3; // LP15,LP13,L11,...
+
+    reg1=reg2=reg3=0;   // Clear parameter
+    for(i=0; i<256; ++i) {
+        a=table[data[i]]; // Get CP0-CP5 code from table
+        reg1^=(a&MASK_CPS); // XOR with a
+        if ((a&BIT6)!=0)
+        { // If D_all(all bit XOR) = 1
+            reg3^=(BYTE)i; // XOR with counter
+            reg2^=~((BYTE)i); // XOR with inv. of counter
+        }
+    }
+
+    // Trans LP14,12,10,... & LP15,13,11,... -> LP15,14,13,... & LP7,6,5,..
+    trans_result(reg2,reg3,ecc1,ecc2);
+    *ecc1=~(*ecc1); *ecc2=~(*ecc2); // Inv. ecc2 & ecc3
+    *ecc3=((~reg1)<<2)|BIT1BIT0; // Make TEL format
+}
+
+BYTE correct_data(data,eccdata,ecc1,ecc2,ecc3)
+BYTE *data; // DATA
+BYTE *eccdata; // ECC DATA
+BYTE ecc1; // LP15,LP14,LP13,...
+BYTE ecc2; // LP07,LP06,LP05,...
+BYTE ecc3; // CP5,CP4,CP3,...,"1","1"
+{
+    DWORD l; // Working to check d
+    DWORD d; // Result of comparison
+    DWORD i; // For counting
+    BYTE d1,d2,d3; // Result of comparison
+    BYTE a; // Working for add
+    BYTE add; // Byte address of cor. DATA
+    BYTE b; // Working for bit
+    BYTE bit; // Bit address of cor. DATA
+
+    d1=ecc1^eccdata[1]; d2=ecc2^eccdata[0]; // Compare LP's
+    d3=ecc3^eccdata[2]; // Comapre CP's
+    d=((DWORD)d1<<16) // Result of comparison
+    +((DWORD)d2<<8)
+    +(DWORD)d3;
+
+    if (d==0) return(0); // If No error, return
+
+    if (((d^(d>>1))&CORRECTABLE)==CORRECTABLE)
+    { // If correctable
+        l=BIT23;
+        add=0; // Clear parameter
+        a=BIT7;
+
+        for(i=0; i<8; ++i) { // Checking 8 bit
+            if ((d&l)!=0) add|=a; // Make byte address from LP's
+            l>>=2; a>>=1; // Right Shift
+        }
+
+        bit=0; // Clear parameter
+        b=BIT2;
+        for(i=0; i<3; ++i) { // Checking 3 bit
+            if ((d&l)!=0) bit|=b; // Make bit address from CP's
+            l>>=2; b>>=1; // Right shift
+        }
+
+        b=BIT0;
+        data[add]^=(b<<bit); // Put corrected data
+        return(1);
+    }
+
+    i=0; // Clear count
+    d&=0x00ffffffL; // Masking
+
+    while(d) { // If d=0 finish counting
+        if (d&BIT0) ++i; // Count number of 1 bit
+        d>>=1; // Right shift
+    }
+
+    if (i==1)
+    { // If ECC error
+        eccdata[1]=ecc1; eccdata[0]=ecc2; // Put right ECC code
+        eccdata[2]=ecc3;
+        return(2);
+    }
+    return(3); // Uncorrectable error
+}
+
+int _Correct_D_SwECC(buf,redundant_ecc,calculate_ecc)
+BYTE *buf;
+BYTE *redundant_ecc;
+BYTE *calculate_ecc;
+{
+    DWORD err;
+
+    err=correct_data(buf,redundant_ecc,*(calculate_ecc+1),*(calculate_ecc),*(calculate_ecc+2));
+    if (err==1) StringCopy(calculate_ecc,redundant_ecc,3);
+        if (err==0 || err==1 || err==2)
+            return(0);
+    return(-1);
+}
+
+void _Calculate_D_SwECC(buf,ecc)
+BYTE *buf;
+BYTE *ecc;
+{
+    calculate_ecc(ecctable,buf,ecc+1,ecc+0,ecc+2);
+}
+
+
diff --git a/drivers/staging/keucr/smilmain.c b/drivers/staging/keucr/smilmain.c
new file mode 100644 (file)
index 0000000..bdfbf76
--- /dev/null
@@ -0,0 +1,1852 @@
+#include <linux/slab.h>
+#include "usb.h"
+#include "scsiglue.h"
+#include "smcommon.h"
+#include "smil.h"
+
+int         Check_D_LogCHS              (WORD *,BYTE *,BYTE *);
+void        Initialize_D_Media          (void);
+void        PowerOff_D_Media            (void);
+int         Check_D_MediaPower          (void);
+int         Check_D_MediaExist          (void);
+int         Check_D_MediaWP             (void);
+int         Check_D_MediaFmt            (struct us_data *);
+int         Check_D_MediaFmtForEraseAll (struct us_data *);
+int         Conv_D_MediaAddr            (struct us_data *, DWORD);
+int         Inc_D_MediaAddr             (struct us_data *);
+int         Check_D_FirstSect           (void);
+int         Check_D_LastSect            (void);
+int         Media_D_ReadOneSect         (struct us_data *, WORD, BYTE *);
+int         Media_D_WriteOneSect        (struct us_data *, WORD, BYTE *);
+int         Media_D_CopyBlockHead       (struct us_data *);
+int         Media_D_CopyBlockTail       (struct us_data *);
+int         Media_D_EraseOneBlock       (void);
+int         Media_D_EraseAllBlock       (void);
+
+int  Copy_D_BlockAll             (struct us_data *, DWORD);
+int  Copy_D_BlockHead            (struct us_data *);
+int  Copy_D_BlockTail            (struct us_data *);
+int  Reassign_D_BlockHead        (struct us_data *);
+
+int  Assign_D_WriteBlock         (void);
+int  Release_D_ReadBlock         (struct us_data *);
+int  Release_D_WriteBlock        (struct us_data *);
+int  Release_D_CopySector        (struct us_data *);
+
+int  Copy_D_PhyOneSect           (struct us_data *);
+int  Read_D_PhyOneSect           (struct us_data *, WORD, BYTE *);
+int  Write_D_PhyOneSect          (struct us_data *, WORD, BYTE *);
+int  Erase_D_PhyOneBlock         (struct us_data *);
+
+int  Set_D_PhyFmtValue           (struct us_data *);
+int  Search_D_CIS                (struct us_data *);
+int  Make_D_LogTable             (struct us_data *);
+void Check_D_BlockIsFull         (void);
+
+int  MarkFail_D_PhyOneBlock      (struct us_data *);
+
+DWORD ErrXDCode;
+DWORD ErrCode;
+//BYTE  SectBuf[SECTSIZE];
+BYTE  WorkBuf[SECTSIZE];
+BYTE  Redundant[REDTSIZE];
+BYTE  WorkRedund[REDTSIZE];
+//WORD  Log2Phy[MAX_ZONENUM][MAX_LOGBLOCK];
+WORD  *Log2Phy[MAX_ZONENUM];                 // 128 x 1000,   Log2Phy[MAX_ZONENUM][MAX_LOGBLOCK];
+BYTE  Assign[MAX_ZONENUM][MAX_BLOCKNUM/8];
+WORD  AssignStart[MAX_ZONENUM];
+WORD  ReadBlock;
+WORD  WriteBlock;
+DWORD MediaChange;
+DWORD SectCopyMode;
+
+extern struct SSFDCTYPE  Ssfdc;
+extern struct ADDRESS    Media;
+extern struct CIS_AREA   CisArea;
+
+//BIT Controll Macro
+BYTE BitData[] = { 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 } ;
+#define Set_D_Bit(a,b)    (a[(BYTE)((b)/8)]|= BitData[(b)%8])
+#define Clr_D_Bit(a,b)    (a[(BYTE)((b)/8)]&=~BitData[(b)%8])
+#define Chk_D_Bit(a,b)    (a[(BYTE)((b)/8)] & BitData[(b)%8])
+
+//extern PBYTE    SMHostAddr;
+extern BYTE     IsSSFDCCompliance;
+extern BYTE     IsXDCompliance;
+
+
+//
+////Power Controll & Media Exist Check Function
+////----- Init_D_SmartMedia() --------------------------------------------
+//int Init_D_SmartMedia(void)
+//{
+//    int     i;
+//
+//    EMCR_Print("Init_D_SmartMedia start\n");
+//    for (i=0; i<MAX_ZONENUM; i++)
+//    {
+//        if (Log2Phy[i]!=NULL)
+//        {
+//            EMCR_Print("ExFreePool Zone = %x, Addr = %x\n", i, Log2Phy[i]);
+//            ExFreePool(Log2Phy[i]);
+//            Log2Phy[i] = NULL;
+//        }
+//    }
+//
+//    Initialize_D_Media();
+//    return(NO_ERROR);
+//}
+
+//----- SM_FreeMem() -------------------------------------------------
+int SM_FreeMem(void)
+{
+       int     i;
+
+       printk("SM_FreeMem start\n");
+       for (i=0; i<MAX_ZONENUM; i++)
+       {
+               if (Log2Phy[i]!=NULL)
+               {
+                       printk("Free Zone = %x, Addr = %p\n", i, Log2Phy[i]);
+                       kfree(Log2Phy[i]);
+                       Log2Phy[i] = NULL;
+               }
+       }
+       return(NO_ERROR);
+}
+
+////----- Pwoff_D_SmartMedia() -------------------------------------------
+//int Pwoff_D_SmartMedia(void)
+//{
+//    PowerOff_D_Media();
+//    return(NO_ERROR);
+//}
+//
+////----- Check_D_SmartMedia() -------------------------------------------
+//int Check_D_SmartMedia(void)
+//{
+//    if (Check_D_MediaExist())
+//        return(ErrCode);
+//
+//    return(NO_ERROR);
+//}
+//
+////----- Check_D_Parameter() --------------------------------------------
+//int Check_D_Parameter(PFDO_DEVICE_EXTENSION fdoExt,WORD *pcyl,BYTE *phead,BYTE *psect)
+//{
+//    if (Check_D_MediaPower())
+//        return(ErrCode);
+//
+//    if (Check_D_MediaFmt(fdoExt))
+//        return(ErrCode);
+//
+//    if (Check_D_LogCHS(pcyl,phead,psect))
+//        return(ErrCode);
+//
+//    return(NO_ERROR);
+//}
+
+//SmartMedia Read/Write/Erase Function
+//----- Media_D_ReadSector() -------------------------------------------
+int Media_D_ReadSector(struct us_data *us, DWORD start,WORD count,BYTE *buf)
+{
+       WORD len, bn;
+
+       //if (Check_D_MediaPower())        ; Â¦b 6250 don't care
+       //    return(ErrCode);             ;
+       //if (Check_D_MediaFmt(fdoExt))    ;
+       //    return(ErrCode);             ;
+       if (Conv_D_MediaAddr(us, start))
+               return(ErrCode);
+
+       while(1)
+       {
+               len = Ssfdc.MaxSectors - Media.Sector;
+               if (count > len)
+                       bn = len;
+               else
+                       bn = count;
+               //if (Media_D_ReadOneSect(fdoExt, SectBuf))
+               //if (Media_D_ReadOneSect(fdoExt, count, buf))
+               if (Media_D_ReadOneSect(us, bn, buf))
+               {
+                       ErrCode = ERR_EccReadErr;
+                       return(ErrCode);
+               }
+
+               Media.Sector += bn;
+               count -= bn;
+
+               if (count<=0)
+                       break;
+
+               buf += bn * SECTSIZE;
+
+               if (Inc_D_MediaAddr(us))
+                       return(ErrCode);
+       }
+
+       return(NO_ERROR);
+}
+// here
+//----- Media_D_CopySector() ------------------------------------------
+int Media_D_CopySector(struct us_data *us, DWORD start,WORD count,BYTE *buf)
+{
+       //DWORD mode;
+       //int i;
+       WORD len, bn;
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       //printk("Media_D_CopySector !!!\n");
+       if (Conv_D_MediaAddr(us, start))
+               return(ErrCode);
+
+       while(1)
+       {
+               if (Assign_D_WriteBlock())
+                       return(ERROR);
+
+               len = Ssfdc.MaxSectors - Media.Sector;
+               if (count > len)
+                       bn = len;
+               else
+               bn = count;
+
+               //if (Ssfdc_D_CopyBlock(fdoExt,count,buf,Redundant))
+               if (Ssfdc_D_CopyBlock(us,bn,buf,Redundant))
+               {
+                       ErrCode = ERR_WriteFault;
+                       return(ErrCode);
+               }
+
+               Media.Sector = 0x1F;
+               //if (Release_D_ReadBlock(fdoExt))
+               if (Release_D_CopySector(us))
+               {
+                       if (ErrCode==ERR_HwError)
+                       {
+                               ErrCode = ERR_WriteFault;
+                               return(ErrCode);
+                       }
+               }
+               count -= bn;
+
+               if (count<=0)
+                       break;
+
+               buf += bn * SECTSIZE;
+
+               if (Inc_D_MediaAddr(us))
+                       return(ErrCode);
+
+       }
+       return(NO_ERROR);
+}
+
+//----- Release_D_CopySector() ------------------------------------------
+int Release_D_CopySector(struct us_data *us)
+{
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       Log2Phy[Media.Zone][Media.LogBlock]=WriteBlock;
+       Media.PhyBlock=ReadBlock;
+
+       if (Media.PhyBlock==NO_ASSIGN)
+       {
+               Media.PhyBlock=WriteBlock;
+               return(SUCCESS);
+       }
+
+       Clr_D_Bit(Assign[Media.Zone],Media.PhyBlock);
+       Media.PhyBlock=WriteBlock;
+
+       return(SUCCESS);
+}
+/*
+//----- Media_D_WriteSector() ------------------------------------------
+int Media_D_WriteSector(PFDO_DEVICE_EXTENSION fdoExt, DWORD start,WORD count,BYTE *buf)
+{
+    int i;
+    WORD len, bn;
+    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+    ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+    //if (Check_D_MediaPower())
+    //    return(ErrCode);
+    //
+    //if (Check_D_MediaFmt(fdoExt))
+    //    return(ErrCode);
+    //
+    //if (Check_D_MediaWP())
+    //    return(ErrCode);
+
+    if (Conv_D_MediaAddr(fdoExt, start))
+        return(ErrCode);
+
+    //ENE_Print("Media_D_WriteSector --- Sector = %x\n", Media.Sector);
+    if (Check_D_FirstSect())
+    {
+        if (Media_D_CopyBlockHead(fdoExt))
+        {
+            ErrCode = ERR_WriteFault;
+            return(ErrCode);
+        }
+    }
+
+    while(1)
+    {
+        if (!Check_D_FirstSect())
+        {
+            if (Assign_D_WriteBlock())
+                return(ErrCode);
+        }
+
+        len = Ssfdc.MaxSectors - Media.Sector;
+        if (count > len)
+           bn = len;
+        else
+           bn = count;
+        //for(i=0;i<SECTSIZE;i++)
+        //    SectBuf[i]=*buf++;
+
+        //if (Media_D_WriteOneSect(fdoExt, SectBuf))
+        if (Media_D_WriteOneSect(fdoExt, bn, buf))
+        {
+            ErrCode = ERR_WriteFault;
+            return(ErrCode);
+        }
+
+        Media.Sector += bn - 1;
+
+        if (!Check_D_LastSect())
+        {
+            if (Release_D_ReadBlock(fdoExt))
+
+            {    if (ErrCode==ERR_HwError)
+                {
+                    ErrCode = ERR_WriteFault;
+                    return(ErrCode);
+                }
+            }
+        }
+
+        count -= bn;
+
+        if (count<=0)
+            break;
+
+        buf += bn * SECTSIZE;
+
+        //if (--count<=0)
+        //    break;
+
+        if (Inc_D_MediaAddr(fdoExt))
+            return(ErrCode);
+    }
+
+    if (!Check_D_LastSect())
+        return(NO_ERROR);
+
+    if (Inc_D_MediaAddr(fdoExt))
+        return(ErrCode);
+
+    if (Media_D_CopyBlockTail(fdoExt))
+    {
+        ErrCode = ERR_WriteFault;
+        return(ErrCode);
+    }
+
+    return(NO_ERROR);
+}
+//
+////----- Media_D_EraseBlock() -------------------------------------------
+//int Media_D_EraseBlock(PFDO_DEVICE_EXTENSION fdoExt, DWORD start,WORD count)
+//{
+//    if (Check_D_MediaPower())
+//        return(ErrCode);
+//
+//    if (Check_D_MediaFmt(fdoExt))
+//        return(ErrCode);
+//
+//    if (Check_D_MediaWP())
+//        return(ErrCode);
+//
+//    if (Conv_D_MediaAddr(start))
+//        return(ErrCode);
+//
+//    while(Check_D_FirstSect()) {
+//        if (Inc_D_MediaAddr(fdoExt))
+//            return(ErrCode);
+//
+//        if (--count<=0)
+//            return(NO_ERROR);
+//    }
+//
+//    while(1) {
+//        if (!Check_D_LastSect())
+//            if (Media_D_EraseOneBlock())
+//                if (ErrCode==ERR_HwError)
+//                {
+//                    ErrCode = ERR_WriteFault;
+//                    return(ErrCode);
+//                }
+//
+//        if (Inc_D_MediaAddr(fdoExt))
+//            return(ErrCode);
+//
+//        if (--count<=0)
+//            return(NO_ERROR);
+//    }
+//}
+//
+////----- Media_D_EraseAll() ---------------------------------------------
+//int Media_D_EraseAll(PFDO_DEVICE_EXTENSION fdoExt)
+//{
+//    if (Check_D_MediaPower())
+//        return(ErrCode);
+//
+//    if (Check_D_MediaFmtForEraseAll(fdoExt))
+//        return(ErrCode);
+//
+//    if (Check_D_MediaWP())
+//        return(ErrCode);
+//
+//    if (Media_D_EraseAllBlock())
+//        return(ErrCode);
+//
+//    return(NO_ERROR);
+//}
+
+//SmartMedia Write Function for One Sector Write Mode
+//----- Media_D_OneSectWriteStart() ------------------------------------
+int Media_D_OneSectWriteStart(PFDO_DEVICE_EXTENSION fdoExt,DWORD start,BYTE *buf)
+{
+//  int i;
+//  SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+//  ADDRESS_T   bb = (ADDRESS_T) &Media;
+//
+//  //if (Check_D_MediaPower())
+//  //    return(ErrCode);
+//  //if (Check_D_MediaFmt(fdoExt))
+//  //    return(ErrCode);
+//  //if (Check_D_MediaWP())
+//  //    return(ErrCode);
+//  if (Conv_D_MediaAddr(fdoExt, start))
+//      return(ErrCode);
+//
+//  if (Check_D_FirstSect())
+//      if (Media_D_CopyBlockHead(fdoExt))
+//      {
+//          ErrCode = ERR_WriteFault;
+//          return(ErrCode);
+//      }
+//
+//  if (!Check_D_FirstSect())
+//      if (Assign_D_WriteBlock())
+//          return(ErrCode);
+//
+//  //for(i=0;i<SECTSIZE;i++)
+//  //    SectBuf[i]=*buf++;
+//
+//  //if (Media_D_WriteOneSect(fdoExt, SectBuf))
+//  if (Media_D_WriteOneSect(fdoExt, buf))
+//  {
+//      ErrCode = ERR_WriteFault;
+//      return(ErrCode);
+//  }
+//
+//  if (!Check_D_LastSect())
+//  {
+//      if (Release_D_ReadBlock(fdoExt))
+//          if (ErrCode==ERR_HwError)
+//          {
+//              ErrCode = ERR_WriteFault;
+//              return(ErrCode);
+//          }
+//  }
+
+    return(NO_ERROR);
+}
+
+//----- Media_D_OneSectWriteNext() -------------------------------------
+int Media_D_OneSectWriteNext(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf)
+{
+//  int i;
+//  SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+//  ADDRESS_T   bb = (ADDRESS_T) &Media;
+//
+//  if (Inc_D_MediaAddr(fdoExt))
+//      return(ErrCode);
+//
+//  if (!Check_D_FirstSect())
+//    if (Assign_D_WriteBlock())
+//      return(ErrCode);
+//
+//  //for(i=0;i<SECTSIZE;i++)
+//  //    SectBuf[i]=*buf++;
+//
+//  //if (Media_D_WriteOneSect(fdoExt, SectBuf))
+//  if (Media_D_WriteOneSect(fdoExt, buf))
+//  {
+//      ErrCode = ERR_WriteFault;
+//      return(ErrCode);
+//  }
+//
+//  if (!Check_D_LastSect())
+//  {
+//      if (Release_D_ReadBlock(fdoExt))
+//          if (ErrCode==ERR_HwError)
+//          {
+//              ErrCode = ERR_WriteFault;
+//              return(ErrCode);
+//          }
+//  }
+
+    return(NO_ERROR);
+}
+
+//----- Media_D_OneSectWriteFlush() ------------------------------------
+int Media_D_OneSectWriteFlush(PFDO_DEVICE_EXTENSION fdoExt)
+{
+    if (!Check_D_LastSect())
+        return(NO_ERROR);
+
+    if (Inc_D_MediaAddr(fdoExt))
+        return(ErrCode);
+
+    if (Media_D_CopyBlockTail(fdoExt))
+    {
+        ErrCode = ERR_WriteFault;
+        return(ErrCode);
+    }
+
+    return(NO_ERROR);
+}
+//
+////LED Tern On/Off Subroutine
+////----- SM_EnableLED() -----------------------------------------------
+//void SM_EnableLED(PFDO_DEVICE_EXTENSION fdoExt, BOOLEAN enable)
+//{
+//    if (fdoExt->Drive_IsSWLED)
+//    {
+//        if (enable)
+//           Led_D_TernOn();
+//        else
+//           Led_D_TernOff();
+//    }
+//}
+//
+////----- Led_D_TernOn() -------------------------------------------------
+//void Led_D_TernOn(void)
+//{
+//    if (Check_D_CardStsChg())
+//        MediaChange=ERROR;
+//
+//    Cnt_D_LedOn();
+//}
+//
+////----- Led_D_TernOff() ------------------------------------------------
+//void Led_D_TernOff(void)
+//{
+//    if (Check_D_CardStsChg())
+//        MediaChange=ERROR;
+//
+//    Cnt_D_LedOff();
+//}
+//
+////SmartMedia Logical Format Subroutine
+////----- Check_D_LogCHS() -----------------------------------------------
+//int Check_D_LogCHS(WORD *c,BYTE *h,BYTE *s)
+//{
+//    switch(Ssfdc.Model) {
+//        case SSFDC1MB:   *c=125; *h= 4; *s= 4; break;
+//        case SSFDC2MB:   *c=125; *h= 4; *s= 8; break;
+//        case SSFDC4MB:   *c=250; *h= 4; *s= 8; break;
+//        case SSFDC8MB:   *c=250; *h= 4; *s=16; break;
+//        case SSFDC16MB:  *c=500; *h= 4; *s=16; break;
+//        case SSFDC32MB:  *c=500; *h= 8; *s=16; break;
+//        case SSFDC64MB:  *c=500; *h= 8; *s=32; break;
+//        case SSFDC128MB: *c=500; *h=16; *s=32; break;
+//        default:         *c= 0;  *h= 0; *s= 0; ErrCode = ERR_NoSmartMedia;    return(ERROR);
+//    }
+//
+//    return(SUCCESS);
+//}
+//
+////Power Controll & Media Exist Check Subroutine
+////----- Initialize_D_Media() -------------------------------------------
+//void Initialize_D_Media(void)
+//{
+//    ErrCode      = NO_ERROR;
+//    MediaChange  = ERROR;
+//    SectCopyMode = COMPLETED;
+//    Cnt_D_Reset();
+//}
+//
+////----- PowerOff_D_Media() ---------------------------------------------
+//void PowerOff_D_Media(void)
+//{
+//    Cnt_D_PowerOff();
+//}
+//
+////----- Check_D_MediaPower() -------------------------------------------
+//int Check_D_MediaPower(void)
+//{
+//    //usleep(56*1024);
+//    if (Check_D_CardStsChg())
+//        MediaChange = ERROR;
+//    //usleep(56*1024);
+//    if ((!Check_D_CntPower())&&(!MediaChange))  // Â¦Â³ power & Media Â¨S³Q change, Â«h return success
+//        return(SUCCESS);
+//    //usleep(56*1024);
+//
+//    if (Check_D_CardExist())                    // Check if card is not exist, return err
+//    {
+//        ErrCode        = ERR_NoSmartMedia;
+//        MediaChange = ERROR;
+//        return(ERROR);
+//    }
+//    //usleep(56*1024);
+//    if (Cnt_D_PowerOn())
+//    {
+//        ErrCode        = ERR_NoSmartMedia;
+//        MediaChange = ERROR;
+//        return(ERROR);
+//    }
+//    //usleep(56*1024);
+//    Ssfdc_D_Reset(fdoExt);
+//    //usleep(56*1024);
+//    return(SUCCESS);
+//}
+//
+////-----Check_D_MediaExist() --------------------------------------------
+//int Check_D_MediaExist(void)
+//{
+//    if (Check_D_CardStsChg())
+//        MediaChange = ERROR;
+//
+//    if (!Check_D_CardExist())
+//    {
+//        if (!MediaChange)
+//            return(SUCCESS);
+//
+//        ErrCode = ERR_ChangedMedia;
+//        return(ERROR);
+//    }
+//
+//    ErrCode = ERR_NoSmartMedia;
+//
+//    return(ERROR);
+//}
+//
+////----- Check_D_MediaWP() ----------------------------------------------
+//int Check_D_MediaWP(void)
+//{
+//    if (Ssfdc.Attribute &MWP)
+//    {
+//        ErrCode = ERR_WrtProtect;
+//        return(ERROR);
+//    }
+//
+//    return(SUCCESS);
+//}
+*/
+//SmartMedia Physical Format Test Subroutine
+//----- Check_D_MediaFmt() ---------------------------------------------
+int Check_D_MediaFmt(struct us_data *us)
+{
+       printk("Check_D_MediaFmt\n");
+       //ULONG i,j, result=FALSE, zone,block;
+
+       //usleep(56*1024);
+       if (!MediaChange)
+               return(SUCCESS);
+
+       MediaChange  = ERROR;
+       SectCopyMode = COMPLETED;
+
+       //usleep(56*1024);
+       if (Set_D_PhyFmtValue(us))
+       {
+               ErrCode = ERR_UnknownMedia;
+               return(ERROR);
+       }
+       
+       //usleep(56*1024);
+       if (Search_D_CIS(us))
+       {
+               ErrCode = ERR_IllegalFmt;
+               return(ERROR);
+       }
+
+
+    MediaChange = SUCCESS;
+    return(SUCCESS);
+}
+/*
+////----- Check_D_BlockIsFull() ----------------------------------
+//void Check_D_BlockIsFull()
+//{
+//    ULONG i, block;
+//
+//    if (IsXDCompliance || IsSSFDCCompliance)
+//    {
+//       // If the blocks are full then return write-protect.
+//       block = Ssfdc.MaxBlocks/8;
+//       for (Media.Zone=0; Media.Zone<Ssfdc.MaxZones; Media.Zone++)
+//       {
+//           if (Log2Phy[Media.Zone]==NULL)
+//           {
+//               if (Make_D_LogTable())
+//               {
+//                   ErrCode = ERR_IllegalFmt;
+//                   return;
+//               }
+//           }
+//
+//           for (i=0; i<block; i++)
+//           {
+//               if (Assign[Media.Zone][i] != 0xFF)
+//                  return;
+//           }
+//       }
+//       Ssfdc.Attribute |= WP;
+//    }
+//}
+//
+//
+////----- Check_D_MediaFmtForEraseAll() ----------------------------------
+//int Check_D_MediaFmtForEraseAll(PFDO_DEVICE_EXTENSION fdoExt)
+//{
+//    MediaChange  = ERROR;
+//    SectCopyMode = COMPLETED;
+//
+//    if (Set_D_PhyFmtValue(fdoExt))
+//    {
+//        ErrCode = ERR_UnknownMedia;
+//        return(ERROR);
+//    }
+//
+//    if (Search_D_CIS(fdoExt))
+//    {
+//        ErrCode = ERR_IllegalFmt;
+//        return(ERROR);
+//    }
+//
+//    return(SUCCESS);
+//}
+*/
+//SmartMedia Physical Address Controll Subroutine
+//----- Conv_D_MediaAddr() ---------------------------------------------
+int Conv_D_MediaAddr(struct us_data *us, DWORD addr)
+{
+       DWORD temp;
+       //ULONG  zz;
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       temp           = addr/Ssfdc.MaxSectors;
+       Media.Zone     = (BYTE) (temp/Ssfdc.MaxLogBlocks);
+
+       if (Log2Phy[Media.Zone]==NULL)
+       {
+               if (Make_D_LogTable(us))
+               {
+                       ErrCode = ERR_IllegalFmt;
+                       return(ERROR);
+               }
+       }
+
+       Media.Sector   = (BYTE) (addr%Ssfdc.MaxSectors);
+       Media.LogBlock = (WORD) (temp%Ssfdc.MaxLogBlocks);
+
+       if (Media.Zone<Ssfdc.MaxZones)
+       {
+               Clr_D_RedundantData(Redundant);
+               Set_D_LogBlockAddr(Redundant);
+               Media.PhyBlock = Log2Phy[Media.Zone][Media.LogBlock];
+               return(SUCCESS);
+       }
+
+       ErrCode = ERR_OutOfLBA;
+       return(ERROR);
+}
+
+//----- Inc_D_MediaAddr() ----------------------------------------------
+int Inc_D_MediaAddr(struct us_data *us)
+{
+       WORD        LogBlock = Media.LogBlock;
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       if (++Media.Sector<Ssfdc.MaxSectors)
+               return(SUCCESS);
+
+       if (Log2Phy[Media.Zone]==NULL)
+       {
+               if (Make_D_LogTable(us))
+               {
+                       ErrCode = ERR_IllegalFmt;
+                       return(ERROR);
+               }
+       }
+
+       Media.Sector=0;
+       Media.LogBlock = LogBlock;
+
+       if (++Media.LogBlock<Ssfdc.MaxLogBlocks)
+       {
+               Clr_D_RedundantData(Redundant);
+               Set_D_LogBlockAddr(Redundant);
+               Media.PhyBlock=Log2Phy[Media.Zone][Media.LogBlock];
+               return(SUCCESS);
+       }
+
+       Media.LogBlock=0;
+
+       if (++Media.Zone<Ssfdc.MaxZones)
+       {
+               if (Log2Phy[Media.Zone]==NULL)
+               {
+                       if (Make_D_LogTable(us))
+                       {
+                               ErrCode = ERR_IllegalFmt;
+                               return(ERROR);
+                       }
+               }
+
+               Media.LogBlock = 0;
+
+               Clr_D_RedundantData(Redundant);
+               Set_D_LogBlockAddr(Redundant);
+               Media.PhyBlock=Log2Phy[Media.Zone][Media.LogBlock];
+               return(SUCCESS);
+       }
+
+       Media.Zone=0;
+       ErrCode = ERR_OutOfLBA;
+
+       return(ERROR);
+}
+/*
+//----- Check_D_FirstSect() --------------------------------------------
+int Check_D_FirstSect(void)
+{
+    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+    ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+    if (!Media.Sector)
+        return(SUCCESS);
+
+    return(ERROR);
+}
+
+//----- Check_D_LastSect() ---------------------------------------------
+int Check_D_LastSect(void)
+{
+    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+    ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+    if (Media.Sector<(Ssfdc.MaxSectors-1))
+        return(ERROR);
+
+    return(SUCCESS);
+}
+*/
+//SmartMedia Read/Write Subroutine with Retry
+//----- Media_D_ReadOneSect() ------------------------------------------
+int Media_D_ReadOneSect(struct us_data *us, WORD count, BYTE *buf)
+{
+       DWORD err, retry;
+
+       if (!Read_D_PhyOneSect(us, count, buf))
+               return(SUCCESS);
+       if (ErrCode==ERR_HwError)
+               return(ERROR);
+       if (ErrCode==ERR_DataStatus)
+               return(ERROR);
+
+#ifdef RDERR_REASSIGN
+       if (Ssfdc.Attribute &MWP)
+       {
+               if (ErrCode==ERR_CorReadErr)
+                       return(SUCCESS);
+               return(ERROR);
+       }
+
+       err=ErrCode;
+       for(retry=0; retry<2; retry++)
+       {
+               if (Copy_D_BlockAll(us, (err==ERR_EccReadErr)?REQ_FAIL:REQ_ERASE))
+               {
+                       if (ErrCode==ERR_HwError)
+                               return(ERROR);
+                       continue;
+               }
+
+               ErrCode = err;
+               if (ErrCode==ERR_CorReadErr)
+                       return(SUCCESS);
+               return(ERROR);
+       }
+
+       MediaChange = ERROR;
+#else
+       if (ErrCode==ERR_CorReadErr) return(SUCCESS);
+#endif
+
+       return(ERROR);
+}
+/*
+//----- Media_D_WriteOneSect() -----------------------------------------
+int Media_D_WriteOneSect(PFDO_DEVICE_EXTENSION fdoExt, WORD count, BYTE *buf)
+{
+    DWORD retry;
+    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+    ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+    if (!Write_D_PhyOneSect(fdoExt, count, buf))
+        return(SUCCESS);
+    if (ErrCode==ERR_HwError)
+        return(ERROR);
+
+    for(retry=1; retry<2; retry++)
+    {
+        if (Reassign_D_BlockHead(fdoExt))
+        {
+            if (ErrCode==ERR_HwError)
+                return(ERROR);
+            continue;
+        }
+
+        if (!Write_D_PhyOneSect(fdoExt, count, buf))
+            return(SUCCESS);
+        if (ErrCode==ERR_HwError)
+            return(ERROR);
+    }
+
+    if (Release_D_WriteBlock(fdoExt))
+        return(ERROR);
+
+    ErrCode        = ERR_WriteFault;
+    MediaChange = ERROR;
+    return(ERROR);
+}
+
+//SmartMedia Data Copy Subroutine with Retry
+//----- Media_D_CopyBlockHead() ----------------------------------------
+int Media_D_CopyBlockHead(PFDO_DEVICE_EXTENSION fdoExt)
+{
+    DWORD retry;
+
+    for(retry=0; retry<2; retry++)
+    {
+        if (!Copy_D_BlockHead(fdoExt))
+            return(SUCCESS);
+        if (ErrCode==ERR_HwError)
+            return(ERROR);
+    }
+
+    MediaChange = ERROR;
+    return(ERROR);
+}
+
+//----- Media_D_CopyBlockTail() ----------------------------------------
+int Media_D_CopyBlockTail(PFDO_DEVICE_EXTENSION fdoExt)
+{
+    DWORD retry;
+
+    if (!Copy_D_BlockTail(fdoExt))
+        return(SUCCESS);
+    if (ErrCode==ERR_HwError)
+        return(ERROR);
+
+    for(retry=1; retry<2; retry++)
+    {
+        if (Reassign_D_BlockHead(fdoExt))
+        {
+            if (ErrCode==ERR_HwError)
+                return(ERROR);
+            continue;
+        }
+
+        if (!Copy_D_BlockTail(fdoExt))
+            return(SUCCESS);
+        if (ErrCode==ERR_HwError)
+            return(ERROR);
+    }
+
+    if (Release_D_WriteBlock(fdoExt))
+        return(ERROR);
+
+    ErrCode        = ERR_WriteFault;
+    MediaChange = ERROR;
+    return(ERROR);
+}
+//
+////----- Media_D_EraseOneBlock() ----------------------------------------
+//int Media_D_EraseOneBlock(void)
+//{
+//    WORD        LogBlock = Media.LogBlock;
+//    WORD        PhyBlock = Media.PhyBlock;
+//    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+//    ADDRESS_T   bb = (ADDRESS_T) &Media;
+//
+//    if (Media.PhyBlock==NO_ASSIGN)
+//        return(SUCCESS);
+//
+//    if (Log2Phy[Media.Zone]==NULL)
+//    {
+//        if (Make_D_LogTable())
+//        {
+//            ErrCode = ERR_IllegalFmt;
+//            return(ERROR);
+//        }
+//    }
+//    Media.LogBlock = LogBlock;
+//    Media.PhyBlock = PhyBlock;
+//
+//    Log2Phy[Media.Zone][Media.LogBlock]=NO_ASSIGN;
+//
+//    if (Erase_D_PhyOneBlock(fdoExt))
+//    {
+//        if (ErrCode==ERR_HwError)
+//            return(ERROR);
+//        if (MarkFail_D_PhyOneBlock())
+//            return(ERROR);
+//
+//        ErrCode = ERR_WriteFault;
+//        return(ERROR);
+//    }
+//
+//    Clr_D_Bit(Assign[Media.Zone],Media.PhyBlock);
+//    Media.PhyBlock=NO_ASSIGN;
+//    return(SUCCESS);
+//}
+//
+////SmartMedia Erase Subroutine
+////----- Media_D_EraseAllBlock() ----------------------------------------
+//int Media_D_EraseAllBlock(void)
+//{
+//    WORD cis=0;
+//
+//    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+//    ADDRESS_T   bb = (ADDRESS_T) &Media;
+//
+//    MediaChange = ERROR;
+//    Media.Sector   = 0;
+//
+//    for(Media.Zone=0; Media.Zone<Ssfdc.MaxZones; Media.Zone++)
+//        for(Media.PhyBlock=0; Media.PhyBlock<Ssfdc.MaxBlocks; Media.PhyBlock++) {
+//            if (Ssfdc_D_ReadRedtData(Redundant))
+//            {
+//                Ssfdc_D_Reset(fdoExt);
+//                return(ERROR);
+//            }
+//
+//            Ssfdc_D_Reset(fdoExt);
+//            if (!Check_D_FailBlock(Redundant))
+//            {
+//                if (cis)
+//                {
+//                    if (Ssfdc_D_EraseBlock(fdoExt))
+//                    {
+//                        ErrCode = ERR_HwError;
+//                        return(ERROR);
+//                    }
+//
+//                    if (Ssfdc_D_CheckStatus())
+//                    {
+//                        if (MarkFail_D_PhyOneBlock())
+//                            return(ERROR);
+//                    }
+//
+//                    continue;
+//                }
+//
+//                if (Media.PhyBlock!=CisArea.PhyBlock)
+//                {
+//                    ErrCode = ERR_IllegalFmt;
+//                    return(ERROR);
+//                }
+//
+//                cis++;
+//            }
+//
+//        }
+//    return(SUCCESS);
+//}
+*/
+//SmartMedia Physical Sector Data Copy Subroutine
+//----- Copy_D_BlockAll() ----------------------------------------------
+int Copy_D_BlockAll(struct us_data *us, DWORD mode)
+{
+       BYTE sect;
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       sect=Media.Sector;
+
+       if (Assign_D_WriteBlock())
+               return(ERROR);
+       if (mode==REQ_FAIL)
+               SectCopyMode=REQ_FAIL;
+
+       for(Media.Sector=0; Media.Sector<Ssfdc.MaxSectors; Media.Sector++)
+       {
+               if (Copy_D_PhyOneSect(us))
+               {
+                       if (ErrCode==ERR_HwError)
+                               return(ERROR);
+                       if (Release_D_WriteBlock(us))
+                               return(ERROR);
+
+                       ErrCode = ERR_WriteFault;
+                       Media.PhyBlock=ReadBlock;
+                       Media.Sector=sect;
+
+                       return(ERROR);
+               }
+       }
+
+       if (Release_D_ReadBlock(us))
+               return(ERROR);
+
+       Media.PhyBlock=WriteBlock;
+       Media.Sector=sect;
+       return(SUCCESS);
+}
+/*
+//----- Copy_D_BlockHead() ---------------------------------------------
+int Copy_D_BlockHead(PFDO_DEVICE_EXTENSION fdoExt)
+{
+    BYTE sect;
+    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+    ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+    sect=Media.Sector;
+    if (Assign_D_WriteBlock())
+        return(ERROR);
+
+    for(Media.Sector=0; Media.Sector<sect; Media.Sector++)
+    {
+        if (Copy_D_PhyOneSect(fdoExt))
+        {
+            if (ErrCode==ERR_HwError)
+                return(ERROR);
+            if (Release_D_WriteBlock(fdoExt))
+                return(ERROR);
+
+            ErrCode = ERR_WriteFault;
+            Media.PhyBlock=ReadBlock;
+            Media.Sector=sect;
+
+            return(ERROR);
+        }
+    }
+
+    Media.PhyBlock=WriteBlock;
+    Media.Sector=sect;
+    return(SUCCESS);
+}
+
+//----- Copy_D_BlockTail() ---------------------------------------------
+int Copy_D_BlockTail(PFDO_DEVICE_EXTENSION fdoExt)
+{
+    BYTE sect;
+    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+    ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+    for(sect=Media.Sector; Media.Sector<Ssfdc.MaxSectors; Media.Sector++)
+    {
+        if (Copy_D_PhyOneSect(fdoExt))
+        {
+            if (ErrCode==ERR_HwError)
+                return(ERROR);
+
+            Media.PhyBlock=WriteBlock;
+            Media.Sector=sect;
+
+            return(ERROR);
+        }
+    }
+
+    if (Release_D_ReadBlock(fdoExt))
+        return(ERROR);
+
+    Media.PhyBlock=WriteBlock;
+    Media.Sector=sect;
+    return(SUCCESS);
+}
+
+//----- Reassign_D_BlockHead() -----------------------------------------
+int Reassign_D_BlockHead(PFDO_DEVICE_EXTENSION fdoExt)
+{
+    DWORD  mode;
+    WORD   block;
+    BYTE   sect;
+    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+    ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+    mode=SectCopyMode;
+    block=ReadBlock;
+    sect=Media.Sector;
+
+    if (Assign_D_WriteBlock())
+        return(ERROR);
+
+    SectCopyMode=REQ_FAIL;
+
+    for(Media.Sector=0; Media.Sector<sect; Media.Sector++)
+    {
+        if (Copy_D_PhyOneSect(fdoExt))
+        {
+            if (ErrCode==ERR_HwError)
+                return(ERROR);
+            if (Release_D_WriteBlock(fdoExt))
+                return(ERROR);
+
+            ErrCode = ERR_WriteFault;
+            SectCopyMode=mode;
+            WriteBlock=ReadBlock;
+            ReadBlock=block;
+            Media.Sector=sect;
+            Media.PhyBlock=WriteBlock;
+
+            return(ERROR);
+        }
+    }
+
+    if (Release_D_ReadBlock(fdoExt))
+        return(ERROR);
+
+    SectCopyMode=mode;
+    ReadBlock=block;
+    Media.Sector=sect;
+    Media.PhyBlock=WriteBlock;
+    return(SUCCESS);
+}
+*/
+//SmartMedia Physical Block Assign/Release Subroutine
+//----- Assign_D_WriteBlock() ------------------------------------------
+int Assign_D_WriteBlock(void)
+{
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+       ReadBlock=Media.PhyBlock;
+
+       for(WriteBlock=AssignStart[Media.Zone]; WriteBlock<Ssfdc.MaxBlocks; WriteBlock++)
+       {
+               if (!Chk_D_Bit(Assign[Media.Zone],WriteBlock))
+               {
+                       Set_D_Bit(Assign[Media.Zone],WriteBlock);
+                       AssignStart[Media.Zone]=WriteBlock+1;
+                       Media.PhyBlock=WriteBlock;
+                       SectCopyMode=REQ_ERASE;
+                       //ErrXDCode = NO_ERROR;
+                       return(SUCCESS);
+               }
+       }
+
+       for(WriteBlock=0; WriteBlock<AssignStart[Media.Zone]; WriteBlock++)
+       {
+               if (!Chk_D_Bit(Assign[Media.Zone],WriteBlock))
+               {
+                       Set_D_Bit(Assign[Media.Zone],WriteBlock);
+                       AssignStart[Media.Zone]=WriteBlock+1;
+                       Media.PhyBlock=WriteBlock;
+                       SectCopyMode=REQ_ERASE;
+                       //ErrXDCode = NO_ERROR;
+                       return(SUCCESS);
+               }
+       }
+
+       WriteBlock=NO_ASSIGN;
+       ErrCode = ERR_WriteFault;
+       // For xD test
+       //Ssfdc.Attribute |= WP;
+       //ErrXDCode = ERR_WrtProtect;
+       return(ERROR);
+}
+
+//----- Release_D_ReadBlock() ------------------------------------------
+int Release_D_ReadBlock(struct us_data *us)
+{
+       DWORD mode;
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       mode=SectCopyMode;
+       SectCopyMode=COMPLETED;
+
+       if (mode==COMPLETED)
+               return(SUCCESS);
+
+       Log2Phy[Media.Zone][Media.LogBlock]=WriteBlock;
+       Media.PhyBlock=ReadBlock;
+
+       if (Media.PhyBlock==NO_ASSIGN)
+       {
+               Media.PhyBlock=WriteBlock;
+               return(SUCCESS);
+       }
+
+       if (mode==REQ_ERASE)
+       {
+               if (Erase_D_PhyOneBlock(us))
+               {
+                       if (ErrCode==ERR_HwError) return(ERROR);
+                       if (MarkFail_D_PhyOneBlock(us)) return(ERROR);
+               }
+               else
+                       Clr_D_Bit(Assign[Media.Zone],Media.PhyBlock);
+       }
+       else if (MarkFail_D_PhyOneBlock(us))
+               return(ERROR);
+
+       Media.PhyBlock=WriteBlock;
+       return(SUCCESS);
+}
+
+//----- Release_D_WriteBlock() -----------------------------------------
+int Release_D_WriteBlock(struct us_data *us)
+{
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+       SectCopyMode=COMPLETED;
+       Media.PhyBlock=WriteBlock;
+
+       if (MarkFail_D_PhyOneBlock(us))
+               return(ERROR);
+
+       Media.PhyBlock=ReadBlock;
+       return(SUCCESS);
+}
+
+//SmartMedia Physical Sector Data Copy Subroutine
+//----- Copy_D_PhyOneSect() --------------------------------------------
+int Copy_D_PhyOneSect(struct us_data *us)
+{
+       int           i;
+       DWORD  err, retry;
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       //printk("Copy_D_PhyOneSect --- Secotr = %x\n", Media.Sector);
+       if (ReadBlock!=NO_ASSIGN)
+       {
+               Media.PhyBlock=ReadBlock;
+               for(retry=0; retry<2; retry++)
+               {
+                       if (retry!=0)
+                       {
+                               Ssfdc_D_Reset(us);
+                               if (Ssfdc_D_ReadCisSect(us,WorkBuf,WorkRedund))
+                               { ErrCode = ERR_HwError; MediaChange=ERROR; return(ERROR); }
+
+                               if (Check_D_CISdata(WorkBuf,WorkRedund))
+                               { ErrCode = ERR_HwError; MediaChange=ERROR; return(ERROR); }
+                       }
+
+                       if (Ssfdc_D_ReadSect(us,WorkBuf,WorkRedund))
+                       { ErrCode = ERR_HwError; MediaChange=ERROR; return(ERROR); }
+                       if (Check_D_DataStatus(WorkRedund))
+                       { err=ERROR; break; }
+                       if (!Check_D_ReadError(WorkRedund))
+                       { err=SUCCESS; break; }
+                       if (!Check_D_Correct(WorkBuf,WorkRedund))
+                       { err=SUCCESS; break; }
+
+                       err=ERROR;
+                       SectCopyMode=REQ_FAIL;
+               }
+       }
+       else
+       {
+               err=SUCCESS;
+               for(i=0; i<SECTSIZE; i++)
+                       WorkBuf[i]=DUMMY_DATA;
+               Clr_D_RedundantData(WorkRedund);
+       }
+
+       Set_D_LogBlockAddr(WorkRedund);
+       if (err==ERROR)
+       {
+               Set_D_RightECC(WorkRedund);
+               Set_D_DataStaus(WorkRedund);
+       }
+
+       Media.PhyBlock=WriteBlock;
+
+       if (Ssfdc_D_WriteSectForCopy(us, WorkBuf, WorkRedund))
+       { ErrCode = ERR_HwError; MediaChange=ERROR; return(ERROR); }
+       if (Ssfdc_D_CheckStatus())
+       { ErrCode = ERR_WriteFault; return(ERROR); }
+
+       Media.PhyBlock=ReadBlock;
+       return(SUCCESS);
+}
+
+//SmartMedia Physical Sector Read/Write/Erase Subroutine
+//----- Read_D_PhyOneSect() --------------------------------------------
+int Read_D_PhyOneSect(struct us_data *us, WORD count, BYTE *buf)
+{
+       int           i;
+       DWORD  retry;
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       if (Media.PhyBlock==NO_ASSIGN)
+       {
+               for(i=0; i<SECTSIZE; i++)
+                       *buf++=DUMMY_DATA;
+               return(SUCCESS);
+       }
+
+       for(retry=0; retry<2; retry++)
+       {
+               if (retry!=0)
+               {
+                       Ssfdc_D_Reset(us);
+
+                       if (Ssfdc_D_ReadCisSect(us,WorkBuf,WorkRedund))
+                       { ErrCode = ERR_HwError; MediaChange=ERROR; return(ERROR); }
+                       if (Check_D_CISdata(WorkBuf,WorkRedund))
+                       { ErrCode = ERR_HwError; MediaChange=ERROR; return(ERROR); }
+               }
+
+               //if (Ssfdc_D_ReadSect(fdoExt,buf,Redundant))
+               if (Ssfdc_D_ReadBlock(us,count,buf,Redundant))
+               { ErrCode = ERR_HwError; MediaChange=ERROR; return(ERROR); }
+               if (Check_D_DataStatus(Redundant))
+               { ErrCode = ERR_DataStatus; return(ERROR); }
+
+               if (!Check_D_ReadError(Redundant))
+                       return(SUCCESS);
+
+               if (!Check_D_Correct(buf,Redundant))
+               { ErrCode = ERR_CorReadErr; return(ERROR); }
+       }
+
+       ErrCode = ERR_EccReadErr;
+       return(ERROR);
+}
+/*
+//----- Write_D_PhyOneSect() -------------------------------------------
+int Write_D_PhyOneSect(PFDO_DEVICE_EXTENSION fdoExt, WORD count, BYTE *buf)
+{
+    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+    ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+    //if (Ssfdc_D_WriteSect(fdoExt,buf,Redundant))
+    if (Ssfdc_D_WriteBlock(fdoExt,count,buf,Redundant))
+    { ErrCode = ERR_HwError; MediaChange=ERROR; return(ERROR); }
+    if (Ssfdc_D_CheckStatus())
+    { ErrCode = ERR_WriteFault; return(ERROR); }
+
+    return(SUCCESS);
+}
+*/
+//----- Erase_D_PhyOneBlock() ------------------------------------------
+int Erase_D_PhyOneBlock(struct us_data *us)
+{
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       if (Ssfdc_D_EraseBlock(us))
+       { ErrCode = ERR_HwError; MediaChange=ERROR; return(ERROR); }
+       if (Ssfdc_D_CheckStatus())
+       { ErrCode = ERR_WriteFault; return(ERROR); }
+
+       return(SUCCESS);
+}
+
+//SmartMedia Physical Format Check Local Subroutine
+//----- Set_D_PhyFmtValue() --------------------------------------------
+int Set_D_PhyFmtValue(struct us_data *us)
+{
+//    PPDO_DEVICE_EXTENSION   pdoExt;
+//    BYTE      idcode[4];
+//    DWORD     UserDefData_1, UserDefData_2, Data, mask;
+//
+//    //if (!fdoExt->ChildDeviceObject)       return(ERROR);
+//    //pdoExt = fdoExt->ChildDeviceObject->DeviceExtension;
+//
+//    Ssfdc_D_ReadID(idcode, READ_ID_1);
+//
+    //if (Set_D_SsfdcModel(idcode[1]))
+    if (Set_D_SsfdcModel(us->SM_DeviceID))
+        return(ERROR);
+
+//    //Use Multi-function pin to differentiate SM and xD.
+//    UserDefData_1 = ReadPCIReg(fdoExt->BusID, fdoExt->DevID, fdoExt->FuncID, PCI_REG_USER_DEF) & 0x80;
+//    if (UserDefData_1)
+//    {
+//       if ( READ_PORT_BYTE(SM_REG_INT_STATUS) & 0x80 )      fdoExt->DiskType = DISKTYPE_XD;
+//       if ( READ_PORT_BYTE(SM_REG_INT_STATUS) & 0x40 )      fdoExt->DiskType = DISKTYPE_SM;
+//
+//       if ( IsXDCompliance && (fdoExt->DiskType == DISKTYPE_XD) )
+//       {
+//          Ssfdc_D_ReadID(idcode, READ_ID_3);
+//          if (idcode[2] != 0xB5)
+//             return(ERROR);
+//       }
+//    }
+//
+//    //Use GPIO to differentiate SM and xD.
+//    UserDefData_2 = ReadPCIReg(fdoExt->BusID, fdoExt->DevID, fdoExt->FuncID, PCI_REG_USER_DEF) >> 8;
+//    if ( UserDefData_2 )
+//    {
+//       Data = ReadPCIReg(fdoExt->BusID, fdoExt->DevID, 0, 0xAC);
+//
+//       mask = 1 << (UserDefData_2-1);
+//       // 1 : xD , 0 : SM
+//       if ( Data & mask)
+//          fdoExt->DiskType = DISKTYPE_XD;
+//       else
+//          fdoExt->DiskType = DISKTYPE_SM;
+//
+//       if ( IsXDCompliance && (fdoExt->DiskType == DISKTYPE_XD) )
+//       {
+//          Ssfdc_D_ReadID(idcode, READ_ID_3);
+//          if (idcode[2] != 0xB5)
+//             return(ERROR);
+//       }
+//    }
+//
+//    if ( !(UserDefData_1 | UserDefData_2) )
+//    {
+//      // Use UserDefine Register to differentiate SM and xD.
+//      Ssfdc_D_ReadID(idcode, READ_ID_3);
+//
+//      if (idcode[2] == 0xB5)
+//         fdoExt->DiskType = DISKTYPE_XD;
+//      else
+//      {
+//          if (!IsXDCompliance)
+//             fdoExt->DiskType = DISKTYPE_SM;
+//          else
+//             return(ERROR);
+//      }
+//
+//      if (fdoExt->UserDef_DiskType == 0x04)  fdoExt->DiskType = DISKTYPE_XD;
+//      if (fdoExt->UserDef_DiskType == 0x08)  fdoExt->DiskType = DISKTYPE_SM;
+//    }
+//
+//    if (!fdoExt->UserDef_DisableWP)
+//    {
+//       if (fdoExt->DiskType == DISKTYPE_SM)
+//       {
+//           if (Check_D_SsfdcWP())
+//              Ssfdc.Attribute|=WP;
+//       }
+//    }
+
+    return(SUCCESS);
+}
+
+//----- Search_D_CIS() -------------------------------------------------
+int Search_D_CIS(struct us_data *us)
+{
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       Media.Zone=0; Media.Sector=0;
+
+       for (Media.PhyBlock=0; Media.PhyBlock<(Ssfdc.MaxBlocks-Ssfdc.MaxLogBlocks-1); Media.PhyBlock++)
+       {
+               if (Ssfdc_D_ReadRedtData(us, Redundant))
+               {
+                       Ssfdc_D_Reset(us);
+                       return(ERROR);
+               }
+
+               if (!Check_D_FailBlock(Redundant))
+                       break;
+       }
+
+       if (Media.PhyBlock==(Ssfdc.MaxBlocks-Ssfdc.MaxLogBlocks-1))
+       {
+               Ssfdc_D_Reset(us);
+               return(ERROR);
+       }
+
+       while (Media.Sector<CIS_SEARCH_SECT)
+       {
+               if (Media.Sector)
+               {
+                       if (Ssfdc_D_ReadRedtData(us, Redundant))
+                       {
+                               Ssfdc_D_Reset(us);
+                               return(ERROR);
+                       }
+               }
+               if (!Check_D_DataStatus(Redundant))
+               {
+                       if (Ssfdc_D_ReadSect(us,WorkBuf,Redundant))
+                       {
+                               Ssfdc_D_Reset(us);
+                               return(ERROR);
+                       }
+
+                       if (Check_D_CISdata(WorkBuf,Redundant))
+                       {
+                               Ssfdc_D_Reset(us);
+                               return(ERROR);
+                       }
+
+                       CisArea.PhyBlock=Media.PhyBlock;
+                       CisArea.Sector=Media.Sector;
+                       Ssfdc_D_Reset(us);
+                       return(SUCCESS);
+               }
+
+               Media.Sector++;
+       }
+
+       Ssfdc_D_Reset(us);
+       return(ERROR);
+}
+
+//----- Make_D_LogTable() ----------------------------------------------
+int Make_D_LogTable(struct us_data *us)
+{
+       WORD  phyblock,logblock;
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       if (Log2Phy[Media.Zone]==NULL)
+       {
+               Log2Phy[Media.Zone] = kmalloc(MAX_LOGBLOCK*sizeof(WORD), GFP_KERNEL);
+               //printk("ExAllocatePool Zone = %x, Addr = %x\n", Media.Zone, Log2Phy[Media.Zone]);
+               if (Log2Phy[Media.Zone]==NULL)
+                       return(ERROR);
+       }
+
+       Media.Sector=0;
+
+       //for(Media.Zone=0; Media.Zone<MAX_ZONENUM; Media.Zone++)
+       //for(Media.Zone=0; Media.Zone<Ssfdc.MaxZones; Media.Zone++)
+       {
+               //printk("Make_D_LogTable --- MediaZone = 0x%x\n", Media.Zone);
+               for(Media.LogBlock=0; Media.LogBlock<Ssfdc.MaxLogBlocks; Media.LogBlock++)
+                       Log2Phy[Media.Zone][Media.LogBlock]=NO_ASSIGN;
+
+               for(Media.PhyBlock=0; Media.PhyBlock<(MAX_BLOCKNUM/8); Media.PhyBlock++)
+                       Assign[Media.Zone][Media.PhyBlock]=0x00;
+
+               for(Media.PhyBlock=0; Media.PhyBlock<Ssfdc.MaxBlocks; Media.PhyBlock++)
+               {
+                       if ((!Media.Zone) && (Media.PhyBlock<=CisArea.PhyBlock))
+                       {
+                               Set_D_Bit(Assign[Media.Zone],Media.PhyBlock);
+                               continue;
+                       }
+
+                       if (Ssfdc_D_ReadRedtData(us, Redundant))
+                       { Ssfdc_D_Reset(us); return(ERROR); }
+
+                       if (!Check_D_DataBlank(Redundant))
+                               continue;
+
+                       Set_D_Bit(Assign[Media.Zone],Media.PhyBlock);
+
+                       if (Check_D_FailBlock(Redundant))
+                               continue;
+
+                       //if (Check_D_DataStatus(Redundant))
+                       //    continue;
+
+                       if (Load_D_LogBlockAddr(Redundant))
+                               continue;
+
+                       if (Media.LogBlock>=Ssfdc.MaxLogBlocks)
+                               continue;
+
+                       if (Log2Phy[Media.Zone][Media.LogBlock]==NO_ASSIGN)
+                       {
+                               Log2Phy[Media.Zone][Media.LogBlock]=Media.PhyBlock;
+                               continue;
+                       }
+
+                       phyblock     = Media.PhyBlock;
+                       logblock     = Media.LogBlock;
+                       Media.Sector = (BYTE)(Ssfdc.MaxSectors-1);
+
+                       if (Ssfdc_D_ReadRedtData(us, Redundant))
+                       { Ssfdc_D_Reset(us); return(ERROR); }
+
+                       if (!Load_D_LogBlockAddr(Redundant))
+                       {
+                               if (Media.LogBlock==logblock)
+                               {
+                                       Media.PhyBlock=Log2Phy[Media.Zone][logblock];
+
+                                       if (Ssfdc_D_ReadRedtData(us, Redundant))
+                                       { Ssfdc_D_Reset(us); return(ERROR); }
+
+                                       Media.PhyBlock=phyblock;
+
+                                       if (!Load_D_LogBlockAddr(Redundant))
+                                       {
+                                               if (Media.LogBlock!=logblock)
+                                               {
+                                                       Media.PhyBlock=Log2Phy[Media.Zone][logblock];
+                                                       Log2Phy[Media.Zone][logblock]=phyblock;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               Media.PhyBlock=Log2Phy[Media.Zone][logblock];
+                                               Log2Phy[Media.Zone][logblock]=phyblock;
+                                       }
+                               }
+                       }
+
+                       Media.Sector=0;
+
+// here Not yet
+//#ifdef L2P_ERR_ERASE
+//                     if (!(Ssfdc.Attribute &MWP))
+//                     {
+//                             Ssfdc_D_Reset(fdoExt);
+//                             if (Ssfdc_D_EraseBlock(fdoExt))
+//                                     return(ERROR);
+//
+//                             if (Ssfdc_D_CheckStatus())
+//                             {
+//                                     if (MarkFail_D_PhyOneBlock())
+//                                             return(ERROR);
+//                             }
+//                             else
+//                                     Clr_D_Bit(Assign[Media.Zone],Media.PhyBlock);
+//                     }
+//#else
+//                     Ssfdc.Attribute|=MWP;
+//#endif
+                       Media.PhyBlock=phyblock;
+
+               } // End for (Media.PhyBlock<Ssfdc.MaxBlocks)
+
+               AssignStart[Media.Zone]=0;
+
+       } // End for (Media.Zone<MAX_ZONENUM)
+
+       Ssfdc_D_Reset(us);
+       return(SUCCESS);
+}
+
+//----- MarkFail_D_PhyOneBlock() ---------------------------------------
+int MarkFail_D_PhyOneBlock(struct us_data *us)
+{
+       BYTE sect;
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       sect=Media.Sector;
+       Set_D_FailBlock(WorkRedund);
+       //Ssfdc_D_WriteRedtMode();
+
+       for(Media.Sector=0; Media.Sector<Ssfdc.MaxSectors; Media.Sector++)
+       {
+               if (Ssfdc_D_WriteRedtData(us, WorkRedund))
+               {
+                       Ssfdc_D_Reset(us);
+                       Media.Sector   = sect;
+                       ErrCode        = ERR_HwError;
+                       MediaChange = ERROR;
+                       return(ERROR);
+               } // NO Status Check
+       }
+
+       Ssfdc_D_Reset(us);
+       Media.Sector=sect;
+       return(SUCCESS);
+}
+/*
+//
+////----- SM_Init() ----------------------------------------------------
+//void SM_Init(void)
+//{
+//    _Hw_D_ClrIntCardChg();
+//    _Hw_D_SetIntMask();
+//    // For DMA Interrupt
+//    _Hw_D_ClrDMAIntCardChg();
+//    _Hw_D_SetDMAIntMask();
+//}
+//
+////----- Media_D_EraseAllRedtData() -----------------------------------
+//int Media_D_EraseAllRedtData(DWORD Index, BOOLEAN CheckBlock)
+//{
+//    BYTE    i;
+//
+//    if (Check_D_MediaPower())
+//        return(ErrCode);
+//
+//    if (Check_D_MediaWP())
+//        return(ErrCode);
+//
+//    for (i=0; i<REDTSIZE; i++)
+//        WorkRedund[i] = 0xFF;
+//
+//    Media.Zone = (BYTE)Index;
+//    for (Media.PhyBlock=0; Media.PhyBlock<Ssfdc.MaxBlocks; Media.PhyBlock++)
+//    {
+//        if ((!Media.Zone) && (Media.PhyBlock<=CisArea.PhyBlock))
+//            continue;
+//
+//        if (Ssfdc_D_EraseBlock(fdoExt))
+//        {
+//            ErrCode = ERR_HwError;
+//            return(ERROR);
+//        }
+//
+//        for(Media.Sector=0; Media.Sector<Ssfdc.MaxSectors; Media.Sector++)
+//        {
+//            Ssfdc_D_WriteRedtMode();
+//
+//            if (Ssfdc_D_WriteRedtData(WorkRedund))
+//            {
+//                Ssfdc_D_Reset(fdoExt);
+//                ErrCode        = ERR_HwError;
+//                MediaChange    = ERROR;
+//                return(ERROR);
+//            } // NO Status Check
+//        }
+//
+//        Ssfdc_D_Reset(fdoExt);
+//    }
+//
+//    Ssfdc_D_Reset(fdoExt);
+//
+//    return(SUCCESS);
+//}
+//
+////----- Media_D_GetMediaInfo() ---------------------------------------
+//DWORD Media_D_GetMediaInfo(PFDO_DEVICE_EXTENSION fdoExt, PIOCTL_MEDIA_INFO_IN pParamIn, PIOCTL_MEDIA_INFO_OUT pParamOut)
+//{
+//    pParamOut->ErrCode = STATUS_CMD_FAIL;
+//
+//    Init_D_SmartMedia();
+//
+//    if (Check_D_MediaPower())
+//        return (ErrCode==ERR_NoSmartMedia) ? STATUS_CMD_NO_MEDIA : STATUS_CMD_FAIL;
+//
+//    if (Set_D_PhyFmtValue(fdoExt))
+//        return STATUS_CMD_FAIL;
+//
+//    //usleep(56*1024);
+//    if (Search_D_CIS(fdoExt))
+//        return STATUS_CMD_FAIL;
+//
+//    if (Check_D_MediaWP())
+//        return STATUS_CMD_MEDIA_WP;
+//
+//    pParamOut->PageSize  = Ssfdc.MaxSectors;
+//    pParamOut->BlockSize = Ssfdc.MaxBlocks;
+//    pParamOut->ZoneSize  = Ssfdc.MaxZones;
+//
+//    return STATUS_CMD_SUCCESS;
+//}*/
diff --git a/drivers/staging/keucr/smilsub.c b/drivers/staging/keucr/smilsub.c
new file mode 100644 (file)
index 0000000..844b659
--- /dev/null
@@ -0,0 +1,1661 @@
+#include <linux/slab.h>
+#include "usb.h"
+#include "scsiglue.h"
+#include "transport.h"
+//#include "init.h"
+
+//#include "stdlib.h"
+//#include "EUCR6SK.h"
+#include "smcommon.h"
+#include "smil.h"
+
+void   _Set_D_SsfdcRdCmd     (BYTE);
+void   _Set_D_SsfdcRdAddr    (BYTE);
+void   _Set_D_SsfdcRdChip    (void);
+void   _Set_D_SsfdcRdStandby (void);
+void   _Start_D_SsfdcRdHwECC (void);
+void   _Stop_D_SsfdcRdHwECC  (void);
+void   _Load_D_SsfdcRdHwECC  (BYTE);
+void   _Set_D_SsfdcWrCmd     (BYTE);
+void   _Set_D_SsfdcWrAddr    (BYTE);
+void   _Set_D_SsfdcWrBlock   (void);
+void   _Set_D_SsfdcWrStandby (void);
+void   _Start_D_SsfdcWrHwECC (void);
+void   _Load_D_SsfdcWrHwECC  (BYTE);
+int    _Check_D_SsfdcBusy    (WORD);
+int    _Check_D_SsfdcStatus  (void);
+void   _Reset_D_SsfdcErr     (void);
+void   _Read_D_SsfdcBuf      (BYTE *);
+void   _Write_D_SsfdcBuf     (BYTE *);
+void   _Read_D_SsfdcByte     (BYTE *);
+void   _ReadRedt_D_SsfdcBuf  (BYTE *);
+void   _WriteRedt_D_SsfdcBuf (BYTE *);
+BYTE   _Check_D_DevCode      (BYTE);
+
+void   _Set_D_ECCdata        (BYTE,BYTE *);
+void   _Calc_D_ECCdata       (BYTE *);
+
+//void   SM_ReadDataWithDMA      (PFDO_DEVICE_EXTENSION, BYTE *, WORD);
+//void   SM_WriteDataWithDMA     (PFDO_DEVICE_EXTENSION, BYTE *, WORD);
+//
+struct SSFDCTYPE                Ssfdc;
+struct ADDRESS                  Media;
+struct CIS_AREA                 CisArea;
+
+BYTE                            EccBuf[6];
+extern PBYTE                    SMHostAddr;
+extern BYTE                     IsSSFDCCompliance;
+extern BYTE                     IsXDCompliance;
+extern DWORD                    ErrXDCode;
+
+extern WORD  ReadBlock;
+extern WORD  WriteBlock;
+
+//KEVENT                          SM_DMADoneEvent;
+
+#define EVEN                    0             // Even Page for 256byte/page
+#define ODD                     1             // Odd Page for 256byte/page
+
+
+//SmartMedia Redundant buffer data Controll Subroutine
+//----- Check_D_DataBlank() --------------------------------------------
+int Check_D_DataBlank(BYTE *redundant)
+{
+       char i;
+
+       for(i=0; i<REDTSIZE; i++)
+               if (*redundant++!=0xFF)
+                       return(ERROR);
+
+       return(SUCCESS);
+}
+
+//----- Check_D_FailBlock() --------------------------------------------
+int Check_D_FailBlock(BYTE *redundant)
+{
+       redundant+=REDT_BLOCK;
+
+       if (*redundant==0xFF)
+               return(SUCCESS);
+       if (!*redundant)
+               return(ERROR);
+       if (Bit_D_Count(*redundant)<7)
+               return(ERROR);
+
+       return(SUCCESS);
+}
+
+//----- Check_D_DataStatus() -------------------------------------------
+int Check_D_DataStatus(BYTE *redundant)
+{
+       redundant+=REDT_DATA;
+
+       if (*redundant==0xFF)
+               return(SUCCESS);
+       if (!*redundant)
+       {
+               ErrXDCode = ERR_DataStatus;
+               return(ERROR);
+       }
+       else
+               ErrXDCode = NO_ERROR;
+
+       if (Bit_D_Count(*redundant)<5)
+               return(ERROR);
+
+       return(SUCCESS);
+}
+
+//----- Load_D_LogBlockAddr() ------------------------------------------
+int Load_D_LogBlockAddr(BYTE *redundant)
+{
+       WORD addr1,addr2;
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       addr1=(WORD)*(redundant+REDT_ADDR1H)*0x0100+(WORD)*(redundant+REDT_ADDR1L);
+       addr2=(WORD)*(redundant+REDT_ADDR2H)*0x0100+(WORD)*(redundant+REDT_ADDR2L);
+
+       if (addr1==addr2)
+               if ((addr1 &0xF000)==0x1000)
+               { Media.LogBlock=(addr1 &0x0FFF)/2; return(SUCCESS); }
+
+       if (Bit_D_CountWord((WORD)(addr1^addr2))!=0x01) return(ERROR);
+
+       if ((addr1 &0xF000)==0x1000)
+               if (!(Bit_D_CountWord(addr1) &0x01))
+               { Media.LogBlock=(addr1 &0x0FFF)/2; return(SUCCESS); }
+
+       if ((addr2 &0xF000)==0x1000)
+               if (!(Bit_D_CountWord(addr2) &0x01))
+               { Media.LogBlock=(addr2 &0x0FFF)/2; return(SUCCESS); }
+
+       return(ERROR);
+}
+
+//----- Clr_D_RedundantData() ------------------------------------------
+void Clr_D_RedundantData(BYTE *redundant)
+{
+       char i;
+
+       for(i=0; i<REDTSIZE; i++)
+       *(redundant+i)=0xFF;
+}
+
+//----- Set_D_LogBlockAddr() -------------------------------------------
+void Set_D_LogBlockAddr(BYTE *redundant)
+{
+       WORD addr;
+
+       *(redundant+REDT_BLOCK)=0xFF;
+       *(redundant+REDT_DATA) =0xFF;
+       addr=Media.LogBlock*2+0x1000;
+
+       if ((Bit_D_CountWord(addr)%2))
+               addr++;
+
+       *(redundant+REDT_ADDR1H)=*(redundant+REDT_ADDR2H)=(BYTE)(addr/0x0100);
+       *(redundant+REDT_ADDR1L)=*(redundant+REDT_ADDR2L)=(BYTE)addr;
+}
+
+//----- Set_D_FailBlock() ----------------------------------------------
+void Set_D_FailBlock(BYTE *redundant)
+{
+    char i;
+
+    for(i=0; i<REDTSIZE; i++)
+        *redundant++=(BYTE)((i==REDT_BLOCK)?0xF0:0xFF);
+}
+
+//----- Set_D_DataStaus() ----------------------------------------------
+void Set_D_DataStaus(BYTE *redundant)
+{
+    redundant+=REDT_DATA;
+    *redundant=0x00;
+}
+
+//SmartMedia Function Command Subroutine
+// 6250 CMD 6
+//----- Ssfdc_D_Reset() ------------------------------------------------
+void Ssfdc_D_Reset(struct us_data *us)
+{
+       //NTSTATUS        ntStatus = STATUS_SUCCESS;
+       //PBULK_CBW       pBulkCbw = fdoExt->pBulkCbw;
+       //BYTE            buf[0x200];
+
+       //printk("Ssfdc_D_Reset --- But do nothing !!\n");
+       return;
+/*     RtlZeroMemory(pBulkCbw, sizeof(struct _BULK_CBW));
+       pBulkCbw->dCBWSignature          = CBW_SIGNTURE;
+       pBulkCbw->bCBWLun                = CBW_LUN;
+       //pBulkCbw->dCBWDataTransferLength = 0x200;
+       pBulkCbw->bmCBWFlags             = 0x80;
+       pBulkCbw->CBWCb[0]               = 0xF2;
+       pBulkCbw->CBWCb[1]               = 0x07;
+
+       ntStatus = ENE_SendScsiCmd(fdoExt, FDIR_READ, NULL);
+
+       if (!NT_SUCCESS(ntStatus))
+       {
+               ENE_Print("Ssfdc_D_Reset Fail !!\n");
+               //return ntStatus;
+       }*/
+}
+
+//----- Ssfdc_D_ReadCisSect() ------------------------------------------
+int Ssfdc_D_ReadCisSect(struct us_data *us, BYTE *buf,BYTE *redundant)
+{
+       BYTE zone,sector;
+       WORD block;
+       //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+       //ADDRESS_T   bb = (ADDRESS_T) &Media;
+
+       zone=Media.Zone; block=Media.PhyBlock; sector=Media.Sector;
+       Media.Zone=0;
+       Media.PhyBlock=CisArea.PhyBlock;
+       Media.Sector=CisArea.Sector;
+
+       if (Ssfdc_D_ReadSect(us,buf,redundant))
+       {
+               Media.Zone=zone; Media.PhyBlock=block; Media.Sector=sector;
+               return(ERROR);
+       }
+
+       Media.Zone=zone; Media.PhyBlock=block; Media.Sector=sector;
+       return(SUCCESS);
+}
+/*
+////----- Ssfdc_D_WriteRedtMode() ----------------------------------------
+//void Ssfdc_D_WriteRedtMode(void)
+//{
+//    _Set_D_SsfdcRdCmd     (RST_CHIP);
+//    _Check_D_SsfdcBusy    (BUSY_RESET);
+//    _Set_D_SsfdcRdCmd     (READ_REDT);
+//    _Check_D_SsfdcBusy    (BUSY_READ);
+//    _Set_D_SsfdcRdStandby ();
+//}
+//
+////----- Ssfdc_D_ReadID() -----------------------------------------------
+//void Ssfdc_D_ReadID(BYTE *buf, BYTE ReadID)
+//{
+//    _Set_D_SsfdcRdCmd     (ReadID);
+//    _Set_D_SsfdcRdChip    ();
+//    _Read_D_SsfdcByte     (buf++);
+//    _Read_D_SsfdcByte     (buf++);
+//    _Read_D_SsfdcByte     (buf++);
+//    _Read_D_SsfdcByte     (buf);
+//    _Set_D_SsfdcRdStandby ();
+//}
+*/
+// 6250 CMD 1
+//----- Ssfdc_D_ReadSect() ---------------------------------------------
+int Ssfdc_D_ReadSect(struct us_data *us, BYTE *buf,BYTE *redundant)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+       WORD    addr;
+
+       result = ENE_LoadBinCode(us, SM_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load SM RW Code Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+       addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
+
+       // Read sect data
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x200;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF1;
+       bcb->CDB[1]                     = 0x02;
+       bcb->CDB[4]                     = (BYTE)addr;
+       bcb->CDB[3]                     = (BYTE)(addr/0x0100);
+       bcb->CDB[2]                     = Media.Zone/2;
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       // Read redundant
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x10;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF1;
+       bcb->CDB[1]                     = 0x03;
+       bcb->CDB[4]                     = (BYTE)addr;
+       bcb->CDB[3]                     = (BYTE)(addr/0x0100);
+       bcb->CDB[2]                     = Media.Zone/2;
+       bcb->CDB[8]                     = 0;
+       bcb->CDB[9]                     = 1;
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, redundant, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- Ssfdc_D_ReadBlock() ---------------------------------------------
+int Ssfdc_D_ReadBlock(struct us_data *us, WORD count, BYTE *buf,BYTE *redundant)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+       WORD    addr;
+
+       //printk("Ssfdc_D_ReadBlock\n");
+       result = ENE_LoadBinCode(us, SM_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load SM RW Code Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+       addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
+
+       // Read sect data
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x200*count;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF1;
+       bcb->CDB[1]                     = 0x02;
+       bcb->CDB[4]                     = (BYTE)addr;
+       bcb->CDB[3]                     = (BYTE)(addr/0x0100);
+       bcb->CDB[2]                     = Media.Zone/2;
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       // Read redundant
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x10;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF1;
+       bcb->CDB[1]                     = 0x03;
+       bcb->CDB[4]                     = (BYTE)addr;
+       bcb->CDB[3]                     = (BYTE)(addr/0x0100);
+       bcb->CDB[2]                     = Media.Zone/2;
+       bcb->CDB[8]                     = 0;
+       bcb->CDB[9]                     = 1;
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, redundant, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+/*
+////----- Ssfdc_D_ReadSect_DMA() ---------------------------------------------
+//int Ssfdc_D_ReadSect_DMA(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant)
+//{
+//    WORD    SectByteCount, addr;
+//    DWORD   Buffer[4];
+//    WORD    len;
+//
+//    if (!_Hw_D_ChkCardIn())
+//       return(ERROR);
+//    addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+//    addr=addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
+//    // cycle starting address
+//    SM_STARTADDR_LSB = 0x00;
+//    SM_STARTADDR_IISB = (BYTE)addr;
+//    SM_STARTADDR_IIISB = (BYTE)(addr/0x0100);
+//    SM_STARTADDR_MSB = Media.Zone/2;
+//
+//    //Sector byte count = 0x200(DMA)
+//    SectByteCount = 0x20f;
+//    SM_BYTECNT_LO = (BYTE)SectByteCount;
+//    SM_CMD_CTRL3 = (SM_CMD_CTRL3 & 0xFC) | (BYTE)(SectByteCount/0x0100);
+//    if ( ((fdoExt->ChipID==READER_CB712)&&(fdoExt->RevID==CHIP_A)) || fdoExt->IsHibernate )
+//       SM_FIFO_CTRL = (SM_APB08_MASK | SM_DMAEN_MASK | SM_DMA_UPSTREAM_MASK | SM_FIFOSHLDVLU_8_MASK);
+//    else
+//       SM_FIFO_CTRL = (SM_APB32_MASK | SM_DMAEN_MASK | SM_DMA_UPSTREAM_MASK | SM_FIFOSHLDVLU_8_MASK);
+//
+//    _Hw_D_EccRdReset();
+//    _Hw_D_EccRdStart();
+//
+//    SM_CMD_CTRL1 = (SM_CMD_READ_1);
+//    SM_CMD_CTRL1 = (SM_CMD_READ_1 | SM_CMD_START_BIT);
+//
+//    SectByteCount = 0x1ff;
+//    //SM_ReadDataWithDMA(fdoExt, buf, SectByteCount);
+//    //_ReadRedt_D_SsfdcBuf(redundant);
+//    len = 0x1000 - ((WORD)(buf) & 0x0FFF);
+//    if (len < 0x200)
+//    {
+//       SM_ReadDataWithDMA(fdoExt, buf, len-1);
+//       SM_ReadDataWithDMA(fdoExt, buf+len, SectByteCount-len);
+//       //ENE_Print("Read DMA !!! buf1 = %p, len = %x, buf2 = %p\n", buf, len, buf+len);
+//    }
+//    else
+//      SM_ReadDataWithDMA(fdoExt, buf, SectByteCount);
+//
+//    if ( ((fdoExt->ChipID==READER_CB712)&&(fdoExt->RevID==CHIP_A)) || fdoExt->IsHibernate )
+//    {
+//       _ReadRedt_D_SsfdcBuf(redundant);
+//    }
+//    else
+//    {
+//       Buffer[0] = READ_PORT_DWORD(SM_REG_DATA);
+//       Buffer[1] = READ_PORT_DWORD(SM_REG_DATA);
+//       Buffer[2] = READ_PORT_DWORD(SM_REG_DATA);
+//       Buffer[3] = READ_PORT_DWORD(SM_REG_DATA);
+//       memcpy(redundant, Buffer, 0x10);
+//    }
+//
+//    while ( _Hw_D_ChkCardIn() )
+//    {
+//        if((READ_PORT_BYTE(SM_REG_INT_STATUS) & 0x10))
+//        {
+//            WRITE_PORT_BYTE(SM_REG_INT_STATUS, 0x10);
+//            break;
+//        }
+//    }
+//    _Hw_D_EccRdStop();
+//    _Hw_D_SetRdStandby();
+//    _Load_D_SsfdcRdHwECC(EVEN);
+//
+//    _Calc_D_ECCdata(buf);
+//    _Set_D_SsfdcRdStandby();
+//
+//    if (!_Hw_D_ChkCardIn())
+//       return(ERROR);
+//    return(SUCCESS);
+//}
+//
+////----- Ssfdc_D_ReadSect_PIO() ---------------------------------------------
+//int Ssfdc_D_ReadSect_PIO(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant)
+//{
+//    _Set_D_SsfdcRdCmd(READ);
+//    _Set_D_SsfdcRdAddr(EVEN);
+//
+//    if (_Check_D_SsfdcBusy(BUSY_READ))
+//    { _Reset_D_SsfdcErr(); return(ERROR); }
+//
+//    _Start_D_SsfdcRdHwECC();
+//    _Read_D_SsfdcBuf(buf);
+//    _Stop_D_SsfdcRdHwECC();
+//    _ReadRedt_D_SsfdcBuf(redundant);
+//    _Load_D_SsfdcRdHwECC(EVEN);
+//
+//    if (_Check_D_SsfdcBusy(BUSY_READ))
+//    { _Reset_D_SsfdcErr(); return(ERROR); }
+//
+//    _Calc_D_ECCdata(buf);
+//    _Set_D_SsfdcRdStandby();
+//    return(SUCCESS);
+//}
+
+// 6250 CMD 3
+//----- Ssfdc_D_WriteSect() --------------------------------------------
+int Ssfdc_D_WriteSect(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant)
+{
+    PBULK_CBW               pBulkCbw = fdoExt->pBulkCbw;
+    NTSTATUS                ntStatus;
+    WORD                    addr;
+
+    //ENE_Print("SMILSUB --- Ssfdc_D_WriteSect\n");
+    ENE_LoadBinCode(fdoExt, SM_RW_PATTERN);
+
+    addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+    addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
+
+    // Write sect data
+    RtlZeroMemory(pBulkCbw, sizeof(struct _BULK_CBW));
+    pBulkCbw->dCBWSignature          = CBW_SIGNTURE;
+    pBulkCbw->bCBWLun                = CBW_LUN;
+    pBulkCbw->dCBWDataTransferLength = 0x200;
+    pBulkCbw->bmCBWFlags             = 0x00;
+    pBulkCbw->CBWCb[0]               = 0xF0;
+    pBulkCbw->CBWCb[1]               = 0x04;
+    //pBulkCbw->CBWCb[4]               = (BYTE)addr;
+    //pBulkCbw->CBWCb[3]               = (BYTE)(addr/0x0100);
+    //pBulkCbw->CBWCb[2]               = Media.Zone/2;
+    //pBulkCbw->CBWCb[5]               = *(redundant+REDT_ADDR1H);
+    //pBulkCbw->CBWCb[6]               = *(redundant+REDT_ADDR1L);
+    pBulkCbw->CBWCb[7]               = (BYTE)addr;
+    pBulkCbw->CBWCb[6]               = (BYTE)(addr/0x0100);
+    pBulkCbw->CBWCb[5]               = Media.Zone/2;
+    pBulkCbw->CBWCb[8]               = *(redundant+REDT_ADDR1H);
+    pBulkCbw->CBWCb[9]               = *(redundant+REDT_ADDR1L);
+
+    ntStatus = ENE_SendScsiCmd(fdoExt, FDIR_WRITE, buf);
+
+    if (!NT_SUCCESS(ntStatus))
+       return(ERROR);
+
+//  // For Test
+//  {
+//     BYTE   bf[0x200], rdd[0x10];
+//     ULONG  i;
+//
+//     RtlZeroMemory(bf, 0x200);
+//     RtlZeroMemory(rdd, 0x10);
+//     ntStatus = SM_ReadBlock(fdoExt, bf, rdd);
+//     for (i=0; i<0x200; i++)
+//     {
+//         if (buf[i] != bf[i])
+//            ENE_Print("buf[%x] = %x, bf[%x] = %x\n", buf, bf);
+//     }
+//     if (!NT_SUCCESS(ntStatus))
+//        ENE_Print("Error\n");
+//  }
+
+    return(SUCCESS);
+}
+*/
+//----- Ssfdc_D_CopyBlock() --------------------------------------------
+int Ssfdc_D_CopyBlock(struct us_data *us, WORD count, BYTE *buf,BYTE *redundant)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+    //PBULK_CBW               pBulkCbw = fdoExt->pBulkCbw;
+    //NTSTATUS                ntStatus;
+       WORD    ReadAddr, WriteAddr;
+
+       //printk("Ssfdc_D_WriteSect --- ZONE = %x, ReadBlock = %x, WriteBlock = %x\n", Media.Zone, ReadBlock, WriteBlock);
+
+       result = ENE_LoadBinCode(us, SM_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load SM RW Code Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       ReadAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks+ReadBlock;
+       ReadAddr = ReadAddr*(WORD)Ssfdc.MaxSectors;
+       WriteAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks+WriteBlock;
+       WriteAddr = WriteAddr*(WORD)Ssfdc.MaxSectors;
+
+       // Write sect data
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x200*count;
+       bcb->Flags                      = 0x00;
+       bcb->CDB[0]                     = 0xF0;
+       bcb->CDB[1]                     = 0x08;
+       bcb->CDB[7]                     = (BYTE)WriteAddr;
+       bcb->CDB[6]                     = (BYTE)(WriteAddr/0x0100);
+       bcb->CDB[5]                     = Media.Zone/2;
+       bcb->CDB[8]                     = *(redundant+REDT_ADDR1H);
+       bcb->CDB[9]                     = *(redundant+REDT_ADDR1L);
+       bcb->CDB[10]            = Media.Sector;
+
+       if (ReadBlock != NO_ASSIGN)
+       {
+               bcb->CDB[4]             = (BYTE)ReadAddr;
+               bcb->CDB[3]             = (BYTE)(ReadAddr/0x0100);
+               bcb->CDB[2]             = Media.Zone/2;
+       }
+       else
+               bcb->CDB[11]    = 1;
+
+       result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+/*
+//----- Ssfdc_D_WriteBlock() --------------------------------------------
+int Ssfdc_D_WriteBlock(PFDO_DEVICE_EXTENSION fdoExt, WORD count, BYTE *buf,BYTE *redundant)
+{
+    PBULK_CBW               pBulkCbw = fdoExt->pBulkCbw;
+    NTSTATUS                ntStatus;
+    WORD                    addr;
+
+    //ENE_Print("SMILSUB --- Ssfdc_D_WriteSect\n");
+    ENE_LoadBinCode(fdoExt, SM_RW_PATTERN);
+
+    addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+    addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
+
+    // Write sect data
+    RtlZeroMemory(pBulkCbw, sizeof(struct _BULK_CBW));
+    pBulkCbw->dCBWSignature          = CBW_SIGNTURE;
+    pBulkCbw->bCBWLun                = CBW_LUN;
+    pBulkCbw->dCBWDataTransferLength = 0x200*count;
+    pBulkCbw->bmCBWFlags             = 0x00;
+    pBulkCbw->CBWCb[0]               = 0xF0;
+    pBulkCbw->CBWCb[1]               = 0x04;
+    pBulkCbw->CBWCb[7]               = (BYTE)addr;
+    pBulkCbw->CBWCb[6]               = (BYTE)(addr/0x0100);
+    pBulkCbw->CBWCb[5]               = Media.Zone/2;
+    pBulkCbw->CBWCb[8]               = *(redundant+REDT_ADDR1H);
+    pBulkCbw->CBWCb[9]               = *(redundant+REDT_ADDR1L);
+
+    ntStatus = ENE_SendScsiCmd(fdoExt, FDIR_WRITE, buf);
+
+    if (!NT_SUCCESS(ntStatus))
+       return(ERROR);
+
+//  // For Test
+//  {
+//     BYTE   bf[0x200], rdd[0x10];
+//     ULONG  i;
+//
+//     RtlZeroMemory(bf, 0x200);
+//     RtlZeroMemory(rdd, 0x10);
+//     ntStatus = SM_ReadBlock(fdoExt, bf, rdd);
+//     for (i=0; i<0x200; i++)
+//     {
+//         if (buf[i] != bf[i])
+//            ENE_Print("buf[%x] = %x, bf[%x] = %x\n", buf, bf);
+//     }
+//     if (!NT_SUCCESS(ntStatus))
+//        ENE_Print("Error\n");
+//  }
+
+    return(SUCCESS);
+}
+//
+////----- Ssfdc_D_WriteSect_DMA() --------------------------------------------
+//int Ssfdc_D_WriteSect_DMA(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant)
+//{
+//    WORD    SectByteCount, addr;
+//    DWORD   Buffer[4];
+//    WORD    len;
+//
+//    if (!_Hw_D_ChkCardIn())
+//       return(ERROR);
+//    addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+//    addr=addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
+//    // cycle starting address
+//    SM_STARTADDR_LSB = 0x00;
+//    SM_STARTADDR_IISB = (BYTE)addr;
+//    SM_STARTADDR_IIISB = (BYTE)(addr/0x0100);
+//    SM_STARTADDR_MSB = Media.Zone/2;
+//
+//    //Sector byte count (DMA)
+//    SectByteCount = 0x20f;
+//    SM_BYTECNT_LO = (BYTE)SectByteCount;
+//    SM_CMD_CTRL3 = (SM_CMD_CTRL3 & 0xFC) | 0x20 | (BYTE)(SectByteCount/0x0100);
+//    if ( ((fdoExt->ChipID==READER_CB712)&&(fdoExt->RevID==CHIP_A)) || fdoExt->IsHibernate )
+//       SM_FIFO_CTRL = (SM_APB08_MASK | SM_DMAEN_MASK | SM_DMA_DOWNSTREAM_MASK | SM_FIFOSHLDVLU_8_MASK);
+//    else
+//       SM_FIFO_CTRL = (SM_APB32_MASK | SM_DMAEN_MASK | SM_DMA_DOWNSTREAM_MASK | SM_FIFOSHLDVLU_8_MASK);
+//
+//    _Hw_D_EccRdReset();
+//    _Hw_D_EccRdStart();
+//
+//    SM_CMD_CTRL1 = SM_CMD_PAGPRGM_TRUE;
+//    SM_CMD_CTRL1 = (SM_CMD_PAGPRGM_TRUE | SM_CMD_START_BIT);
+//
+//    SectByteCount = 0x1ff;
+//    //SM_WriteDataWithDMA(fdoExt, buf, SectByteCount);
+//    //_WriteRedt_D_SsfdcBuf(redundant);
+//    len = 0x1000 - ((WORD)(buf) & 0x0FFF);
+//    if (len < 0x200)
+//    {
+//       SM_WriteDataWithDMA(fdoExt, buf, len-1);
+//       SM_WriteDataWithDMA(fdoExt, buf+len, SectByteCount-len);
+//       //ENE_Print("Read DMA !!! buf1 = %p, len = %x, buf2 = %p\n", buf, len, buf+len);
+//    }
+//    else
+//      SM_WriteDataWithDMA(fdoExt, buf, SectByteCount);
+//
+//    //T1 = (ULONGLONG)buf & 0xFFFFFFFFFFFFF000;
+//    //T2 = ((ULONGLONG)buf + 0x1FF) & 0xFFFFFFFFFFFFF000;
+//    //if (T1 != T2)
+//    //   ENE_Print("Ssfdc_D_WriteSect_DMA !!! buf = %p, T1 = %p, T2 = %p\n", buf, T1, T2);
+//    //if (T2-T1)
+//    //{
+//    //   l1 = (WORD)(T2 - (ULONGLONG)buf);
+//    //   SM_WriteDataWithDMA(fdoExt, buf, l1-1);
+//    //   SM_WriteDataWithDMA(fdoExt, (PBYTE)T2, SectByteCount-l1);
+//    //}
+//    //else
+//    //  SM_WriteDataWithDMA(fdoExt, buf, SectByteCount);
+//
+//    if ( ((fdoExt->ChipID==READER_CB712)&&(fdoExt->RevID==CHIP_A)) || fdoExt->IsHibernate )
+//    {
+//       _WriteRedt_D_SsfdcBuf(redundant);
+//    }
+//    else
+//    {
+//       memcpy(Buffer, redundant, 0x10);
+//       WRITE_PORT_DWORD(SM_REG_DATA, Buffer[0]);
+//       WRITE_PORT_DWORD(SM_REG_DATA, Buffer[1]);
+//       WRITE_PORT_DWORD(SM_REG_DATA, Buffer[2]);
+//       WRITE_PORT_DWORD(SM_REG_DATA, Buffer[3]);
+//    }
+//
+//    while ( _Hw_D_ChkCardIn() )
+//    {
+//       if ((READ_PORT_BYTE(SM_REG_INT_STATUS) & 0x10))
+//       {
+//           WRITE_PORT_BYTE(SM_REG_INT_STATUS, 0x10);
+//           break;
+//       }
+//    }
+//    _Hw_D_EccRdStop();
+//    _Hw_D_SetRdStandby();
+//
+//    _Set_D_SsfdcWrStandby();
+//    _Set_D_SsfdcRdStandby();
+//    if (!_Hw_D_ChkCardIn())
+//       return(ERROR);
+//
+//    return(SUCCESS);
+//}
+//
+////----- Ssfdc_D_WriteSect_PIO() --------------------------------------------
+//int Ssfdc_D_WriteSect_PIO(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant)
+//{
+//    _Calc_D_ECCdata(buf);
+//    _Set_D_SsfdcWrCmd(WRDATA);
+//    _Set_D_SsfdcWrAddr(EVEN);
+//    _Start_D_SsfdcWrHwECC();
+//
+//    _Write_D_SsfdcBuf(buf);
+//
+//    _Load_D_SsfdcWrHwECC(EVEN);
+//    _Set_D_ECCdata(EVEN,redundant);
+//
+//    _WriteRedt_D_SsfdcBuf(redundant);
+//
+//    _Set_D_SsfdcWrCmd(WRITE);
+//
+//    if (_Check_D_SsfdcBusy(BUSY_PROG))
+//    { _Reset_D_SsfdcErr(); return(ERROR); }
+//
+//    _Set_D_SsfdcWrStandby();
+//    _Set_D_SsfdcRdStandby();
+//    return(SUCCESS);
+//}
+*/
+//----- Ssfdc_D_WriteSectForCopy() -------------------------------------
+int Ssfdc_D_WriteSectForCopy(struct us_data *us, BYTE *buf, BYTE *redundant)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+       //PBULK_CBW               pBulkCbw = fdoExt->pBulkCbw;
+       //NTSTATUS                ntStatus;
+       WORD                    addr;
+
+       //printk("SMILSUB --- Ssfdc_D_WriteSectForCopy\n");
+       result = ENE_LoadBinCode(us, SM_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load SM RW Code Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+
+       addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+       addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
+
+       // Write sect data
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x200;
+       bcb->Flags                      = 0x00;
+       bcb->CDB[0]                     = 0xF0;
+       bcb->CDB[1]                     = 0x04;
+       bcb->CDB[7]                     = (BYTE)addr;
+       bcb->CDB[6]                     = (BYTE)(addr/0x0100);
+       bcb->CDB[5]                     = Media.Zone/2;
+       bcb->CDB[8]                     = *(redundant+REDT_ADDR1H);;
+       bcb->CDB[9]                     = *(redundant+REDT_ADDR1L);;
+
+       result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+// 6250 CMD 5
+//----- Ssfdc_D_EraseBlock() -------------------------------------------
+int Ssfdc_D_EraseBlock(struct us_data *us)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+       WORD    addr;
+
+       result = ENE_LoadBinCode(us, SM_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load SM RW Code Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+       addr=addr*(WORD)Ssfdc.MaxSectors;
+
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x200;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF2;
+       bcb->CDB[1]                     = 0x06;
+       bcb->CDB[7]                     = (BYTE)addr;
+       bcb->CDB[6]                     = (BYTE)(addr/0x0100);
+       bcb->CDB[5]                     = Media.Zone/2;
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+// 6250 CMD 2
+//----- Ssfdc_D_ReadRedtData() -----------------------------------------
+int Ssfdc_D_ReadRedtData(struct us_data *us, BYTE *redundant)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+       WORD    addr;
+       BYTE  *buf;
+
+       result = ENE_LoadBinCode(us, SM_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load SM RW Code Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+       addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
+
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x10;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF1;
+       bcb->CDB[1]                     = 0x03;
+       bcb->CDB[4]                     = (BYTE)addr;
+       bcb->CDB[3]                     = (BYTE)(addr/0x0100);
+       bcb->CDB[2]                     = Media.Zone/2;
+       bcb->CDB[8]                     = 0;
+       bcb->CDB[9]                     = 1;
+
+       buf = kmalloc(0x10, GFP_KERNEL);
+       //result = ENE_SendScsiCmd(us, FDIR_READ, redundant, 0);
+       result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
+       memcpy(redundant, buf, 0x10);
+       kfree(buf);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+// 6250 CMD 4
+//----- Ssfdc_D_WriteRedtData() ----------------------------------------
+int Ssfdc_D_WriteRedtData(struct us_data *us, BYTE *redundant)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int     result;
+       //PBULK_CBW               pBulkCbw = fdoExt->pBulkCbw;
+       //NTSTATUS                ntStatus;
+       WORD                    addr;
+
+       result = ENE_LoadBinCode(us, SM_RW_PATTERN);
+       if (result != USB_STOR_XFER_GOOD)
+       {
+               printk("Load SM RW Code Fail !!\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+       addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
+
+       memset(bcb, 0, sizeof(bcb));
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = 0x10;
+       bcb->Flags                      = 0x80;
+       bcb->CDB[0]                     = 0xF2;
+       bcb->CDB[1]                     = 0x05;
+       bcb->CDB[7]                     = (BYTE)addr;
+       bcb->CDB[6]                     = (BYTE)(addr/0x0100);
+       bcb->CDB[5]                     = Media.Zone/2;
+       bcb->CDB[8]                     = *(redundant+REDT_ADDR1H);
+       bcb->CDB[9]                     = *(redundant+REDT_ADDR1L);
+
+       result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- Ssfdc_D_CheckStatus() ------------------------------------------
+int Ssfdc_D_CheckStatus(void)
+{
+    // Driver Â¤Â£Â°Âµ
+    return(SUCCESS);
+    //_Set_D_SsfdcRdCmd(RDSTATUS);
+    //
+    //if (_Check_D_SsfdcStatus())
+    //{ _Set_D_SsfdcRdStandby(); return(ERROR); }
+    //
+    //_Set_D_SsfdcRdStandby();
+    //return(SUCCESS);
+}
+/*
+////NAND Memory (SmartMedia) Control Subroutine for Read Data
+////----- _Set_D_SsfdcRdCmd() --------------------------------------------
+//void _Set_D_SsfdcRdCmd(BYTE cmd)
+//{
+//    _Hw_D_SetRdCmd();
+//    _Hw_D_OutData(cmd);
+//    _Hw_D_SetRdData();
+//}
+//
+////----- _Set_D_SsfdcRdAddr() -------------------------------------------
+//void _Set_D_SsfdcRdAddr(BYTE add)
+//{
+//    WORD addr;
+//    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+//    ADDRESS_T   bb = (ADDRESS_T) &Media;
+//
+//    addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+//    addr=addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
+//
+//    //if ((Ssfdc.Attribute &MPS)==PS256) // for 256byte/page
+//    //    addr=addr*2+(WORD)add;
+//
+//    _Hw_D_SetRdAddr();
+//    _Hw_D_OutData(0x00);
+//    _Hw_D_OutData((BYTE)addr);
+//    _Hw_D_OutData((BYTE)(addr/0x0100));
+//
+//    if ((Ssfdc.Attribute &MADC)==AD4CYC)
+//        _Hw_D_OutData((BYTE)(Media.Zone/2)); // Patch
+//
+//    _Hw_D_SetRdData();
+//}
+//
+////----- _Set_D_SsfdcRdChip() -------------------------------------------
+//void _Set_D_SsfdcRdChip(void)
+//{
+//    _Hw_D_SetRdAddr();
+//    _Hw_D_OutData(0x00);
+//    _Hw_D_SetRdData();
+//}
+//
+////----- _Set_D_SsfdcRdStandby() ----------------------------------------
+//void _Set_D_SsfdcRdStandby(void)
+//{
+//    _Hw_D_SetRdStandby();
+//}
+//
+////----- _Start_D_SsfdcRdHwECC() ----------------------------------------
+//void _Start_D_SsfdcRdHwECC(void)
+//{
+//#ifdef HW_ECC_SUPPORTED
+//    _Hw_D_EccRdReset();
+//    _Hw_D_InData();
+//    _Hw_D_EccRdStart();
+//#endif
+//}
+//
+////----- _Stop_D_SsfdcRdHwECC() -----------------------------------------
+//void _Stop_D_SsfdcRdHwECC(void)
+//{
+//#ifdef HW_ECC_SUPPORTED
+//    _Hw_D_EccRdStop();
+//#endif
+//}
+//
+////----- _Load_D_SsfdcRdHwECC() -----------------------------------------
+//void _Load_D_SsfdcRdHwECC(BYTE add)
+//{
+//#ifdef HW_ECC_SUPPORTED
+//    _Hw_D_EccRdRead();
+//    //if (!(add==ODD && (Ssfdc.Attribute &MPS)==PS256))
+//    {
+//        EccBuf[0]=_Hw_D_InData();
+//        EccBuf[1]=_Hw_D_InData();
+//        EccBuf[2]=_Hw_D_InData();
+//    }
+//
+//    //if (!(add==EVEN && (Ssfdc.Attribute &MPS)==PS256))
+//    {
+//        EccBuf[3]=_Hw_D_InData();
+//        EccBuf[4]=_Hw_D_InData();
+//        EccBuf[5]=_Hw_D_InData();
+//    }
+//
+//    _Hw_D_EccRdStop();
+//#endif
+//}
+//
+////NAND Memory (SmartMedia) Control Subroutine for Write Data
+//
+////----- _Set_D_SsfdcWrCmd() -----------------------------------------
+//void _Set_D_SsfdcWrCmd(BYTE cmd)
+//{
+//    _Hw_D_SetWrCmd();
+//    _Hw_D_OutData(cmd);
+//    _Hw_D_SetWrData();
+//}
+//
+////----- _Set_D_SsfdcWrAddr() -----------------------------------------
+//void _Set_D_SsfdcWrAddr(BYTE add)
+//{
+//    WORD addr;
+//    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+//    ADDRESS_T   bb = (ADDRESS_T) &Media;
+//
+//    addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+//    addr=addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
+//
+//    //if ((Ssfdc.Attribute &MPS)==PS256) // for 256byte/page
+//    //    addr=addr*2+(WORD)add;
+//
+//    _Hw_D_SetWrAddr();
+//    _Hw_D_OutData(0x00);
+//    _Hw_D_OutData((BYTE)addr);
+//    _Hw_D_OutData((BYTE)(addr/0x0100));
+//
+//    if ((Ssfdc.Attribute &MADC)==AD4CYC)
+//        _Hw_D_OutData((BYTE)(Media.Zone/2)); // Patch
+//
+//    _Hw_D_SetWrData();
+//}
+//
+////----- _Set_D_SsfdcWrBlock() -----------------------------------------
+//void _Set_D_SsfdcWrBlock(void)
+//{
+//    WORD addr;
+//    SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc;
+//    ADDRESS_T   bb = (ADDRESS_T) &Media;
+//
+//    addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+//    addr=addr*(WORD)Ssfdc.MaxSectors;
+//
+//    //if ((Ssfdc.Attribute &MPS)==PS256) // for 256byte/page
+//    //    addr=addr*2;
+//
+//    _Hw_D_SetWrAddr();
+//    _Hw_D_OutData((BYTE)addr);
+//    _Hw_D_OutData((BYTE)(addr/0x0100));
+//
+//    if ((Ssfdc.Attribute &MADC)==AD4CYC)
+//        _Hw_D_OutData((BYTE)(Media.Zone/2)); // Patch
+//
+//    _Hw_D_SetWrData();
+//}
+//
+////----- _Set_D_SsfdcWrStandby() -----------------------------------------
+//void _Set_D_SsfdcWrStandby(void)
+//{
+//    _Hw_D_SetWrStandby();
+//}
+//
+////----- _Start_D_SsfdcWrHwECC() -----------------------------------------
+//void _Start_D_SsfdcWrHwECC(void)
+//{
+//#ifdef HW_ECC_SUPPORTED
+//    _Hw_D_EccWrReset();
+//    _Hw_D_InData();
+//    _Hw_D_EccWrStart();
+//#endif
+//}
+//
+////----- _Load_D_SsfdcWrHwECC() -----------------------------------------
+//void _Load_D_SsfdcWrHwECC(BYTE add)
+//{
+//#ifdef HW_ECC_SUPPORTED
+//    _Hw_D_EccWrRead();
+//    //if (!(add==ODD && (Ssfdc.Attribute &MPS)==PS256))
+//    {
+//        EccBuf[0]=_Hw_D_InData();
+//        EccBuf[1]=_Hw_D_InData();
+//        EccBuf[2]=_Hw_D_InData();
+//    }
+//
+//    //if (!(add==EVEN && (Ssfdc.Attribute &MPS)==PS256))
+//    {
+//        EccBuf[3]=_Hw_D_InData();
+//        EccBuf[4]=_Hw_D_InData();
+//        EccBuf[5]=_Hw_D_InData();
+//    }
+//
+//    _Hw_D_EccWrStop();
+//#endif
+//}
+//
+////NAND Memory (SmartMedia) Control Subroutine
+////----- _Check_D_SsfdcBusy() -------------------------------------------
+//int _Check_D_SsfdcBusy(WORD time)
+//{
+//    WORD  count = 0;
+//
+//    do {
+//        if (!_Hw_D_ChkBusy())
+//            return(SUCCESS);
+//        EDelay(100);
+//        count++;
+//    } while (count<=time);
+//
+//    return(ERROR);
+//}
+//
+////----- _Check_D_SsfdcStatus() -----------------------------------------
+//int _Check_D_SsfdcStatus(void)
+//{
+//    if (_Hw_D_InData() & WR_FAIL)
+//        return(ERROR);
+//
+//    return(SUCCESS);
+//}
+//
+//// For 712
+////----- _Reset_D_SsfdcErr() -----------------------------------------
+//void _Reset_D_SsfdcErr(void)
+//{
+//    WORD  count = 0;
+//
+//    _Hw_D_SetRdCmd();
+//    _Hw_D_OutData(RST_CHIP);
+//    _Hw_D_SetRdData();
+//
+//    do {
+//        if (!_Hw_D_ChkBusy())
+//            break;
+//        EDelay(100);
+//        count++;
+//    } while (count<=BUSY_RESET);
+//
+//    _Hw_D_SetRdStandby();
+//}
+//
+////NAND Memory (SmartMedia) Buffer Data Xfer Subroutine
+////----- SM_ReadDataWithDMA() -----------------------------------------
+//void SM_ReadDataWithDMA(PFDO_DEVICE_EXTENSION fdoExt, BYTE *databuf, WORD SectByteCount)
+//{
+//    PHYSICAL_ADDRESS        Addr;
+//    LARGE_INTEGER           ptimeout ;
+//
+//    KeClearEvent(&fdoExt->SM_DMADoneEvent);
+//
+//    Addr = MmGetPhysicalAddress(databuf);
+//
+//    WRITE_PORT_DWORD(SM_DMA_ADDR_REG, (DWORD)Addr.LowPart);
+//    WRITE_PORT_BYTE(SM_DMA_DATA_CTRL, 0);
+//    WRITE_PORT_WORD(SM_DMA_BYTE_COUNT_REG, SectByteCount);
+//
+//    while ( _Hw_D_ChkCardIn() )
+//    {
+//        if ((READ_PORT_BYTE(SM_REG_FIFO_STATUS) & 0x80))
+//           break;
+//    }
+//    if (!_Hw_D_ChkCardIn())      return;
+//    WRITE_PORT_BYTE(SM_DMA_DATA_CTRL, 0x01);
+//
+//    ptimeout.QuadPart = 2000 * (-10000);                                    // 2 sec
+//    KeWaitForSingleObject(&fdoExt->SM_DMADoneEvent, Executive, KernelMode, FALSE, &ptimeout);
+//    _Hw_D_SetDMAIntMask();
+//}
+//
+////----- SM_WriteDataWithDMA() -----------------------------------------
+//void SM_WriteDataWithDMA(PFDO_DEVICE_EXTENSION fdoExt, BYTE *databuf, WORD SectByteCount)
+//{
+//    PHYSICAL_ADDRESS        Addr;
+//    LARGE_INTEGER           ptimeout ;
+//
+//    KeClearEvent(&fdoExt->SM_DMADoneEvent);
+//
+//    Addr = MmGetPhysicalAddress(databuf);
+//
+//    WRITE_PORT_DWORD(SM_DMA_ADDR_REG, (DWORD)Addr.LowPart);
+//    WRITE_PORT_BYTE(SM_DMA_DATA_CTRL, 2);
+//    WRITE_PORT_WORD(SM_DMA_BYTE_COUNT_REG, SectByteCount);
+//
+//    while ( _Hw_D_ChkCardIn() )
+//    {
+//       if ((READ_PORT_BYTE(SM_REG_FIFO_STATUS) & 0x40))
+//           break;
+//    }
+//    if (!_Hw_D_ChkCardIn())      return;
+//    WRITE_PORT_BYTE(SM_DMA_DATA_CTRL, 0x03);
+//
+//    ptimeout.QuadPart = 2000 * (-10000);                                    // 2 sec
+//    KeWaitForSingleObject(&fdoExt->SM_DMADoneEvent, Executive, KernelMode, FALSE, &ptimeout);
+//    _Hw_D_SetDMAIntMask();
+//}
+//
+////----- _Read_D_SsfdcBuf() -----------------------------------------
+//void _Read_D_SsfdcBuf(BYTE *databuf)
+//{
+//    int i;
+//
+//    //for(i=0x0000;i<(((Ssfdc.Attribute &MPS)==PS256)?0x0100:0x0200);i++)
+//    for(i=0; i<0x200; i++)
+//        *databuf++ =_Hw_D_InData();
+//}
+//
+////----- _Write_D_SsfdcBuf() -----------------------------------------
+//void _Write_D_SsfdcBuf(BYTE *databuf)
+//{
+//    int i;
+//
+//    //for(i=0x0000;i<(((Ssfdc.Attribute &MPS)==PS256)?0x0100:0x0200);i++)
+//    for(i=0; i<0x200; i++)
+//        _Hw_D_OutData(*databuf++);
+//}
+//
+////----- _Read_D_SsfdcByte() -----------------------------------------
+//void _Read_D_SsfdcByte(BYTE *databuf)
+//{
+//    *databuf=(BYTE)_Hw_D_InData();
+//}
+//
+////----- _ReadRedt_D_SsfdcBuf() -----------------------------------------
+//void _ReadRedt_D_SsfdcBuf(BYTE *redundant)
+//{
+//    char i;
+//
+//    //for(i=0x00;i<(((Ssfdc.Attribute &MPS)==PS256)?0x08:0x10);i++)
+//    for(i=0; i<0x10; i++)
+//        redundant[i] =_Hw_D_InData();
+//}
+//
+////----- _WriteRedt_D_SsfdcBuf() -----------------------------------------
+//void _WriteRedt_D_SsfdcBuf(BYTE *redundant)
+//{
+//    char i;
+//
+//    //for(i=0x00;i<(((Ssfdc.Attribute &MPS)==PS256)?0x08:0x10);i++)
+//    for(i=0; i<0x10; i++)
+//        _Hw_D_OutData(*redundant++);
+//}
+*/
+//SmartMedia ID Code Check & Mode Set Subroutine
+//----- Set_D_SsfdcModel() ---------------------------------------------
+int Set_D_SsfdcModel(BYTE dcode)
+{
+    switch (_Check_D_DevCode(dcode)) {
+        case SSFDC1MB:
+            Ssfdc.Model        = SSFDC1MB;
+            Ssfdc.Attribute    = FLASH | AD3CYC | BS16 | PS256;
+            Ssfdc.MaxZones     = 1;
+            Ssfdc.MaxBlocks    = 256;
+            Ssfdc.MaxLogBlocks = 250;
+            Ssfdc.MaxSectors   = 8;
+            break;
+        case SSFDC2MB:
+            Ssfdc.Model        = SSFDC2MB;
+            Ssfdc.Attribute    = FLASH | AD3CYC | BS16 | PS256;
+            Ssfdc.MaxZones     = 1;
+            Ssfdc.MaxBlocks    = 512;
+            Ssfdc.MaxLogBlocks = 500;
+            Ssfdc.MaxSectors   = 8;
+            break;
+        case SSFDC4MB:
+            Ssfdc.Model        = SSFDC4MB;
+            Ssfdc.Attribute    = FLASH | AD3CYC | BS16 | PS512;
+            Ssfdc.MaxZones     = 1;
+            Ssfdc.MaxBlocks    = 512;
+            Ssfdc.MaxLogBlocks = 500;
+            Ssfdc.MaxSectors   = 16;
+            break;
+        case SSFDC8MB:
+            Ssfdc.Model        = SSFDC8MB;
+            Ssfdc.Attribute    = FLASH | AD3CYC | BS16 | PS512;
+            Ssfdc.MaxZones     = 1;
+            Ssfdc.MaxBlocks    = 1024;
+            Ssfdc.MaxLogBlocks = 1000;
+            Ssfdc.MaxSectors   = 16;
+            break;
+        case SSFDC16MB:
+            Ssfdc.Model        = SSFDC16MB;
+            Ssfdc.Attribute    = FLASH | AD3CYC | BS32 | PS512;
+            Ssfdc.MaxZones     = 1;
+            Ssfdc.MaxBlocks    = 1024;
+            Ssfdc.MaxLogBlocks = 1000;
+            Ssfdc.MaxSectors   = 32;
+            break;
+        case SSFDC32MB:
+            Ssfdc.Model        = SSFDC32MB;
+            Ssfdc.Attribute    = FLASH | AD3CYC | BS32 | PS512;
+            Ssfdc.MaxZones     = 2;
+            Ssfdc.MaxBlocks    = 1024;
+            Ssfdc.MaxLogBlocks = 1000;
+            Ssfdc.MaxSectors   = 32;
+            break;
+        case SSFDC64MB:
+            Ssfdc.Model        = SSFDC64MB;
+            Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
+            Ssfdc.MaxZones     = 4;
+            Ssfdc.MaxBlocks    = 1024;
+            Ssfdc.MaxLogBlocks = 1000;
+            Ssfdc.MaxSectors   = 32;
+            break;
+        case SSFDC128MB:
+            Ssfdc.Model        = SSFDC128MB;
+            Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
+            Ssfdc.MaxZones     = 8;
+            Ssfdc.MaxBlocks    = 1024;
+            Ssfdc.MaxLogBlocks = 1000;
+            Ssfdc.MaxSectors   = 32;
+            break;
+        case SSFDC256MB:
+            Ssfdc.Model        = SSFDC256MB;
+            Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
+            Ssfdc.MaxZones     = 16;
+            Ssfdc.MaxBlocks    = 1024;
+            Ssfdc.MaxLogBlocks = 1000;
+            Ssfdc.MaxSectors   = 32;
+            break;
+        case SSFDC512MB:
+            Ssfdc.Model        = SSFDC512MB;
+            Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
+            Ssfdc.MaxZones     = 32;
+            Ssfdc.MaxBlocks    = 1024;
+            Ssfdc.MaxLogBlocks = 1000;
+            Ssfdc.MaxSectors   = 32;
+            break;
+        case SSFDC1GB:
+            Ssfdc.Model        = SSFDC1GB;
+            Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
+            Ssfdc.MaxZones     = 64;
+            Ssfdc.MaxBlocks    = 1024;
+            Ssfdc.MaxLogBlocks = 1000;
+            Ssfdc.MaxSectors   = 32;
+            break;
+        case SSFDC2GB:
+            Ssfdc.Model        = SSFDC2GB;
+            Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
+            Ssfdc.MaxZones     = 128;
+            Ssfdc.MaxBlocks    = 1024;
+            Ssfdc.MaxLogBlocks = 1000;
+            Ssfdc.MaxSectors   = 32;
+            break;
+        default:
+            Ssfdc.Model = NOSSFDC;
+            return(ERROR);
+    }
+
+    return(SUCCESS);
+}
+
+//----- _Check_D_DevCode() ---------------------------------------------
+BYTE _Check_D_DevCode(BYTE dcode)
+{
+    switch(dcode){
+        case 0x6E:
+        case 0xE8:
+        case 0xEC: return(SSFDC1MB);   // 8Mbit (1M) NAND
+        case 0x64:
+        case 0xEA: return(SSFDC2MB);   // 16Mbit (2M) NAND
+        case 0x6B:
+        case 0xE3:
+        case 0xE5: return(SSFDC4MB);   // 32Mbit (4M) NAND
+        case 0xE6: return(SSFDC8MB);   // 64Mbit (8M) NAND
+        case 0x73: return(SSFDC16MB);  // 128Mbit (16M)NAND
+        case 0x75: return(SSFDC32MB);  // 256Mbit (32M)NAND
+        case 0x76: return(SSFDC64MB);  // 512Mbit (64M)NAND
+        case 0x79: return(SSFDC128MB); // 1Gbit(128M)NAND
+        case 0x71: return(SSFDC256MB);
+        case 0xDC: return(SSFDC512MB);
+        case 0xD3: return(SSFDC1GB);
+        case 0xD5: return(SSFDC2GB);
+        default: return(NOSSFDC);
+    }
+}
+/*
+////SmartMedia Power Controll Subroutine
+////----- Cnt_D_Reset() ----------------------------------------------
+//void Cnt_D_Reset(void)
+//{
+//    _Hw_D_LedOff();
+//    _Hw_D_SetRdStandby();
+//    _Hw_D_VccOff();
+//}
+//
+////----- Cnt_D_PowerOn() ----------------------------------------------
+//int Cnt_D_PowerOn(void)
+//{
+//    // No support 5V.
+//    _Hw_D_EnableVcc3VOn();                      // Set SM_REG_CTRL_5 Reg. to 3V
+//    _Hw_D_VccOn();
+//    _Hw_D_SetRdStandby();
+//    _Wait_D_Timer(TIME_PON);
+//
+//    if (_Hw_D_ChkPower())
+//    {
+//        _Hw_D_EnableOB();                       // Set SM_REG_CTRL_5 Reg. to 0x83
+//        return(SUCCESS);
+//    }
+//
+//    _Hw_D_SetVccOff();
+//    return(ERROR);
+//}
+//
+////----- Cnt_D_PowerOff() ----------------------------------------------
+//void Cnt_D_PowerOff(void)
+//{
+//    _Hw_D_SetRdStandby();
+//    _Hw_D_SetVccOff();
+//    _Hw_D_VccOff();
+//}
+//
+////----- Cnt_D_LedOn() ----------------------------------------------
+//void Cnt_D_LedOn(void)
+//{
+//    _Hw_D_LedOn();
+//}
+//
+////----- Cnt_D_LedOff() ----------------------------------------------
+//void Cnt_D_LedOff(void)
+//{
+//    _Hw_D_LedOff();
+//}
+//
+////----- Check_D_CntPower() ----------------------------------------------
+//int Check_D_CntPower(void)
+//{
+//    if (_Hw_D_ChkPower())
+//        return(SUCCESS); // Power On
+//
+//    return(ERROR);       // Power Off
+//}
+//
+////----- Check_D_CardExist() ----------------------------------------------
+//int Check_D_CardExist(void)
+//{
+//    char i,j,k;
+//
+//    if (!_Hw_D_ChkStatus()) // Not Status Change
+//        if (_Hw_D_ChkCardIn())
+//            return(SUCCESS); // Card exist in Slot
+//
+//    for(i=0,j=0,k=0; i<16; i++) {
+//        if (_Hw_D_ChkCardIn()) // Status Change
+//        {
+//            j++; k=0;
+//        }
+//        else
+//        {
+//            j=0; k++;
+//        }
+//
+//        if (j>3)
+//            return(SUCCESS); // Card exist in Slot
+//        if (k>3)
+//            return(ERROR); // NO Card exist in Slot
+//
+//        _Wait_D_Timer(TIME_CDCHK);
+//    }
+//
+//    return(ERROR);
+//}
+//
+////----- Check_D_CardStsChg() ----------------------------------------------
+//int Check_D_CardStsChg(void)
+//{
+//    if (_Hw_D_ChkStatus())
+//        return(ERROR); // Status Change
+//
+//    return(SUCCESS);   // Not Status Change
+//}
+//
+////----- Check_D_SsfdcWP() ----------------------------------------------
+//int Check_D_SsfdcWP(void)
+//{ // ERROR: WP, SUCCESS: Not WP
+//    char i;
+//
+//    for(i=0; i<8; i++) {
+//        if (_Hw_D_ChkWP())
+//            return(ERROR);
+//        _Wait_D_Timer(TIME_WPCHK);
+//    }
+//
+//    return(SUCCESS);
+//}
+//
+*/
+//SmartMedia ECC Controll Subroutine
+//----- Check_D_ReadError() ----------------------------------------------
+int Check_D_ReadError(BYTE *redundant)
+{
+    // Driver Â¤Â£Â°Âµ ECC Check
+    return(SUCCESS);
+    if (!StringCmp((char *)(redundant+0x0D),(char *)EccBuf,3))
+        if (!StringCmp((char *)(redundant+0x08),(char *)(EccBuf+0x03),3))
+            return(SUCCESS);
+
+    return(ERROR);
+}
+
+//----- Check_D_Correct() ----------------------------------------------
+int Check_D_Correct(BYTE *buf,BYTE *redundant)
+{
+    // Driver Â¤Â£Â°Âµ ECC Check
+    return(SUCCESS);
+    if (StringCmp((char *)(redundant+0x0D),(char *)EccBuf,3))
+        if (_Correct_D_SwECC(buf,redundant+0x0D,EccBuf))
+            return(ERROR);
+
+    buf+=0x100;
+    if (StringCmp((char *)(redundant+0x08),(char *)(EccBuf+0x03),3))
+        if (_Correct_D_SwECC(buf,redundant+0x08,EccBuf+0x03))
+            return(ERROR);
+
+    return(SUCCESS);
+}
+
+//----- Check_D_CISdata() ----------------------------------------------
+int Check_D_CISdata(BYTE *buf, BYTE *redundant)
+{
+    BYTE cis[]={0x01,0x03,0xD9,0x01,0xFF,0x18,0x02,0xDF,0x01,0x20};
+
+    if (!IsSSFDCCompliance && !IsXDCompliance)
+        return(SUCCESS);             // Â¥Ã˜Â«e¬°±j¨î SUCCESS [Arnold 02-08-23] SSFDC Â´ÃºÂ¸Ã•, Â¤Â£Â¯Ã Â±j¨î SUCCESS
+
+    if (!StringCmp((char *)(redundant+0x0D),(char *)EccBuf,3))
+        return(StringCmp((char *)buf,(char *)cis,10));
+
+    if (!_Correct_D_SwECC(buf,redundant+0x0D,EccBuf))
+        return(StringCmp((char *)buf,(char *)cis,10));
+
+    buf+=0x100;
+    if (!StringCmp((char *)(redundant+0x08),(char *)(EccBuf+0x03),3))
+        return(StringCmp((char *)buf,(char *)cis,10));
+
+    if (!_Correct_D_SwECC(buf,redundant+0x08,EccBuf+0x03))
+        return(StringCmp((char *)buf,(char *)cis,10));
+
+    return(ERROR);
+}
+
+//----- Set_D_RightECC() ----------------------------------------------
+void Set_D_RightECC(BYTE *redundant)
+{
+    // Driver Â¤Â£Â°Âµ ECC Check
+    return;
+    //StringCopy((char *)(redundant+0x0D),(char *)EccBuf,3);
+    //StringCopy((char *)(redundant+0x08),(char *)(EccBuf+0x03),3);
+}
+/*
+////----- _Calc_D_ECCdata() ----------------------------------------------
+//void _Calc_D_ECCdata(BYTE *buf)
+//{
+//#ifdef HW_ECC_SUPPORTED
+//#else
+//    _Calculate_D_SwECC(buf,EccBuf);
+//    buf+=0x0100;
+//    _Calculate_D_SwECC(buf,EccBuf+0x03);
+//#endif
+//}
+//
+////----- _Set_D_ECCdata() ----------------------------------------------
+//void _Set_D_ECCdata(BYTE add,BYTE *redundant)
+//{
+//    //if (add==EVEN && (Ssfdc.Attribute &MPS)==PS256)
+//    //    return;
+//
+//    // for 256byte/page
+//    StringCopy((char *)(redundant+0x0D),(char *)EccBuf,3);
+//    StringCopy((char *)(redundant+0x08),(char *)(EccBuf+0x03),3);
+//}
+*/
+//Common Subroutine
+char Bit_D_Count(BYTE cdata)
+{
+    WORD bitcount=0;
+
+    while(cdata) {
+        bitcount+=(WORD)(cdata &0x01);
+        cdata /=2;
+    }
+
+    return((char)bitcount);
+}
+
+//-----
+char Bit_D_CountWord(WORD cdata)
+{
+    WORD bitcount=0;
+
+    while(cdata) {
+        bitcount+=(cdata &0x01);
+        cdata /=2;
+    }
+
+    return((char)bitcount);
+}
+
+void StringCopy(char *stringA, char *stringB, int count)
+{
+    int i;
+
+    for(i=0; i<count; i++)
+        *stringA++ = *stringB++;
+}
+
+//-----
+int StringCmp(char *stringA, char *stringB, int count)
+{
+    int i;
+
+    for (i=0;i<count;i++)
+        if (*stringA++ != *stringB++)
+            return(ERROR);
+
+    return(SUCCESS);
+}
+/*
+//----- SM_ReadBlock() ---------------------------------------------
+int SM_ReadBlock(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant)
+{
+    PBULK_CBW               pBulkCbw = fdoExt->pBulkCbw;
+    NTSTATUS                ntStatus;
+    WORD                    addr;
+
+    ENE_LoadBinCode(fdoExt, SM_RW_PATTERN);
+
+    addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
+    addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
+
+    // Read sect data
+    RtlZeroMemory(pBulkCbw, sizeof(struct _BULK_CBW));
+    pBulkCbw->dCBWSignature          = CBW_SIGNTURE;
+    pBulkCbw->bCBWLun                = CBW_LUN;
+    pBulkCbw->dCBWDataTransferLength = 0x200;
+    pBulkCbw->bmCBWFlags             = 0x80;
+    pBulkCbw->CBWCb[0]               = 0xF1;
+    pBulkCbw->CBWCb[1]               = 0x02;
+    pBulkCbw->CBWCb[4]               = (BYTE)addr;
+    pBulkCbw->CBWCb[3]               = (BYTE)(addr/0x0100);
+    pBulkCbw->CBWCb[2]               = Media.Zone/2;
+
+    ntStatus = ENE_SendScsiCmd(fdoExt, FDIR_READ, buf);
+
+    if (!NT_SUCCESS(ntStatus))
+       return(ERROR);
+
+    // Read redundant
+    RtlZeroMemory(pBulkCbw, sizeof(struct _BULK_CBW));
+    pBulkCbw->dCBWSignature          = CBW_SIGNTURE;
+    pBulkCbw->bCBWLun                = CBW_LUN;
+    pBulkCbw->dCBWDataTransferLength = 0x10;
+    pBulkCbw->bmCBWFlags             = 0x80;
+    pBulkCbw->CBWCb[0]               = 0xF1;
+    pBulkCbw->CBWCb[1]               = 0x03;
+    pBulkCbw->CBWCb[4]               = (BYTE)addr;
+    pBulkCbw->CBWCb[3]               = (BYTE)(addr/0x0100);
+    pBulkCbw->CBWCb[2]               = Media.Zone/2;
+    pBulkCbw->CBWCb[5]               = 0;
+    pBulkCbw->CBWCb[6]               = 1;
+
+    ntStatus = ENE_SendScsiCmd(fdoExt, FDIR_READ, redundant);
+
+    if (!NT_SUCCESS(ntStatus))
+       return(ERROR);
+
+    return(SUCCESS);
+}*/
diff --git a/drivers/staging/keucr/smscsi.c b/drivers/staging/keucr/smscsi.c
new file mode 100644 (file)
index 0000000..43e32c6
--- /dev/null
@@ -0,0 +1,189 @@
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+
+#include "usb.h"
+#include "scsiglue.h"
+#include "transport.h"
+//#include "smcommon.h"
+#include "smil.h"
+
+int SM_SCSI_Test_Unit_Ready (struct us_data *us, struct scsi_cmnd *srb);
+int SM_SCSI_Inquiry         (struct us_data *us, struct scsi_cmnd *srb);
+int SM_SCSI_Mode_Sense      (struct us_data *us, struct scsi_cmnd *srb);
+int SM_SCSI_Start_Stop      (struct us_data *us, struct scsi_cmnd *srb);
+int SM_SCSI_Read_Capacity   (struct us_data *us, struct scsi_cmnd *srb);
+int SM_SCSI_Read            (struct us_data *us, struct scsi_cmnd *srb);
+int SM_SCSI_Write           (struct us_data *us, struct scsi_cmnd *srb);
+
+extern struct SSFDCTYPE     Ssfdc;
+extern struct ADDRESS       Media;
+extern PBYTE                SMHostAddr;
+extern DWORD                ErrXDCode;
+
+//----- SM_SCSIIrp() --------------------------------------------------
+int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb)
+{
+       int    result;
+
+       us->SrbStatus = SS_SUCCESS;
+       switch (srb->cmnd[0])
+       {
+               case TEST_UNIT_READY :  result = SM_SCSI_Test_Unit_Ready (us, srb);  break; //0x00
+               case INQUIRY         :  result = SM_SCSI_Inquiry         (us, srb);  break; //0x12
+               case MODE_SENSE      :  result = SM_SCSI_Mode_Sense      (us, srb);  break; //0x1A
+               case READ_CAPACITY   :  result = SM_SCSI_Read_Capacity   (us, srb);  break; //0x25
+               case READ_10         :  result = SM_SCSI_Read            (us, srb);  break; //0x28
+               case WRITE_10        :  result = SM_SCSI_Write           (us, srb);  break; //0x2A
+
+               default:
+                       us->SrbStatus = SS_ILLEGAL_REQUEST;
+                       result = USB_STOR_TRANSPORT_FAILED;
+                       break;
+       }
+       return result;
+}
+
+//----- SM_SCSI_Test_Unit_Ready() --------------------------------------------------
+int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb)
+{
+       //printk("SM_SCSI_Test_Unit_Ready\n");
+       if (us->SM_Status.Insert && us->SM_Status.Ready)
+               return USB_STOR_TRANSPORT_GOOD;
+       else
+       {
+               ENE_SMInit(us);
+               return USB_STOR_TRANSPORT_GOOD;
+       }
+               
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- SM_SCSI_Inquiry() --------------------------------------------------
+int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb)
+{
+       //printk("SM_SCSI_Inquiry\n");
+       BYTE data_ptr[36] = {0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
+
+       usb_stor_set_xfer_buf(us, data_ptr, 36, srb, TO_XFER_BUF);
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+
+//----- SM_SCSI_Mode_Sense() --------------------------------------------------
+int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb)
+{
+       BYTE    mediaNoWP[12] = {0x0b,0x00,0x00,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
+       BYTE    mediaWP[12]   = {0x0b,0x00,0x80,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
+
+       if (us->SM_Status.WtP)
+               usb_stor_set_xfer_buf(us, mediaWP, 12, srb, TO_XFER_BUF);
+       else
+               usb_stor_set_xfer_buf(us, mediaNoWP, 12, srb, TO_XFER_BUF);
+
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- SM_SCSI_Read_Capacity() --------------------------------------------------
+int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb)
+{
+       unsigned int offset = 0;
+       struct scatterlist *sg = NULL;
+       DWORD   bl_num;
+       WORD    bl_len;
+       BYTE    buf[8];
+
+       printk("SM_SCSI_Read_Capacity\n");
+
+       bl_len = 0x200;
+       bl_num = Ssfdc.MaxLogBlocks * Ssfdc.MaxSectors * Ssfdc.MaxZones - 1;
+       //printk("MaxLogBlocks = %x\n", Ssfdc.MaxLogBlocks);
+       //printk("MaxSectors   = %x\n", Ssfdc.MaxSectors);
+       //printk("MaxZones     = %x\n", Ssfdc.MaxZones);
+       //printk("bl_num       = %x\n", bl_num);
+
+       us->bl_num = bl_num;
+       printk("bl_len = %x\n", bl_len);
+       printk("bl_num = %x\n", bl_num);
+
+       //srb->request_bufflen = 8;
+       buf[0] = (bl_num>>24) & 0xff;
+       buf[1] = (bl_num>>16) & 0xff;
+       buf[2] = (bl_num>> 8) & 0xff;
+       buf[3] = (bl_num>> 0) & 0xff;
+       buf[4] = (bl_len>>24) & 0xff;
+       buf[5] = (bl_len>>16) & 0xff;
+       buf[6] = (bl_len>> 8) & 0xff;
+       buf[7] = (bl_len>> 0) & 0xff;
+       
+       usb_stor_access_xfer_buf(us, buf, 8, srb, &sg, &offset, TO_XFER_BUF);
+       //usb_stor_set_xfer_buf(us, buf, srb->request_bufflen, srb, TO_XFER_BUF);
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- SM_SCSI_Read() --------------------------------------------------
+int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb)
+{
+       //struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int result=0;
+       PBYTE   Cdb = srb->cmnd;
+       DWORD bn  =  ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
+                   ((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
+       WORD  blen = ((Cdb[7]<< 8) & 0xff00)     | ((Cdb[8]<< 0) & 0x00ff);
+       DWORD   blenByte = blen * 0x200;
+       void    *buf;
+
+       //printk("SCSIOP_READ --- bn = %X, blen = %X, srb->use_sg = %X\n", bn, blen, srb->use_sg);
+       
+       if (bn > us->bl_num)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       buf = kmalloc(blenByte, GFP_KERNEL);
+       result = Media_D_ReadSector(us, bn, blen, buf);
+       usb_stor_set_xfer_buf(us, buf, blenByte, srb, TO_XFER_BUF);
+       kfree(buf);
+
+       if (!result)
+               return USB_STOR_TRANSPORT_GOOD;
+       else
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
+//----- SM_SCSI_Write() --------------------------------------------------
+int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb)
+{
+       //struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       int result=0;
+       PBYTE   Cdb = srb->cmnd;
+       DWORD bn  =  ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
+                   ((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
+       WORD  blen = ((Cdb[7]<< 8) & 0xff00)     | ((Cdb[8]<< 0) & 0x00ff);
+       DWORD   blenByte = blen * 0x200;
+       void    *buf;
+
+       //printk("SCSIOP_Write --- bn = %X, blen = %X, srb->use_sg = %X\n", bn, blen, srb->use_sg);
+
+       if (bn > us->bl_num)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       buf = kmalloc(blenByte, GFP_KERNEL);
+       usb_stor_set_xfer_buf(us, buf, blenByte, srb, FROM_XFER_BUF);
+       result = Media_D_CopySector(us, bn, blen, buf);
+       kfree(buf);
+
+       if (!result)
+               return USB_STOR_TRANSPORT_GOOD;
+       else
+               return USB_STOR_TRANSPORT_ERROR;
+
+       return USB_STOR_TRANSPORT_GOOD;
+}
+
diff --git a/drivers/staging/keucr/transport.c b/drivers/staging/keucr/transport.c
new file mode 100644 (file)
index 0000000..7215429
--- /dev/null
@@ -0,0 +1,788 @@
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+
+#include "usb.h"
+#include "scsiglue.h"
+#include "transport.h"
+
+/***********************************************************************
+ * Data transfer routines
+ ***********************************************************************/
+//----- usb_stor_blocking_completion() ---------------------
+static void usb_stor_blocking_completion(struct urb *urb)
+{
+       struct completion *urb_done_ptr = urb->context;
+
+       //printk("transport --- usb_stor_blocking_completion\n");
+       complete(urb_done_ptr);
+}
+
+//----- usb_stor_msg_common() ---------------------
+static int usb_stor_msg_common(struct us_data *us, int timeout)
+{
+       struct completion urb_done;
+       long timeleft;
+       int status;
+
+       //printk("transport --- usb_stor_msg_common\n");
+       if (test_bit(US_FLIDX_ABORTING, &us->dflags))
+               return -EIO;
+
+       init_completion(&urb_done);
+
+       us->current_urb->context = &urb_done;
+       us->current_urb->actual_length = 0;
+       us->current_urb->error_count = 0;
+       us->current_urb->status = 0;
+
+//     us->current_urb->transfer_flags = URB_NO_SETUP_DMA_MAP;
+       if (us->current_urb->transfer_buffer == us->iobuf)
+               us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+       us->current_urb->transfer_dma = us->iobuf_dma;
+       us->current_urb->setup_dma = us->cr_dma;
+
+       status = usb_submit_urb(us->current_urb, GFP_NOIO);
+       if (status)
+               return status;
+
+       set_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
+
+       if (test_bit(US_FLIDX_ABORTING, &us->dflags))
+       {
+               if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags))
+               {
+                       //printk("-- cancelling URB\n");
+                       usb_unlink_urb(us->current_urb);
+               }
+       }
+
+       timeleft = wait_for_completion_interruptible_timeout(&urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT);
+       clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
+
+       if (timeleft <= 0)
+       {
+               //printk("%s -- cancelling URB\n", timeleft == 0 ? "Timeout" : "Signal");
+               usb_kill_urb(us->current_urb);
+       }
+
+       return us->current_urb->status;
+}
+
+//----- usb_stor_control_msg() ---------------------
+int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
+                u8 request, u8 requesttype, u16 value, u16 index,
+                void *data, u16 size, int timeout)
+{
+       int status;
+
+       //printk("transport --- usb_stor_control_msg\n");
+
+       /* fill in the devrequest structure */
+       us->cr->bRequestType = requesttype;
+       us->cr->bRequest = request;
+       us->cr->wValue = cpu_to_le16(value);
+       us->cr->wIndex = cpu_to_le16(index);
+       us->cr->wLength = cpu_to_le16(size);
+
+       /* fill and submit the URB */
+       usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
+                        (unsigned char*) us->cr, data, size,
+                        usb_stor_blocking_completion, NULL);
+       status = usb_stor_msg_common(us, timeout);
+
+       /* return the actual length of the data transferred if no error */
+       if (status == 0)
+               status = us->current_urb->actual_length;
+       return status;
+}
+
+//----- usb_stor_clear_halt() ---------------------
+int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
+{
+       int result;
+       int endp = usb_pipeendpoint(pipe);
+
+       //printk("transport --- usb_stor_clear_halt\n");
+       if (usb_pipein (pipe))
+               endp |= USB_DIR_IN;
+
+       result = usb_stor_control_msg(us, us->send_ctrl_pipe,
+               USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
+               USB_ENDPOINT_HALT, endp,
+               NULL, 0, 3*HZ);
+
+       /* reset the endpoint toggle */
+       if (result >= 0)
+               //usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
+                usb_reset_endpoint(us->pusb_dev, endp);
+
+       return result;
+}
+
+//----- interpret_urb_result() ---------------------
+static int interpret_urb_result(struct us_data *us, unsigned int pipe,
+               unsigned int length, int result, unsigned int partial)
+{
+       //printk("transport --- interpret_urb_result\n");
+       switch (result) {
+       /* no error code; did we send all the data? */
+       case 0:
+               if (partial != length)
+               {
+                       //printk("-- short transfer\n");
+                       return USB_STOR_XFER_SHORT;
+               }
+               //printk("-- transfer complete\n");
+               return USB_STOR_XFER_GOOD;
+       case -EPIPE:
+               if (usb_pipecontrol(pipe))
+               {
+                       //printk("-- stall on control pipe\n");
+                       return USB_STOR_XFER_STALLED;
+               }
+               //printk("clearing endpoint halt for pipe 0x%x\n", pipe);
+               if (usb_stor_clear_halt(us, pipe) < 0)
+                       return USB_STOR_XFER_ERROR;
+               return USB_STOR_XFER_STALLED;
+       case -EOVERFLOW:
+               //printk("-- babble\n");
+               return USB_STOR_XFER_LONG;
+       case -ECONNRESET:
+               //printk("-- transfer cancelled\n");
+               return USB_STOR_XFER_ERROR;
+       case -EREMOTEIO:
+               //printk("-- short read transfer\n");
+               return USB_STOR_XFER_SHORT;
+       case -EIO:
+               //printk("-- abort or disconnect in progress\n");
+               return USB_STOR_XFER_ERROR;
+       default:
+               //printk("-- unknown error\n");
+               return USB_STOR_XFER_ERROR;
+       }
+}
+
+//----- usb_stor_bulk_transfer_buf() ---------------------
+int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
+       void *buf, unsigned int length, unsigned int *act_len)
+{
+       int result;
+
+       //printk("transport --- usb_stor_bulk_transfer_buf\n");
+
+       /* fill and submit the URB */
+       usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length, usb_stor_blocking_completion, NULL);
+       result = usb_stor_msg_common(us, 0);
+
+       /* store the actual length of the data transferred */
+       if (act_len)
+               *act_len = us->current_urb->actual_length;
+
+       return interpret_urb_result(us, pipe, length, result, us->current_urb->actual_length);
+}
+
+//----- usb_stor_bulk_transfer_sglist() ---------------------
+static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+               struct scatterlist *sg, int num_sg, unsigned int length,
+               unsigned int *act_len)
+{
+       int result;
+
+       //printk("transport --- usb_stor_bulk_transfer_sglist\n");
+       if (test_bit(US_FLIDX_ABORTING, &us->dflags))
+               return USB_STOR_XFER_ERROR;
+
+       /* initialize the scatter-gather request block */
+       result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0, sg, num_sg, length, GFP_NOIO);
+       if (result)
+       {
+               //printk("usb_sg_init returned %d\n", result);
+               return USB_STOR_XFER_ERROR;
+       }
+
+       /* since the block has been initialized successfully, it's now okay to cancel it */
+       set_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
+
+       /* did an abort/disconnect occur during the submission? */
+       if (test_bit(US_FLIDX_ABORTING, &us->dflags))
+       {
+               /* cancel the request, if it hasn't been cancelled already */
+               if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags))
+               {
+                       //printk("-- cancelling sg request\n");
+                       usb_sg_cancel(&us->current_sg);
+               }
+       }
+
+       /* wait for the completion of the transfer */
+       usb_sg_wait(&us->current_sg);
+       clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
+
+       result = us->current_sg.status;
+       if (act_len)
+               *act_len = us->current_sg.bytes;
+
+       return interpret_urb_result(us, pipe, length, result, us->current_sg.bytes);
+}
+
+//----- usb_stor_bulk_srb() ---------------------
+int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe, struct scsi_cmnd* srb)
+{
+       unsigned int partial;
+       int result = usb_stor_bulk_transfer_sglist(us, pipe, scsi_sglist(srb),
+                                     scsi_sg_count(srb), scsi_bufflen(srb),
+                                     &partial);
+
+       scsi_set_resid(srb, scsi_bufflen(srb) - partial);
+       return result;
+}
+
+//----- usb_stor_bulk_transfer_sg() ---------------------
+int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
+               void *buf, unsigned int length_left, int use_sg, int *residual)
+{
+       int result;
+       unsigned int partial;
+
+       //printk("transport --- usb_stor_bulk_transfer_sg\n");
+       /* are we scatter-gathering? */
+       if (use_sg)
+       {
+               /* use the usb core scatter-gather primitives */
+               result = usb_stor_bulk_transfer_sglist(us, pipe,
+                               (struct scatterlist *) buf, use_sg,
+                               length_left, &partial);
+               length_left -= partial;
+       }
+       else
+       {
+               /* no scatter-gather, just make the request */
+               result = usb_stor_bulk_transfer_buf(us, pipe, buf, length_left, &partial);
+               length_left -= partial;
+       }
+
+       /* store the residual and return the error code */
+       if (residual)
+               *residual = length_left;
+       return result;
+}
+
+/***********************************************************************
+ * Transport routines
+ ***********************************************************************/
+//----- usb_stor_invoke_transport() ---------------------
+void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+       int need_auto_sense;
+       int result;
+
+       //printk("transport --- usb_stor_invoke_transport\n");
+       usb_stor_print_cmd(srb);
+       /* send the command to the transport layer */
+       scsi_set_resid(srb, 0);
+       result = us->transport(srb, us); //usb_stor_Bulk_transport;
+       
+       /* if the command gets aborted by the higher layers, we need to short-circuit all other processing */
+       if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags))
+       {
+               //printk("-- command was aborted\n");
+               srb->result = DID_ABORT << 16;
+               goto Handle_Errors;
+       }
+
+       /* if there is a transport error, reset and don't auto-sense */
+       if (result == USB_STOR_TRANSPORT_ERROR)
+       {
+               //printk("-- transport indicates error, resetting\n");
+               srb->result = DID_ERROR << 16;
+               goto Handle_Errors;
+       }
+
+       /* if the transport provided its own sense data, don't auto-sense */
+       if (result == USB_STOR_TRANSPORT_NO_SENSE)
+       {
+               srb->result = SAM_STAT_CHECK_CONDITION;
+               return;
+       }
+
+       srb->result = SAM_STAT_GOOD;
+
+       /* Determine if we need to auto-sense */
+       need_auto_sense = 0;
+
+       if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) && srb->sc_data_direction != DMA_FROM_DEVICE)
+       {
+               //printk("-- CB transport device requiring auto-sense\n");
+               need_auto_sense = 1;
+       }
+
+       if (result == USB_STOR_TRANSPORT_FAILED)
+       {
+               //printk("-- transport indicates command failure\n");
+               need_auto_sense = 1;
+       }
+
+       /* Now, if we need to do the auto-sense, let's do it */
+       if (need_auto_sense)
+       {
+               int temp_result;
+               struct scsi_eh_save ses;
+
+               printk("Issuing auto-REQUEST_SENSE\n");
+
+               scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE);
+
+               /* we must do the protocol translation here */
+               if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI || us->subclass == US_SC_CYP_ATACB)
+                       srb->cmd_len = 6;
+               else
+                       srb->cmd_len = 12;
+
+               /* issue the auto-sense command */
+               scsi_set_resid(srb, 0);
+               temp_result = us->transport(us->srb, us);
+
+               /* let's clean up right away */
+               scsi_eh_restore_cmnd(srb, &ses);
+
+               if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags))
+               {
+                       //printk("-- auto-sense aborted\n");
+                       srb->result = DID_ABORT << 16;
+                       goto Handle_Errors;
+               }
+               if (temp_result != USB_STOR_TRANSPORT_GOOD)
+               {
+                       //printk("-- auto-sense failure\n");
+                       srb->result = DID_ERROR << 16;
+                       if (!(us->fflags & US_FL_SCM_MULT_TARG))
+                               goto Handle_Errors;
+                       return;
+               }
+
+               /* set the result so the higher layers expect this data */
+               srb->result = SAM_STAT_CHECK_CONDITION;
+
+               if (result == USB_STOR_TRANSPORT_GOOD &&
+                       (srb->sense_buffer[2] & 0xaf) == 0 &&
+                       srb->sense_buffer[12] == 0 &&
+                       srb->sense_buffer[13] == 0)
+               {
+                       srb->result = SAM_STAT_GOOD;
+                       srb->sense_buffer[0] = 0x0;
+               }
+       }
+
+       /* Did we transfer less than the minimum amount required? */
+       if (srb->result == SAM_STAT_GOOD &&     scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
+               srb->result = (DID_ERROR << 16);//v02 | (SUGGEST_RETRY << 24);
+
+       return;
+
+Handle_Errors:
+       scsi_lock(us_to_host(us));
+       set_bit(US_FLIDX_RESETTING, &us->dflags);
+       clear_bit(US_FLIDX_ABORTING, &us->dflags);
+       scsi_unlock(us_to_host(us));
+
+       mutex_unlock(&us->dev_mutex);
+       result = usb_stor_port_reset(us);
+       mutex_lock(&us->dev_mutex);
+
+       if (result < 0)
+       {
+               scsi_lock(us_to_host(us));
+               usb_stor_report_device_reset(us);
+               scsi_unlock(us_to_host(us));
+               us->transport_reset(us);
+       }
+       clear_bit(US_FLIDX_RESETTING, &us->dflags);
+}
+
+//----- ENE_stor_invoke_transport() ---------------------
+void ENE_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+       int result=0;
+
+       //printk("transport --- ENE_stor_invoke_transport\n");
+       usb_stor_print_cmd(srb);
+       /* send the command to the transport layer */
+       scsi_set_resid(srb, 0);
+       if ( !(us->SD_Status.Ready || us->MS_Status.Ready || us->SM_Status.Ready) )
+               result = ENE_InitMedia(us);
+       
+       if (us->Power_IsResum == true) {
+               result = ENE_InitMedia(us);
+               us->Power_IsResum = false;              
+       }       
+       
+       if (us->SD_Status.Ready)        result = SD_SCSIIrp(us, srb);
+       if (us->MS_Status.Ready)        result = MS_SCSIIrp(us, srb);
+       if (us->SM_Status.Ready)        result = SM_SCSIIrp(us, srb);
+
+       /* if the command gets aborted by the higher layers, we need to short-circuit all other processing */
+       if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags))
+       {
+               //printk("-- command was aborted\n");
+               srb->result = DID_ABORT << 16;
+               goto Handle_Errors;
+       }
+
+       /* if there is a transport error, reset and don't auto-sense */
+       if (result == USB_STOR_TRANSPORT_ERROR)
+       {
+               //printk("-- transport indicates error, resetting\n");
+               srb->result = DID_ERROR << 16;
+               goto Handle_Errors;
+       }
+
+       /* if the transport provided its own sense data, don't auto-sense */
+       if (result == USB_STOR_TRANSPORT_NO_SENSE)
+       {
+               srb->result = SAM_STAT_CHECK_CONDITION;
+               return;
+       }
+
+       srb->result = SAM_STAT_GOOD;
+       if (result == USB_STOR_TRANSPORT_FAILED)
+       {
+               //printk("-- transport indicates command failure\n");
+               //need_auto_sense = 1;
+               BuildSenseBuffer(srb, us->SrbStatus);
+               srb->result = SAM_STAT_CHECK_CONDITION;
+       }
+
+       /* Did we transfer less than the minimum amount required? */
+       if (srb->result == SAM_STAT_GOOD && scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
+               srb->result = (DID_ERROR << 16);//v02 | (SUGGEST_RETRY << 24);
+
+       return;
+
+Handle_Errors:
+       scsi_lock(us_to_host(us));
+       set_bit(US_FLIDX_RESETTING, &us->dflags);
+       clear_bit(US_FLIDX_ABORTING, &us->dflags);
+       scsi_unlock(us_to_host(us));
+
+       mutex_unlock(&us->dev_mutex);
+       result = usb_stor_port_reset(us);
+       mutex_lock(&us->dev_mutex);
+
+       if (result < 0)
+       {
+               scsi_lock(us_to_host(us));
+               usb_stor_report_device_reset(us);
+               scsi_unlock(us_to_host(us));
+               us->transport_reset(us);
+       }
+       clear_bit(US_FLIDX_RESETTING, &us->dflags);
+}
+
+//----- BuildSenseBuffer() -------------------------------------------
+void BuildSenseBuffer(struct scsi_cmnd *srb, int SrbStatus)
+{
+    BYTE    *buf = srb->sense_buffer;
+    BYTE    asc;
+
+    printk("transport --- BuildSenseBuffer\n");
+    switch (SrbStatus)
+    {
+        case SS_NOT_READY:        asc = 0x3a;    break;  // sense key = 0x02
+        case SS_MEDIUM_ERR:       asc = 0x0c;    break;  // sense key = 0x03
+        case SS_ILLEGAL_REQUEST:  asc = 0x20;    break;  // sense key = 0x05
+        default:                  asc = 0x00;    break;  // ??
+    }
+
+    memset(buf, 0, 18);
+    buf[0x00] = 0xf0;
+    buf[0x02] = SrbStatus;
+    buf[0x07] = 0x0b;
+    buf[0x0c] = asc;
+}
+
+//----- usb_stor_stop_transport() ---------------------
+void usb_stor_stop_transport(struct us_data *us)
+{
+       //printk("transport --- usb_stor_stop_transport\n");
+
+       if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags))
+       {
+               //printk("-- cancelling URB\n");
+               usb_unlink_urb(us->current_urb);
+       }
+
+       if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags))
+       {
+               //printk("-- cancelling sg request\n");
+               usb_sg_cancel(&us->current_sg);
+       }
+}
+
+//----- usb_stor_Bulk_max_lun() ---------------------
+int usb_stor_Bulk_max_lun(struct us_data *us)
+{
+       int result;
+
+       //printk("transport --- usb_stor_Bulk_max_lun\n");
+       /* issue the command */
+       us->iobuf[0] = 0;
+       result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
+                                US_BULK_GET_MAX_LUN,
+                                USB_DIR_IN | USB_TYPE_CLASS |
+                                USB_RECIP_INTERFACE,
+                                0, us->ifnum, us->iobuf, 1, HZ);
+
+       //printk("GetMaxLUN command result is %d, data is %d\n", result, us->iobuf[0]);
+
+       /* if we have a successful request, return the result */
+       if (result > 0)
+               return us->iobuf[0];
+
+       return 0;
+}
+
+//----- usb_stor_Bulk_transport() ---------------------
+int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
+       unsigned int transfer_length = scsi_bufflen(srb);
+       unsigned int residue;
+       int result;
+       int fake_sense = 0;
+       unsigned int cswlen;
+       unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
+
+       //printk("transport --- usb_stor_Bulk_transport\n");
+       /* Take care of BULK32 devices; set extra byte to 0 */
+       if (unlikely(us->fflags & US_FL_BULK32))
+       {
+               cbwlen = 32;
+               us->iobuf[31] = 0;
+       }
+
+       /* set up the command wrapper */
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = cpu_to_le32(transfer_length);
+       bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
+       bcb->Tag = ++us->tag;
+       bcb->Lun = srb->device->lun;
+       if (us->fflags & US_FL_SCM_MULT_TARG)
+               bcb->Lun |= srb->device->id << 4;
+       bcb->Length = srb->cmd_len;
+
+       /* copy the command payload */
+       memset(bcb->CDB, 0, sizeof(bcb->CDB));
+       memcpy(bcb->CDB, srb->cmnd, bcb->Length);
+
+       // send command
+       /* send it to out endpoint */
+       /*printk("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
+                       le32_to_cpu(bcb->Signature), bcb->Tag,
+                       le32_to_cpu(bcb->DataTransferLength), bcb->Flags,
+                       (bcb->Lun >> 4), (bcb->Lun & 0x0F),
+                       bcb->Length);*/
+       result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, cbwlen, NULL);
+       //printk("Bulk command transfer result=%d\n", result);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       if (unlikely(us->fflags & US_FL_GO_SLOW))
+               udelay(125);
+
+       // R/W data
+       if (transfer_length)
+       {
+               unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? us->recv_bulk_pipe : us->send_bulk_pipe;
+               result = usb_stor_bulk_srb(us, pipe, srb);
+               //printk("Bulk data transfer result 0x%x\n", result);
+               if (result == USB_STOR_XFER_ERROR)
+                       return USB_STOR_TRANSPORT_ERROR;
+
+               if (result == USB_STOR_XFER_LONG)
+                       fake_sense = 1;
+       }
+
+       /* get CSW for device status */
+       //printk("Attempting to get CSW...\n");
+       result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, &cswlen);
+
+       if (result == USB_STOR_XFER_SHORT && cswlen == 0)
+       {
+               //printk("Received 0-length CSW; retrying...\n");
+               result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, &cswlen);
+       }
+
+       /* did the attempt to read the CSW fail? */
+       if (result == USB_STOR_XFER_STALLED)
+       {
+               /* get the status again */
+               //printk("Attempting to get CSW (2nd try)...\n");
+               result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, NULL);
+       }
+
+       /* if we still have a failure at this point, we're in trouble */
+       //printk("Bulk status result = %d\n", result);
+       if (result != USB_STOR_XFER_GOOD)
+               return USB_STOR_TRANSPORT_ERROR;
+
+       /* check bulk status */
+       residue = le32_to_cpu(bcs->Residue);
+       //printk("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", le32_to_cpu(bcs->Signature), bcs->Tag, residue, bcs->Status);
+       if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) || bcs->Status > US_BULK_STAT_PHASE)
+       {
+               //printk("Bulk logical error\n");
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       if (!us->bcs_signature)
+       {
+               us->bcs_signature = bcs->Signature;
+               //if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN))
+               //      printk("Learnt BCS signature 0x%08X\n", le32_to_cpu(us->bcs_signature));
+       }
+       else if (bcs->Signature != us->bcs_signature)
+       {
+               /*printk("Signature mismatch: got %08X, expecting %08X\n",
+                         le32_to_cpu(bcs->Signature),
+                         le32_to_cpu(us->bcs_signature));*/
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+
+       /* try to compute the actual residue, based on how much data
+        * was really transferred and what the device tells us */
+       if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE))
+       {
+
+               /* Heuristically detect devices that generate bogus residues
+                * by seeing what happens with INQUIRY and READ CAPACITY
+                * commands.
+                */
+               if (bcs->Status == US_BULK_STAT_OK &&
+                               scsi_get_resid(srb) == 0 &&
+                                       ((srb->cmnd[0] == INQUIRY &&
+                                               transfer_length == 36) ||
+                                       (srb->cmnd[0] == READ_CAPACITY &&
+                                               transfer_length == 8)))
+               {
+                       us->fflags |= US_FL_IGNORE_RESIDUE;
+
+               }
+               else
+               {
+                       residue = min(residue, transfer_length);
+                       scsi_set_resid(srb, max(scsi_get_resid(srb), (int) residue));
+               }
+       }
+
+       /* based on the status code, we report good or bad */
+       switch (bcs->Status)
+       {
+               case US_BULK_STAT_OK:
+                       if (fake_sense)
+                       {
+                               memcpy(srb->sense_buffer, usb_stor_sense_invalidCDB, sizeof(usb_stor_sense_invalidCDB));
+                               return USB_STOR_TRANSPORT_NO_SENSE;
+                       }
+                       return USB_STOR_TRANSPORT_GOOD;
+
+               case US_BULK_STAT_FAIL:
+                       return USB_STOR_TRANSPORT_FAILED;
+
+               case US_BULK_STAT_PHASE:
+                       return USB_STOR_TRANSPORT_ERROR;
+       }
+       return USB_STOR_TRANSPORT_ERROR;
+}
+
+/***********************************************************************
+ * Reset routines
+ ***********************************************************************/
+//----- usb_stor_reset_common() ---------------------
+static int usb_stor_reset_common(struct us_data *us,
+               u8 request, u8 requesttype,
+               u16 value, u16 index, void *data, u16 size)
+{
+       int result;
+       int result2;
+
+       //printk("transport --- usb_stor_reset_common\n");
+       if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags))
+       {
+               //printk("No reset during disconnect\n");
+               return -EIO;
+       }
+
+       result = usb_stor_control_msg(us, us->send_ctrl_pipe, request, requesttype, value, index, data, size,   5*HZ);
+       if (result < 0)
+       {
+               //printk("Soft reset failed: %d\n", result);
+               return result;
+       }
+
+       wait_event_interruptible_timeout(us->delay_wait, test_bit(US_FLIDX_DISCONNECTING, &us->dflags), HZ*6);
+       if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags))
+       {
+               //printk("Reset interrupted by disconnect\n");
+               return -EIO;
+       }
+
+       //printk("Soft reset: clearing bulk-in endpoint halt\n");
+       result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
+
+       //printk("Soft reset: clearing bulk-out endpoint halt\n");
+       result2 = usb_stor_clear_halt(us, us->send_bulk_pipe);
+
+       /* return a result code based on the result of the clear-halts */
+       if (result >= 0)
+               result = result2;
+       //if (result < 0)
+       //      printk("Soft reset failed\n");
+       //else
+       //      printk("Soft reset done\n");
+       return result;
+}
+
+//----- usb_stor_Bulk_reset() ---------------------
+int usb_stor_Bulk_reset(struct us_data *us)
+{
+       //printk("transport --- usb_stor_Bulk_reset\n");
+       return usb_stor_reset_common(us, US_BULK_RESET_REQUEST,
+                                USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                                0, us->ifnum, NULL, 0);
+}
+
+//----- usb_stor_port_reset() ---------------------
+int usb_stor_port_reset(struct us_data *us)
+{
+       int result, rc_lock;
+
+       //printk("transport --- usb_stor_port_reset\n");
+       result = rc_lock = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
+       if (result < 0)
+               printk("unable to lock device for reset: %d\n", result);
+       else
+       {
+               /* Were we disconnected while waiting for the lock? */
+               if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags))
+               {
+                       result = -EIO;
+                       //printk("No reset during disconnect\n");
+               }
+               else
+               {
+                       result = usb_reset_device(us->pusb_dev);
+                       //printk("usb_reset_composite_device returns %d\n", result);
+               }
+               if (rc_lock)
+                       usb_unlock_device(us->pusb_dev);
+       }
+       return result;
+}
+
+
diff --git a/drivers/staging/keucr/transport.h b/drivers/staging/keucr/transport.h
new file mode 100644 (file)
index 0000000..ae9b5ee
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef _TRANSPORT_H_
+#define _TRANSPORT_H_
+
+#include <linux/blkdev.h>
+
+/* Bulk only data structures */
+
+/* command block wrapper */
+struct bulk_cb_wrap {
+       __le32  Signature;                      /* contains 'USBC' */
+       __u32   Tag;                                    /* unique per command id */
+       __le32  DataTransferLength;     /* size of data */
+       __u8    Flags;                          /* direction in bit 0 */
+       __u8    Lun;                                    /* LUN normally 0 */
+       __u8    Length;                         /* of of the CDB */
+       __u8    CDB[16];                                /* max command */
+};
+
+#define US_BULK_CB_WRAP_LEN    31
+#define US_BULK_CB_SIGN                0x43425355      /*spells out USBC */
+#define US_BULK_FLAG_IN                1
+#define US_BULK_FLAG_OUT       0
+
+/* command status wrapper */
+struct bulk_cs_wrap {
+       __le32  Signature;              /* should = 'USBS' */
+       __u32           Tag;                    /* same as original command */
+       __le32  Residue;                /* amount not transferred */
+       __u8            Status;         /* see below */
+       __u8            Filler[18];
+};
+
+#define US_BULK_CS_WRAP_LEN    13
+#define US_BULK_CS_SIGN                0x53425355      /* spells out 'USBS' */
+#define US_BULK_STAT_OK                0
+#define US_BULK_STAT_FAIL      1
+#define US_BULK_STAT_PHASE     2
+
+/* bulk-only class specific requests */
+#define US_BULK_RESET_REQUEST  0xff
+#define US_BULK_GET_MAX_LUN    0xfe
+
+/* usb_stor_bulk_transfer_xxx() return codes, in order of severity */
+#define USB_STOR_XFER_GOOD     0       /* good transfer                 */
+#define USB_STOR_XFER_SHORT    1       /* transferred less than expected */
+#define USB_STOR_XFER_STALLED  2       /* endpoint stalled              */
+#define USB_STOR_XFER_LONG     3       /* device tried to send too much */
+#define USB_STOR_XFER_ERROR    4       /* transfer died in the middle   */
+
+/* Transport return codes */
+#define USB_STOR_TRANSPORT_GOOD        0       /* Transport good, command good */
+#define USB_STOR_TRANSPORT_FAILED      1       /* Transport good, command failed   */
+#define USB_STOR_TRANSPORT_NO_SENSE    2       /* Command failed, no auto-sense    */
+#define USB_STOR_TRANSPORT_ERROR       3       /* Transport bad (i.e. device dead) */
+
+/*
+ * We used to have USB_STOR_XFER_ABORTED and USB_STOR_TRANSPORT_ABORTED
+ * return codes.  But now the transport and low-level transfer routines
+ * treat an abort as just another error (-ENOENT for a cancelled URB).
+ * It is up to the invoke_transport() function to test for aborts and
+ * distinguish them from genuine communication errors.
+ */
+
+/* CBI accept device specific command */
+#define US_CBI_ADSC            0
+extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data*);
+extern int usb_stor_Bulk_max_lun(struct us_data*);
+extern int usb_stor_Bulk_reset(struct us_data*);
+extern void usb_stor_print_cmd(struct scsi_cmnd *);
+extern void usb_stor_invoke_transport(struct scsi_cmnd *, struct us_data*);
+extern void usb_stor_stop_transport(struct us_data*);
+extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
+               u8 request, u8 requesttype, u16 value, u16 index,
+               void *data, u16 size, int timeout);
+extern int usb_stor_clear_halt(struct us_data *us, unsigned int pipe);
+extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
+               void *buf, unsigned int length, unsigned int *act_len);
+extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
+               void *buf, unsigned int length, int use_sg, int *residual);
+extern int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe,
+               struct scsi_cmnd* srb);
+extern int usb_stor_port_reset(struct us_data *us);
+
+/* Protocol handling routines */
+enum xfer_buf_dir      {TO_XFER_BUF, FROM_XFER_BUF};
+extern unsigned int usb_stor_access_xfer_buf(struct us_data*, unsigned char *buffer,
+       unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **,
+       unsigned int *offset, enum xfer_buf_dir dir);
+extern void usb_stor_set_xfer_buf(struct us_data*, unsigned char *buffer, unsigned int buflen, struct scsi_cmnd *srb,
+       unsigned int dir);
+
+// ENE scsi function
+extern void ENE_stor_invoke_transport(struct scsi_cmnd *, struct us_data*);
+extern int ENE_InitMedia(struct us_data*);
+extern int ENE_SDInit(struct us_data*);
+extern int ENE_MSInit(struct us_data*);
+extern int ENE_SMInit(struct us_data*);
+extern int ENE_ReadSDReg(struct us_data*, u8*);
+extern int ENE_SendScsiCmd(struct us_data*, BYTE, void*, int);
+extern int ENE_LoadBinCode(struct us_data*, BYTE);
+extern int ENE_Read_BYTE(struct us_data*, WORD index, void *buf);
+extern int ENE_Read_Data(struct us_data*, void *buf, unsigned int length);
+extern int ENE_Write_Data(struct us_data*, void *buf, unsigned int length);
+extern void BuildSenseBuffer(struct scsi_cmnd *, int);
+
+// ENE scsi function
+extern int SD_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
+extern int MS_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
+extern int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
+
+// ENE MS function
+extern int     MS_CardInit(struct us_data *us);
+extern void    MS_LibFreeAllocatedArea(struct us_data *us);
+extern void    MS_LibFreeWriteBuf(struct us_data *us);
+extern int     MS_LibFreeLogicalMap(struct us_data *us);
+extern int     MS_LibForceSetLogicalPair(struct us_data *us, WORD logblk, WORD phyblk);
+extern int     MS_ReaderReadPage(struct us_data *us, DWORD PhyBlockAddr, BYTE PageNum, DWORD *PageBuf, MS_LibTypeExtdat *ExtraDat);
+extern int     MS_ReaderCopyBlock(struct us_data *us, WORD oldphy, WORD newphy, WORD PhyBlockAddr, BYTE PageNum, PBYTE buf, WORD len);
+extern int     MS_ReaderEraseBlock(struct us_data *us, DWORD PhyBlockAddr);
+extern int     MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData);
+extern int     MS_LibAllocLogicalMap(struct us_data *us);
+extern int     MS_LibSetBootBlockMark(struct us_data *us, WORD phyblk);
+extern int     MS_LibSetLogicalBlockMark(struct us_data *us, WORD phyblk, WORD mark);
+extern int     MS_LibSetInitialErrorBlock(struct us_data *us, WORD phyblk);
+extern int     MS_LibScanLogicalBlockNumber(struct us_data *us, WORD phyblk);
+extern int     MS_LibAllocWriteBuf(struct us_data *us);
+void           MS_LibClearWriteBuf(struct us_data *us);
+void           MS_LibPhy2LogRange(WORD PhyBlock, WORD *LogStart, WORD *LogEnde);
+extern int     MS_LibReadExtra(struct us_data *us, DWORD PhyBlock, BYTE PageNum, MS_LibTypeExtdat *ExtraDat);
+extern int     MS_LibReadExtraBlock(struct us_data *us, DWORD PhyBlock, BYTE PageNum, BYTE blen, void *buf);
+extern int     MS_LibSetAcquiredErrorBlock(struct us_data *us, WORD phyblk);
+extern int     MS_LibErasePhyBlock(struct us_data *us, WORD phyblk);
+extern int     MS_LibErrorPhyBlock(struct us_data *us, WORD phyblk);
+extern int     MS_LibOverwriteExtra(struct us_data *us, DWORD PhyBlockAddr, BYTE PageNum, BYTE OverwriteFlag);
+extern int     MS_LibSetLogicalPair(struct us_data *us, WORD logblk, WORD phyblk);
+extern int     MS_LibCheckDisableBlock(struct us_data *us, WORD PhyBlock);
+extern int     MS_CountFreeBlock(struct us_data *us, WORD PhyBlock);
+extern int     MS_LibSearchBlockFromLogical(struct us_data *us, WORD logblk);
+extern int     MS_LibSearchBlockFromPhysical(struct us_data *us, WORD phyblk);
+
+// ENE SM function
+extern int     SM_FreeMem(void);
+
+#endif
diff --git a/drivers/staging/keucr/usb.c b/drivers/staging/keucr/usb.c
new file mode 100644 (file)
index 0000000..d7dab72
--- /dev/null
@@ -0,0 +1,701 @@
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/freezer.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include <linux/utsname.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
+#include "usb.h"
+#include "scsiglue.h"
+#include "transport.h"
+
+/* Some informational data */
+MODULE_AUTHOR("Domao");
+MODULE_DESCRIPTION("ENE USB Mass Storage driver for Linux");
+MODULE_LICENSE("GPL");
+
+static struct usb_device_id eucr_usb_ids [] = {
+       { USB_DEVICE(0x058f, 0x6366) },
+       { USB_DEVICE(0x0cf2, 0x6230) },
+       { USB_DEVICE(0x0cf2, 0x6250) },
+       { }                                            /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, eucr_usb_ids);
+
+
+
+int eucr_suspend(struct usb_interface *iface, pm_message_t message)
+{
+       struct us_data *us = usb_get_intfdata(iface);
+       printk("--- eucr_suspend ---\n");
+       /* Wait until no command is running */
+       mutex_lock(&us->dev_mutex);
+
+       //US_DEBUGP("%s\n", __func__);
+       if (us->suspend_resume_hook)
+               (us->suspend_resume_hook)(us, US_SUSPEND);
+
+       /* When runtime PM is working, we'll set a flag to indicate
+        * whether we should autoresume when a SCSI request arrives. */
+       // us->Power_IsResum = true;
+       //us->SD_Status.Ready = 0;
+
+       mutex_unlock(&us->dev_mutex);
+       return 0;
+}
+//EXPORT_SYMBOL_GPL(eucr_suspend);
+
+int eucr_resume(struct usb_interface *iface)
+{
+       BYTE    tmp = 0;
+
+       struct us_data *us = usb_get_intfdata(iface);
+       printk("--- eucr_resume---\n");
+       mutex_lock(&us->dev_mutex);
+
+       //US_DEBUGP("%s\n", __func__);
+       if (us->suspend_resume_hook)
+               (us->suspend_resume_hook)(us, US_RESUME);
+
+
+       mutex_unlock(&us->dev_mutex);
+
+       
+         us->Power_IsResum = true;
+       //
+       //us->SD_Status.Ready = 0; //??
+       us->SD_Status = *(PSD_STATUS)&tmp;
+       us->MS_Status = *(PMS_STATUS)&tmp;
+       us->SM_Status = *(PSM_STATUS)&tmp;
+       
+       return 0;
+}
+//EXPORT_SYMBOL_GPL(eucr_resume);
+int eucr_reset_resume(struct usb_interface *iface)
+{
+       BYTE    tmp = 0;
+       struct us_data *us = usb_get_intfdata(iface);
+
+       printk("--- eucr_reset_resume---\n");
+       //US_DEBUGP("%s\n", __func__);
+
+       /* Report the reset to the SCSI core */
+       usb_stor_report_bus_reset(us);
+
+       /* FIXME: Notify the subdrivers that they need to reinitialize
+        * the device */
+       //ENE_InitMedia(us);
+       us->Power_IsResum = true;
+       //
+       //us->SD_Status.Ready = 0; //??
+       us->SD_Status = *(PSD_STATUS)&tmp;
+       us->MS_Status = *(PMS_STATUS)&tmp;
+       us->SM_Status = *(PSM_STATUS)&tmp;
+       return 0;
+}
+//EXPORT_SYMBOL_GPL(usb_stor_reset_resume);
+
+//----- eucr_pre_reset() ---------------------
+static int eucr_pre_reset(struct usb_interface *iface)
+{
+       struct us_data *us = usb_get_intfdata(iface);
+
+      printk("usb --- eucr_pre_reset\n");
+
+       /* Make sure no command runs during the reset */
+       mutex_lock(&us->dev_mutex);
+       return 0;
+}
+
+//----- eucr_post_reset() ---------------------
+static int eucr_post_reset(struct usb_interface *iface)
+{
+       struct us_data *us = usb_get_intfdata(iface);
+
+      printk("usb --- eucr_post_reset\n");
+
+       /* Report the reset to the SCSI core */
+       usb_stor_report_bus_reset(us);
+
+       mutex_unlock(&us->dev_mutex);
+       return 0;
+}
+
+//----- fill_inquiry_response() ---------------------
+void fill_inquiry_response(struct us_data *us, unsigned char *data, unsigned int data_len)
+{
+      printk("usb --- fill_inquiry_response\n");
+       if (data_len<36) // You lose.
+               return;
+
+       if (data[0]&0x20)
+       {
+               memset(data+8,0,28);
+       }
+       else
+       {
+               u16 bcdDevice = le16_to_cpu(us->pusb_dev->descriptor.bcdDevice);
+               memcpy(data+8, us->unusual_dev->vendorName,
+                       strlen(us->unusual_dev->vendorName) > 8 ? 8 :
+                       strlen(us->unusual_dev->vendorName));
+               memcpy(data+16, us->unusual_dev->productName,
+                       strlen(us->unusual_dev->productName) > 16 ? 16 :
+                       strlen(us->unusual_dev->productName));
+               data[32] = 0x30 + ((bcdDevice>>12) & 0x0F);
+               data[33] = 0x30 + ((bcdDevice>>8) & 0x0F);
+               data[34] = 0x30 + ((bcdDevice>>4) & 0x0F);
+               data[35] = 0x30 + ((bcdDevice) & 0x0F);
+       }
+       usb_stor_set_xfer_buf(us, data, data_len, us->srb, TO_XFER_BUF);
+}
+
+//----- usb_stor_control_thread() ---------------------
+static int usb_stor_control_thread(void * __us)
+{
+       struct us_data *us = (struct us_data *)__us;
+       struct Scsi_Host *host = us_to_host(us);
+
+      printk("usb --- usb_stor_control_thread\n");
+       for(;;)
+       {
+               if (wait_for_completion_interruptible(&us->cmnd_ready))
+                       break;
+                       
+               /* lock the device pointers */
+               mutex_lock(&(us->dev_mutex));
+
+               /* if the device has disconnected, we are free to exit */
+/*             if (test_bit(US_FLIDX_DISCONNECTING, &us->flags))
+               {
+                       mutex_unlock(&us->dev_mutex);
+                       break;
+               }*/
+
+               /* lock access to the state */
+               scsi_lock(host);
+
+               /* When we are called with no command pending, we're done */
+               if (us->srb == NULL)
+               {
+                       scsi_unlock(host);
+                       mutex_unlock(&us->dev_mutex);
+                       //US_DEBUGP("-- exiting\n");
+                       break;
+               }
+
+               /* has the command timed out *already* ? */
+               if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags))
+               {
+                       us->srb->result = DID_ABORT << 16;
+                       goto SkipForAbort;
+               }
+
+               scsi_unlock(host);
+
+               if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL)
+               {
+                       us->srb->result = DID_ERROR << 16;
+               }
+               else if (us->srb->device->id && !(us->fflags & US_FL_SCM_MULT_TARG))
+               {
+                       us->srb->result = DID_BAD_TARGET << 16;
+               }
+               else if (us->srb->device->lun > us->max_lun)
+               {
+                       us->srb->result = DID_BAD_TARGET << 16;
+               }
+               else if ((us->srb->cmnd[0] == INQUIRY) && (us->fflags & US_FL_FIX_INQUIRY))
+               {
+                       unsigned char data_ptr[36] = {0x00, 0x80, 0x02, 0x02, 0x1F, 0x00, 0x00, 0x00};
+
+                       fill_inquiry_response(us, data_ptr, 36);
+                       us->srb->result = SAM_STAT_GOOD;
+               }
+               else
+               {
+                       us->proto_handler(us->srb, us);
+               }
+
+               /* lock access to the state */
+               scsi_lock(host);
+
+               /* indicate that the command is done */
+               if (us->srb->result != DID_ABORT << 16)
+               {
+                       us->srb->scsi_done(us->srb);
+               }
+               else
+               {
+SkipForAbort:
+                       printk("scsi command aborted\n");
+               }
+
+               if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags))
+               {
+                       complete(&(us->notify));
+
+                       /* Allow USB transfers to resume */
+                       clear_bit(US_FLIDX_ABORTING, &us->dflags);
+                       clear_bit(US_FLIDX_TIMED_OUT, &us->dflags);
+               }
+
+               /* finished working on this command */
+               us->srb = NULL;
+               scsi_unlock(host);
+
+               /* unlock the device pointers */
+               mutex_unlock(&us->dev_mutex);
+       } /* for (;;) */
+
+       /* Wait until we are told to stop */
+       for (;;)
+       {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (kthread_should_stop())
+                       break;
+               schedule();
+       }
+       __set_current_state(TASK_RUNNING);
+       return 0;
+}      
+
+//----- associate_dev() ---------------------
+static int associate_dev(struct us_data *us, struct usb_interface *intf)
+{
+      printk("usb --- associate_dev\n");
+
+       /* Fill in the device-related fields */
+       us->pusb_dev = interface_to_usbdev(intf);
+       us->pusb_intf = intf;
+       us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
+       /* Store our private data in the interface */
+       usb_set_intfdata(intf, us);
+
+       /* Allocate the device-related DMA-mapped buffers */
+       us->cr = usb_alloc_coherent(us->pusb_dev, sizeof(*us->cr), GFP_KERNEL, &us->cr_dma);
+       if (!us->cr)
+       {
+               printk("usb_ctrlrequest allocation failed\n");
+               return -ENOMEM;
+       }
+
+       us->iobuf = usb_alloc_coherent(us->pusb_dev, US_IOBUF_SIZE, GFP_KERNEL, &us->iobuf_dma);
+       if (!us->iobuf)
+       {
+               printk("I/O buffer allocation failed\n");
+               return -ENOMEM;
+       }
+
+       us->sensebuf = kmalloc(US_SENSE_SIZE, GFP_KERNEL);
+       if (!us->sensebuf)
+       {
+               printk("Sense buffer allocation failed\n");
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+//----- get_device_info() ---------------------
+static int get_device_info(struct us_data *us, const struct usb_device_id *id)
+{
+       struct usb_device *dev = us->pusb_dev;
+       struct usb_interface_descriptor *idesc = &us->pusb_intf->cur_altsetting->desc;
+
+      printk("usb --- get_device_info\n");
+
+       us->subclass = idesc->bInterfaceSubClass;
+       us->protocol = idesc->bInterfaceProtocol;
+       us->fflags = USB_US_ORIG_FLAGS(id->driver_info);
+       us->Power_IsResum = false;
+
+       if (us->fflags & US_FL_IGNORE_DEVICE)
+       {
+               printk("device ignored\n");
+               return -ENODEV;
+       }
+
+       if (dev->speed != USB_SPEED_HIGH)
+               us->fflags &= ~US_FL_GO_SLOW;
+
+       return 0;
+}
+
+//----- get_transport() ---------------------
+static int get_transport(struct us_data *us)
+{
+      printk("usb --- get_transport\n");
+       switch (us->protocol) {
+       case US_PR_BULK:
+               us->transport_name = "Bulk";
+               us->transport = usb_stor_Bulk_transport;
+               us->transport_reset = usb_stor_Bulk_reset;
+               break;
+
+       default:
+               return -EIO;
+       }
+       //printk("Transport: %s\n", us->transport_name);
+
+       /* fix for single-lun devices */
+       if (us->fflags & US_FL_SINGLE_LUN)
+               us->max_lun = 0;
+       return 0;
+}
+
+//----- get_protocol() ---------------------
+static int get_protocol(struct us_data *us)
+{
+      printk("usb --- get_protocol\n");
+       printk("us->pusb_dev->descriptor.idVendor = %x\n", us->pusb_dev->descriptor.idVendor);
+       printk("us->pusb_dev->descriptor.idProduct = %x\n", us->pusb_dev->descriptor.idProduct);
+       switch (us->subclass) {
+       case US_SC_SCSI:
+               us->protocol_name = "Transparent SCSI";
+               if( (us->pusb_dev->descriptor.idVendor == 0x0CF2) && (us->pusb_dev->descriptor.idProduct == 0x6250) )
+                       us->proto_handler = ENE_stor_invoke_transport;
+               else
+                       us->proto_handler = usb_stor_invoke_transport;
+               break;
+
+       default:
+               return -EIO;
+       }
+       //printk("Protocol: %s\n", us->protocol_name);
+       return 0;
+}
+
+//----- get_pipes() ---------------------
+static int get_pipes(struct us_data *us)
+{
+       struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting;
+       int i;
+       struct usb_endpoint_descriptor *ep;
+       struct usb_endpoint_descriptor *ep_in = NULL;
+       struct usb_endpoint_descriptor *ep_out = NULL;
+       struct usb_endpoint_descriptor *ep_int = NULL;
+
+      printk("usb --- get_pipes\n");
+
+       for (i = 0; i < altsetting->desc.bNumEndpoints; i++)
+       {
+               ep = &altsetting->endpoint[i].desc;
+
+               if (usb_endpoint_xfer_bulk(ep))
+               {
+                       if (usb_endpoint_dir_in(ep))
+                       {
+                               if (!ep_in)
+                                       ep_in = ep;
+                       }
+                       else
+                       {
+                               if (!ep_out)
+                                       ep_out = ep;
+                       }
+               }
+               else if (usb_endpoint_is_int_in(ep))
+               {
+                       if (!ep_int)
+                               ep_int = ep;
+               }
+       }
+
+       if (!ep_in || !ep_out || (us->protocol == US_PR_CBI && !ep_int))
+       {
+               printk("Endpoint sanity check failed! Rejecting dev.\n");
+               return -EIO;
+       }
+
+       /* Calculate and store the pipe values */
+       us->send_ctrl_pipe = usb_sndctrlpipe(us->pusb_dev, 0);
+       us->recv_ctrl_pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
+       us->send_bulk_pipe = usb_sndbulkpipe(us->pusb_dev, ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+       us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev, ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+       if (ep_int)
+       {
+               us->recv_intr_pipe = usb_rcvintpipe(us->pusb_dev, ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+               us->ep_bInterval = ep_int->bInterval;
+       }
+       return 0;
+}
+
+//----- usb_stor_acquire_resources() ---------------------
+static int usb_stor_acquire_resources(struct us_data *us)
+{
+       struct task_struct *th;
+
+      printk("usb --- usb_stor_acquire_resources\n");
+       us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!us->current_urb)
+       {
+               printk("URB allocation failed\n");
+               return -ENOMEM;
+       }
+
+       /* Start up our control thread */
+       th = kthread_run(usb_stor_control_thread, us, "eucr-storage");
+       if (IS_ERR(th))
+       {
+               printk("Unable to start control thread\n");
+               return PTR_ERR(th);
+       }
+       us->ctl_thread = th;
+
+       return 0;
+}
+
+//----- usb_stor_release_resources() ---------------------
+static void usb_stor_release_resources(struct us_data *us)
+{
+       printk("usb --- usb_stor_release_resources\n");
+
+       SM_FreeMem();
+
+       complete(&us->cmnd_ready);
+       if (us->ctl_thread)
+               kthread_stop(us->ctl_thread);
+
+       /* Call the destructor routine, if it exists */
+       if (us->extra_destructor)
+       {
+               printk("-- calling extra_destructor()\n");
+               us->extra_destructor(us->extra);
+       }
+
+       /* Free the extra data and the URB */
+       kfree(us->extra);
+       usb_free_urb(us->current_urb);
+}
+
+//----- dissociate_dev() ---------------------
+static void dissociate_dev(struct us_data *us)
+{
+      printk("usb --- dissociate_dev\n");
+
+       kfree(us->sensebuf);
+
+       /* Free the device-related DMA-mapped buffers */
+       if (us->cr)
+               usb_free_coherent(us->pusb_dev, sizeof(*us->cr), us->cr, us->cr_dma);
+       if (us->iobuf)
+               usb_free_coherent(us->pusb_dev, US_IOBUF_SIZE, us->iobuf, us->iobuf_dma);
+
+       /* Remove our private data from the interface */
+       usb_set_intfdata(us->pusb_intf, NULL);
+}
+
+//----- quiesce_and_remove_host() ---------------------
+static void quiesce_and_remove_host(struct us_data *us)
+{
+       struct Scsi_Host *host = us_to_host(us);
+
+      printk("usb --- quiesce_and_remove_host\n");
+
+       /* If the device is really gone, cut short reset delays */
+       if (us->pusb_dev->state == USB_STATE_NOTATTACHED)
+               set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+
+       /* Prevent SCSI-scanning (if it hasn't started yet)
+        * and wait for the SCSI-scanning thread to stop.
+        */
+       set_bit(US_FLIDX_DONT_SCAN, &us->dflags);
+       wake_up(&us->delay_wait);
+       wait_for_completion(&us->scanning_done);
+
+       /* Removing the host will perform an orderly shutdown: caches
+        * synchronized, disks spun down, etc.
+        */
+       scsi_remove_host(host);
+
+       /* Prevent any new commands from being accepted and cut short
+        * reset delays.
+        */
+       scsi_lock(host);
+       set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+       scsi_unlock(host);
+       wake_up(&us->delay_wait);
+}
+
+//----- release_everything() ---------------------
+static void release_everything(struct us_data *us)
+{
+      printk("usb --- release_everything\n");
+
+       usb_stor_release_resources(us);
+       dissociate_dev(us);
+       scsi_host_put(us_to_host(us));
+}
+
+//----- usb_stor_scan_thread() ---------------------
+static int usb_stor_scan_thread(void * __us)
+{
+       struct us_data *us = (struct us_data *)__us;
+
+      printk("usb --- usb_stor_scan_thread\n");
+       printk("EUCR : device found at %d\n", us->pusb_dev->devnum);
+
+// Have we to add this code ?
+//     set_freezable();
+//     /* Wait for the timeout to expire or for a disconnect */
+//     if (delay_use > 0)
+//     {
+//             wait_event_freezable_timeout(us->delay_wait,
+//                             test_bit(US_FLIDX_DONT_SCAN, &us->dflags),
+//                             delay_use * HZ);
+//     }
+
+       /* If the device is still connected, perform the scanning */
+       if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags))
+       {
+               /* For bulk-only devices, determine the max LUN value */
+               if (us->protocol == US_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN))
+               {
+                       mutex_lock(&us->dev_mutex);
+                       us->max_lun = usb_stor_Bulk_max_lun(us);
+                       mutex_unlock(&us->dev_mutex);
+               }
+               scsi_scan_host(us_to_host(us));
+               printk("EUCR : device scan complete\n");
+       }
+       complete_and_exit(&us->scanning_done, 0);
+}
+
+//----- eucr_probe() ---------------------
+static int eucr_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       struct Scsi_Host *host;
+       struct us_data *us;
+       int result;
+       struct task_struct *th;
+
+      printk("usb --- eucr_probe\n");
+
+      host = scsi_host_alloc(&usb_stor_host_template, sizeof(*us));
+       if (!host)
+       {
+               printk("Unable to allocate the scsi host\n");
+               return -ENOMEM;
+       }
+
+       /* Allow 16-byte CDBs and thus > 2TB */
+       host->max_cmd_len = 16;
+       us = host_to_us(host);
+       memset(us, 0, sizeof(struct us_data));
+       mutex_init(&(us->dev_mutex));
+       init_completion(&us->cmnd_ready);
+       init_completion(&(us->notify));
+       init_waitqueue_head(&us->delay_wait);
+       init_completion(&us->scanning_done);
+
+       /* Associate the us_data structure with the USB device */
+       result = associate_dev(us, intf);
+       if (result)
+               goto BadDevice;
+
+       /* Get Device info */
+       result = get_device_info(us, id);
+       if (result)
+               goto BadDevice;
+
+       /* Get the transport, protocol, and pipe settings */
+       result = get_transport(us);
+       if (result)
+               goto BadDevice;
+       result = get_protocol(us);
+       if (result)
+               goto BadDevice;
+       result = get_pipes(us);
+       if (result)
+               goto BadDevice;
+
+       /* Acquire all the other resources and add the host */
+       result = usb_stor_acquire_resources(us);
+       if (result)
+               goto BadDevice;
+
+       result = scsi_add_host(host, &intf->dev);
+       if (result)
+       {
+               printk("Unable to add the scsi host\n");
+               goto BadDevice;
+       }
+
+       /* Start up the thread for delayed SCSI-device scanning */
+       th = kthread_create(usb_stor_scan_thread, us, "eucr-stor-scan");
+       if (IS_ERR(th))
+       {
+               printk("Unable to start the device-scanning thread\n");
+               complete(&us->scanning_done);
+               quiesce_and_remove_host(us);
+               result = PTR_ERR(th);
+               goto BadDevice;
+       }
+       wake_up_process(th);
+       return 0;
+
+       /* We come here if there are any problems */
+BadDevice:
+      printk("usb --- eucr_probe failed\n");
+       release_everything(us);
+       return result;
+}
+
+//----- eucr_disconnect() ---------------------
+static void eucr_disconnect(struct usb_interface *intf)
+{
+       struct us_data *us = usb_get_intfdata(intf);
+
+      printk("usb --- eucr_disconnect\n");
+       quiesce_and_remove_host(us);
+       release_everything(us);
+}
+
+/***********************************************************************
+ * Initialization and registration
+ ***********************************************************************/
+
+//----- usb_storage_driver() ---------------------
+static struct usb_driver usb_storage_driver = {
+       .name =         "eucr",
+       .probe =                eucr_probe,
+       .suspend =          eucr_suspend,
+       .resume =           eucr_resume,
+       .reset_resume = eucr_reset_resume,
+       .disconnect =   eucr_disconnect,
+       .pre_reset =    eucr_pre_reset,
+       .post_reset =   eucr_post_reset,
+       .id_table =             eucr_usb_ids,
+       .soft_unbind =  1,
+};
+
+//----- usb_stor_init() ---------------------
+static int __init usb_stor_init(void)
+{
+       int retval;
+      printk("usb --- usb_stor_init start\n");
+
+       retval = usb_register(&usb_storage_driver);
+       if (retval == 0)
+            printk("ENE USB Mass Storage support registered.\n");
+
+       return retval;
+}
+
+//----- usb_stor_exit() ---------------------
+static void __exit usb_stor_exit(void)
+{
+      printk("usb --- usb_stor_exit\n");
+
+       usb_deregister(&usb_storage_driver) ;
+}
+
+module_init(usb_stor_init);
+module_exit(usb_stor_exit);
diff --git a/drivers/staging/keucr/usb.h b/drivers/staging/keucr/usb.h
new file mode 100644 (file)
index 0000000..bbf578a
--- /dev/null
@@ -0,0 +1,238 @@
+// Driver for USB Mass Storage compliant devices
+
+#ifndef _USB_H_
+#define _USB_H_
+
+#include <linux/usb.h>
+#include <linux/usb_usual.h>
+#include <linux/blkdev.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <scsi/scsi_host.h>
+#include "common.h"
+#include "ms.h"
+
+struct us_data;
+struct scsi_cmnd;
+
+/*
+ * Unusual device list definitions
+ */
+
+struct us_unusual_dev {
+       const char* vendorName;
+       const char* productName;
+       __u8  useProtocol;
+       __u8  useTransport;
+       int (*initFunction)(struct us_data *);
+};
+
+//EnE HW Register
+#define REG_CARD_STATUS     0xFF83
+#define REG_HW_TRAP1        0xFF89
+
+// SRB Status. Refers /usr/include/wine/wine/wnaspi32.h & SCSI sense key
+#define SS_SUCCESS                  0x00      // No Sense
+#define SS_NOT_READY                0x02
+#define SS_MEDIUM_ERR               0x03
+#define SS_HW_ERR                   0x04
+#define SS_ILLEGAL_REQUEST          0x05
+#define SS_UNIT_ATTENTION           0x06
+
+//ENE Load FW Pattern
+#define SD_INIT1_PATTERN   1
+#define SD_INIT2_PATTERN   2
+#define SD_RW_PATTERN      3
+#define MS_INIT_PATTERN    4
+#define MSP_RW_PATTERN     5
+#define MS_RW_PATTERN      6
+#define SM_INIT_PATTERN    7
+#define SM_RW_PATTERN      8
+
+#define FDIR_WRITE        0
+#define FDIR_READ         1
+
+typedef struct _SD_STATUS {
+    BYTE    Insert:1;
+    BYTE    Ready:1;
+    BYTE    MediaChange:1;
+    BYTE    IsMMC:1;
+    BYTE    HiCapacity:1;
+    BYTE    HiSpeed:1;
+    BYTE    WtP:1;
+    BYTE    Reserved:1;
+} SD_STATUS, *PSD_STATUS;
+
+typedef struct _MS_STATUS {
+    BYTE    Insert:1;
+    BYTE    Ready:1;
+    BYTE    MediaChange:1;
+    BYTE    IsMSPro:1;
+    BYTE    IsMSPHG:1;
+    BYTE    Reserved1:1;
+    BYTE    WtP:1;
+    BYTE    Reserved2:1;
+} MS_STATUS, *PMS_STATUS;
+
+typedef struct _SM_STATUS {
+    BYTE    Insert:1;
+    BYTE    Ready:1;
+    BYTE    MediaChange:1;
+    BYTE    Reserved:3;
+    BYTE    WtP:1;
+    BYTE    IsMS:1;
+} SM_STATUS, *PSM_STATUS;
+
+// SD Block Length
+#define SD_BLOCK_LEN                            9       // 2^9 = 512 Bytes, The HW maximum read/write data length
+
+/* Dynamic bitflag definitions (us->dflags): used in set_bit() etc. */
+#define US_FLIDX_URB_ACTIVE    0       /* current_urb is in use    */
+#define US_FLIDX_SG_ACTIVE     1       /* current_sg is in use     */
+#define US_FLIDX_ABORTING      2       /* abort is in progress     */
+#define US_FLIDX_DISCONNECTING 3       /* disconnect in progress   */
+#define US_FLIDX_RESETTING     4       /* device reset in progress */
+#define US_FLIDX_TIMED_OUT     5       /* SCSI midlayer timed out  */
+#define US_FLIDX_DONT_SCAN     6       /* don't scan (disconnect)  */
+
+
+#define USB_STOR_STRING_LEN 32
+
+/*
+ * We provide a DMA-mapped I/O buffer for use with small USB transfers.
+ * It turns out that CB[I] needs a 12-byte buffer and Bulk-only needs a
+ * 31-byte buffer.  But Freecom needs a 64-byte buffer, so that's the
+ * size we'll allocate.
+ */
+
+#define US_IOBUF_SIZE          64      /* Size of the DMA-mapped I/O buffer */
+#define US_SENSE_SIZE          18      /* Size of the autosense data buffer */
+
+typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
+typedef int (*trans_reset)(struct us_data*);
+typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*);
+typedef void (*extra_data_destructor)(void *); /* extra data destructor */
+typedef void (*pm_hook)(struct us_data *, int);        /* power management hook */
+
+#define US_SUSPEND     0
+#define US_RESUME      1
+
+/* we allocate one of these for every device that we remember */
+struct us_data {
+       /* The device we're working with
+        * It's important to note:
+        *    (o) you must hold dev_mutex to change pusb_dev
+        */
+       struct mutex            dev_mutex;       /* protect pusb_dev */
+       struct usb_device       *pusb_dev;       /* this usb_device */
+       struct usb_interface    *pusb_intf;      /* this interface */
+       struct us_unusual_dev   *unusual_dev;    /* device-filter entry     */
+       unsigned long           fflags;          /* fixed flags from filter */
+       unsigned long           dflags;          /* dynamic atomic bitflags */
+       unsigned int            send_bulk_pipe;  /* cached pipe values */
+       unsigned int            recv_bulk_pipe;
+       unsigned int            send_ctrl_pipe;
+       unsigned int            recv_ctrl_pipe;
+       unsigned int            recv_intr_pipe;
+
+       /* information about the device */
+       char                    *transport_name;
+       char                    *protocol_name;
+       __le32                  bcs_signature;
+       u8                      subclass;
+       u8                      protocol;
+       u8                      max_lun;
+
+       u8                      ifnum;           /* interface number   */
+       u8                      ep_bInterval;    /* interrupt interval */
+
+       /* function pointers for this device */
+       trans_cmnd              transport;       /* transport function     */
+       trans_reset             transport_reset; /* transport device reset */
+       proto_cmnd              proto_handler;   /* protocol handler       */
+
+       /* SCSI interfaces */
+       struct scsi_cmnd        *srb;            /* current srb         */
+       unsigned int            tag;             /* current dCBWTag     */
+
+       /* control and bulk communications data */
+       struct urb              *current_urb;    /* USB requests         */
+       struct usb_ctrlrequest  *cr;             /* control requests     */
+       struct usb_sg_request   current_sg;      /* scatter-gather req.  */
+       unsigned char           *iobuf;          /* I/O buffer           */
+       unsigned char           *sensebuf;       /* sense data buffer    */
+       dma_addr_t              cr_dma;          /* buffer DMA addresses */
+       dma_addr_t              iobuf_dma;
+       struct task_struct      *ctl_thread;     /* the control thread   */
+
+       /* mutual exclusion and synchronization structures */
+       struct completion       cmnd_ready;      /* to sleep thread on      */
+       struct completion       notify;          /* thread begin/end        */
+       wait_queue_head_t       delay_wait;      /* wait during scan, reset */
+       struct completion       scanning_done;   /* wait for scan thread    */
+
+       /* subdriver information */
+       void                    *extra;          /* Any extra data          */
+       extra_data_destructor   extra_destructor;/* extra data destructor   */
+#ifdef CONFIG_PM
+       pm_hook                 suspend_resume_hook;
+#endif
+       // for 6250 code
+       SD_STATUS   SD_Status;
+       MS_STATUS   MS_Status;
+       SM_STATUS   SM_Status;
+
+       //----- SD Control Data ----------------
+       //SD_REGISTER SD_Regs;
+       WORD        SD_Block_Mult;
+       BYTE        SD_READ_BL_LEN;
+       WORD        SD_C_SIZE;
+       BYTE        SD_C_SIZE_MULT;
+
+       // SD/MMC New spec.
+       BYTE        SD_SPEC_VER;
+       BYTE        SD_CSD_VER;
+       BYTE        SD20_HIGH_CAPACITY;
+       DWORD       HC_C_SIZE;
+       BYTE        MMC_SPEC_VER;
+       BYTE        MMC_BusWidth;
+       BYTE        MMC_HIGH_CAPACITY;
+       
+       //----- MS Control Data ----------------
+       BOOLEAN             MS_SWWP;
+       DWORD               MSP_TotalBlock;
+       MS_LibControl       MS_Lib;
+       BOOLEAN             MS_IsRWPage;
+       WORD                MS_Model;
+
+       //----- SM Control Data ----------------
+       BYTE            SM_DeviceID;
+       BYTE            SM_CardID;
+
+       PBYTE           testbuf;
+       BYTE            BIN_FLAG;
+       DWORD           bl_num;
+       int             SrbStatus;
+       
+       //------Power Managerment ---------------
+       BOOLEAN         Power_IsResum;  
+};
+
+/* Convert between us_data and the corresponding Scsi_Host */
+static inline struct Scsi_Host *us_to_host(struct us_data *us) {
+       return container_of((void *) us, struct Scsi_Host, hostdata);
+}
+static inline struct us_data *host_to_us(struct Scsi_Host *host) {
+       return (struct us_data *) host->hostdata;
+}
+
+/* Function to fill an inquiry response. See usb.c for details */
+extern void fill_inquiry_response(struct us_data *us,
+       unsigned char *data, unsigned int data_len);
+
+/* The scsi_lock() and scsi_unlock() macros protect the sm_state and the
+ * single queue element srb for write access */
+#define scsi_unlock(host)      spin_unlock_irq(host->host_lock)
+#define scsi_lock(host)                spin_lock_irq(host->host_lock)
+
+#endif