aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/keucr/Kconfig13
-rw-r--r--drivers/staging/keucr/Makefile16
-rw-r--r--drivers/staging/keucr/Module.symvers0
-rw-r--r--drivers/staging/keucr/TODO11
-rw-r--r--drivers/staging/keucr/common.h25
-rw-r--r--drivers/staging/keucr/init.c541
-rw-r--r--drivers/staging/keucr/init.h1042
-rw-r--r--drivers/staging/keucr/ms.c956
-rw-r--r--drivers/staging/keucr/ms.h383
-rw-r--r--drivers/staging/keucr/msscsi.c320
-rw-r--r--drivers/staging/keucr/scsiglue.c448
-rw-r--r--drivers/staging/keucr/scsiglue.h10
-rw-r--r--drivers/staging/keucr/sdscsi.c210
-rw-r--r--drivers/staging/keucr/smcommon.h40
-rw-r--r--drivers/staging/keucr/smil.h289
-rw-r--r--drivers/staging/keucr/smilecc.c201
-rw-r--r--drivers/staging/keucr/smilmain.c1852
-rw-r--r--drivers/staging/keucr/smilsub.c1661
-rw-r--r--drivers/staging/keucr/smscsi.c189
-rw-r--r--drivers/staging/keucr/transport.c788
-rw-r--r--drivers/staging/keucr/transport.h144
-rw-r--r--drivers/staging/keucr/usb.c701
-rw-r--r--drivers/staging/keucr/usb.h238
25 files changed, 10081 insertions, 0 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index b9d81eaf1b2..35ad9397a6b 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -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
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 64ec1e9a40b..a33209be3ba 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -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
index 00000000000..ff42d7ed853
--- /dev/null
+++ b/drivers/staging/keucr/Kconfig
@@ -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
index 00000000000..2a4200f019d
--- /dev/null
+++ b/drivers/staging/keucr/Makefile
@@ -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
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/drivers/staging/keucr/Module.symvers
diff --git a/drivers/staging/keucr/TODO b/drivers/staging/keucr/TODO
new file mode 100644
index 00000000000..4e39e03f579
--- /dev/null
+++ b/drivers/staging/keucr/TODO
@@ -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
index 00000000000..f40c64f4e0c
--- /dev/null
+++ b/drivers/staging/keucr/common.h
@@ -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
index 00000000000..2ae129bfb60
--- /dev/null
+++ b/drivers/staging/keucr/init.c
@@ -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
index 00000000000..17af95b6229
--- /dev/null
+++ b/drivers/staging/keucr/init.h
@@ -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
index 00000000000..d4340a9da87
--- /dev/null
+++ b/drivers/staging/keucr/ms.c
@@ -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
index 00000000000..80b168e9f23
--- /dev/null
+++ b/drivers/staging/keucr/ms.h
@@ -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
index 00000000000..b908a238396
--- /dev/null
+++ b/drivers/staging/keucr/msscsi.c
@@ -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
index 00000000000..d830348ed01
--- /dev/null
+++ b/drivers/staging/keucr/scsiglue.c
@@ -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
index 00000000000..c7e59f0f9cd
--- /dev/null
+++ b/drivers/staging/keucr/scsiglue.h
@@ -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
index 00000000000..6c332f850eb
--- /dev/null
+++ b/drivers/staging/keucr/sdscsi.c
@@ -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
index 00000000000..c20dbcfab0d
--- /dev/null
+++ b/drivers/staging/keucr/smcommon.h
@@ -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
index 00000000000..b138888fd58
--- /dev/null
+++ b/drivers/staging/keucr/smil.h
@@ -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
index 00000000000..daf322ac9bf
--- /dev/null
+++ b/drivers/staging/keucr/smilecc.c
@@ -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
index 00000000000..bdfbf76f8df
--- /dev/null
+++ b/drivers/staging/keucr/smilmain.c
@@ -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
index 00000000000..844b6598863
--- /dev/null
+++ b/drivers/staging/keucr/smilsub.c
@@ -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
index 00000000000..43e32c6ded9
--- /dev/null
+++ b/drivers/staging/keucr/smscsi.c
@@ -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
index 00000000000..7215429759b
--- /dev/null
+++ b/drivers/staging/keucr/transport.c
@@ -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
index 00000000000..ae9b5ee8a0c
--- /dev/null
+++ b/drivers/staging/keucr/transport.h
@@ -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
index 00000000000..d7dab727cd6
--- /dev/null
+++ b/drivers/staging/keucr/usb.c
@@ -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
index 00000000000..bbf578ad631
--- /dev/null
+++ b/drivers/staging/keucr/usb.h
@@ -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