diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-28 09:44:56 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-28 09:44:56 -0700 |
commit | e4c5bf8e3dca827a1b3a6fac494eae8c74b7e1e7 (patch) | |
tree | ea51b391f7d74ca695dcb9f5e46eb02688a92ed9 /drivers/staging/keucr | |
parent | 81280572ca6f54009edfa4deee563e8678784218 (diff) | |
parent | a4ac0d847af9dd34d5953a5e264400326144b6b2 (diff) |
Merge 'staging-next' to Linus's tree
This merges the staging-next tree to Linus's tree and resolves
some conflicts that were present due to changes in other trees that were
affected by files here.
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/keucr')
-rw-r--r-- | drivers/staging/keucr/Kconfig | 13 | ||||
-rw-r--r-- | drivers/staging/keucr/Makefile | 16 | ||||
-rw-r--r-- | drivers/staging/keucr/TODO | 14 | ||||
-rw-r--r-- | drivers/staging/keucr/common.h | 26 | ||||
-rw-r--r-- | drivers/staging/keucr/init.c | 543 | ||||
-rw-r--r-- | drivers/staging/keucr/init.h | 2066 | ||||
-rw-r--r-- | drivers/staging/keucr/ms.c | 956 | ||||
-rw-r--r-- | drivers/staging/keucr/ms.h | 381 | ||||
-rw-r--r-- | drivers/staging/keucr/msscsi.c | 324 | ||||
-rw-r--r-- | drivers/staging/keucr/scsiglue.c | 448 | ||||
-rw-r--r-- | drivers/staging/keucr/scsiglue.h | 10 | ||||
-rw-r--r-- | drivers/staging/keucr/sdscsi.c | 210 | ||||
-rw-r--r-- | drivers/staging/keucr/smcommon.h | 33 | ||||
-rw-r--r-- | drivers/staging/keucr/smil.h | 290 | ||||
-rw-r--r-- | drivers/staging/keucr/smilecc.c | 201 | ||||
-rw-r--r-- | drivers/staging/keucr/smilmain.c | 1852 | ||||
-rw-r--r-- | drivers/staging/keucr/smilsub.c | 1661 | ||||
-rw-r--r-- | drivers/staging/keucr/smscsi.c | 193 | ||||
-rw-r--r-- | drivers/staging/keucr/transport.c | 783 | ||||
-rw-r--r-- | drivers/staging/keucr/transport.h | 144 | ||||
-rw-r--r-- | drivers/staging/keucr/usb.c | 709 | ||||
-rw-r--r-- | drivers/staging/keucr/usb.h | 238 |
22 files changed, 11111 insertions, 0 deletions
diff --git a/drivers/staging/keucr/Kconfig b/drivers/staging/keucr/Kconfig new file mode 100644 index 000000000000..b595bdbd4740 --- /dev/null +++ b/drivers/staging/keucr/Kconfig @@ -0,0 +1,13 @@ +config USB_ENESTORAGE + tristate "USB ENE card reader support" + depends on USB && SCSI && m + ---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 000000000000..5c19b7b0d3b7 --- /dev/null +++ b/drivers/staging/keucr/Makefile @@ -0,0 +1,16 @@ +ccflags-y := -Idrivers/scsi + +obj-$(CONFIG_USB_ENESTORAGE) += keucr.o + +keucr-y := \ + 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/TODO b/drivers/staging/keucr/TODO new file mode 100644 index 000000000000..29f1b10bd2f6 --- /dev/null +++ b/drivers/staging/keucr/TODO @@ -0,0 +1,14 @@ +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 + - common.h: use kernel swap, le, & be functions + - smcommon.h & smilsub.c: use kernel hweight8(), hweight16(), + strcmp(), & strcpy() + +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 000000000000..8693c54f76d0 --- /dev/null +++ b/drivers/staging/keucr/common.h @@ -0,0 +1,26 @@ +#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 000000000000..1934805844f2 --- /dev/null +++ b/drivers/staging/keucr/init.c @@ -0,0 +1,543 @@ +#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); + if (buf == NULL) + return USB_STOR_TRANSPORT_ERROR; + 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 000000000000..cd199fc1e6d5 --- /dev/null +++ b/drivers/staging/keucr/init.h @@ -0,0 +1,2066 @@ +#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 000000000000..d4340a9da87d --- /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 000000000000..4509db79298a --- /dev/null +++ b/drivers/staging/keucr/ms.h @@ -0,0 +1,381 @@ +#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 000000000000..ad0c5c629935 --- /dev/null +++ b/drivers/staging/keucr/msscsi.c @@ -0,0 +1,324 @@ +#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); + if (buf == NULL) + return USB_STOR_TRANSPORT_ERROR; + + 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); + if (buf == NULL) + return USB_STOR_TRANSPORT_ERROR; + 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 000000000000..d830348ed011 --- /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 000000000000..c7e59f0f9cd6 --- /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 000000000000..6c332f850ebe --- /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 000000000000..169460547662 --- /dev/null +++ b/drivers/staging/keucr/smcommon.h @@ -0,0 +1,33 @@ +/*----- < 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 */ + +/***************************************************************************/ +char Bit_D_Count(BYTE); +char Bit_D_CountWord(WORD); +void StringCopy(char *, char *, int); +int StringCmp(char *, char *, int); + +#endif diff --git a/drivers/staging/keucr/smil.h b/drivers/staging/keucr/smil.h new file mode 100644 index 000000000000..4226813ba588 --- /dev/null +++ b/drivers/staging/keucr/smil.h @@ -0,0 +1,290 @@ +/*----- < 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 000000000000..daf322ac9bf9 --- /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 000000000000..bdfbf76f8df9 --- /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 000000000000..844b65988636 --- /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 000000000000..62116869b38a --- /dev/null +++ b/drivers/staging/keucr/smscsi.c @@ -0,0 +1,193 @@ +#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); + if (buf == NULL) + return USB_STOR_TRANSPORT_ERROR; + 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); + if (buf == NULL) + return USB_STOR_TRANSPORT_ERROR; + 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 000000000000..469702176ccc --- /dev/null +++ b/drivers/staging/keucr/transport.c @@ -0,0 +1,783 @@ +#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; + + //printk("transport --- usb_stor_port_reset\n"); + result = 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); + } + 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 000000000000..ae9b5ee8a0cc --- /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 000000000000..606053db069e --- /dev/null +++ b/drivers/staging/keucr/usb.c @@ -0,0 +1,709 @@ +#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 unsigned int delay_use = 1; + +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); + + +#ifdef CONFIG_PM + +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); + +#else + +#define eucr_suspend NULL +#define eucr_resume NULL +#define eucr_reset_resume NULL + +#endif + +//----- 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->dflags)) { + 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); + + 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 000000000000..bbf578ad6316 --- /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 |