Initial commit; kernel source import

This commit is contained in:
Nathan
2025-04-06 23:50:55 -05:00
commit 25c6d769f4
45093 changed files with 18199410 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
config USB_ENESTORAGE
tristate "USB ENE SM card reader support"
depends on USB && SCSI && m
---help---
Say Y here if you wish to control a ENE SM Card reader.
To use SD/MS card, please build driver/usb/storage/ums-eneub6250.ko
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.

View File

@@ -0,0 +1,13 @@
ccflags-y := -Idrivers/scsi
obj-$(CONFIG_USB_ENESTORAGE) += keucr.o
keucr-y := \
usb.o \
scsiglue.o \
transport.o \
init.o \
smscsi.o \
smilmain.o \
smilsub.o \
smilecc.o

View File

@@ -0,0 +1,12 @@
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
- smcommon.h & smilsub.c: use kernel hweight8(), hweight16()
Please send any patches for this driver to Al Cho <acho@novell.com> and
Greg Kroah-Hartman <gregkh@linuxfoundation.org>.

View File

@@ -0,0 +1,15 @@
#ifndef COMMON_INCD
#define COMMON_INCD
typedef u8 BOOLEAN;
typedef u8 BYTE;
typedef u8 *PBYTE;
typedef u16 WORD;
typedef u16 *PWORD;
typedef u32 DWORD;
typedef u32 *PDWORD;
#define BYTE_MASK 0xff
#endif

View File

@@ -0,0 +1,372 @@
#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"
/*
* ENE_InitMedia():
*/
int ENE_InitMedia(struct us_data *us)
{
int result;
BYTE MiscReg03 = 0;
printk(KERN_INFO "--- Init Media ---\n");
result = ENE_Read_BYTE(us, REG_CARD_STATUS, &MiscReg03);
if (result != USB_STOR_XFER_GOOD) {
printk(KERN_ERR "Read register fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
printk(KERN_INFO "MiscReg03 = %x\n", MiscReg03);
if (MiscReg03 & 0x02) {
if (!us->SM_Status.Ready && !us->MS_Status.Ready) {
result = ENE_SMInit(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(struct bulk_cb_wrap));
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_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(KERN_INFO "transport --- ENE_SMInit\n");
result = ENE_LoadBinCode(us, SM_INIT_PATTERN);
if (result != USB_STOR_XFER_GOOD) {
printk(KERN_INFO "Load SM Init Code Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
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(KERN_ERR
"Execution 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(KERN_INFO "Insert = %x\n", us->SM_Status.Insert);
printk(KERN_INFO "Ready = %x\n", us->SM_Status.Ready);
printk(KERN_INFO "WtP = %x\n", us->SM_Status.WtP);
printk(KERN_INFO "DeviceID = %x\n", us->SM_DeviceID);
printk(KERN_INFO "CardID = %x\n", us->SM_CardID);
MediaChange = 1;
Check_D_MediaFmt(us);
} else {
printk(KERN_ERR "SM Card Not Ready --- %x\n", buf[0]);
return USB_STOR_TRANSPORT_ERROR;
}
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(KERN_INFO "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 SS */
case SM_INIT_PATTERN:
printk(KERN_INFO "SM_INIT_PATTERN\n");
memcpy(buf, SM_Init, 0x800);
break;
case SM_RW_PATTERN:
printk(KERN_INFO "SM_RW_PATTERN\n");
memcpy(buf, SM_Rdwr, 0x800);
break;
}
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
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(KERN_INFO "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(KERN_ERR "send cmd to out endpoint fail ---\n");
return USB_STOR_TRANSPORT_ERROR;
}
if (buf) {
unsigned int pipe = fDir;
if (fDir == FDIR_READ)
pipe = us->recv_bulk_pipe;
else
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(KERN_ERR "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(KERN_WARNING "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(KERN_WARNING "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);
if (us->srb)
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(KERN_INFO "transport --- ENE_Read_Data\n"); */
/* set up the command wrapper */
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
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(struct bulk_cb_wrap));
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(KERN_INFO
"scsi cmd %X --- SCSIOP_TEST_UNIT_READY\n", cmd); */
break;
case INQUIRY:
printk(KERN_INFO "scsi cmd %X --- SCSIOP_INQUIRY\n", cmd);
break;
case MODE_SENSE:
printk(KERN_INFO "scsi cmd %X --- SCSIOP_MODE_SENSE\n", cmd);
break;
case START_STOP:
printk(KERN_INFO "scsi cmd %X --- SCSIOP_START_STOP\n", cmd);
break;
case READ_CAPACITY:
printk(KERN_INFO "scsi cmd %X --- SCSIOP_READ_CAPACITY\n", cmd);
break;
case READ_10:
/* printk(KERN_INFO
"scsi cmd %X --- SCSIOP_READ,bn = %X, blen = %X\n"
,cmd, bn, blen); */
break;
case WRITE_10:
/* printk(KERN_INFO
"scsi cmd %X --- SCSIOP_WRITE,
bn = %X, blen = %X\n" , cmd, bn, blen); */
break;
case ALLOW_MEDIUM_REMOVAL:
printk(KERN_INFO
"scsi cmd %X --- SCSIOP_ALLOW_MEDIUM_REMOVAL\n", cmd);
break;
default:
printk(KERN_INFO "scsi cmd %X --- Other cmd\n", cmd);
break;
}
bn = 0;
blen = 0;
}

View File

@@ -0,0 +1,523 @@
#include "common.h"
extern DWORD MediaChange;
extern int Check_D_MediaFmt(struct us_data *);
static 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 };
static 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 };

View File

@@ -0,0 +1,469 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#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)
{
/* pr_info("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);
/* pr_info("scsiglue --- slave_alloc\n"); */
sdev->inquiry_len = 36;
blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
if (us->subclass == USB_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);
/* pr_info("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 != USB_SC_SCSI &&
us->subclass != USB_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 == USB_PR_CB || us->protocol == USB_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_lck(struct scsi_cmnd *srb,
void (*done)(struct scsi_cmnd *))
{
struct us_data *us = host_to_us(srb->device->host);
/* pr_info("scsiglue --- queuecommand\n"); */
/* check for state-transition errors */
if (us->srb != NULL) {
/* pr_info("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)) {
pr_info("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;
}
static DEF_SCSI_QCMD(queuecommand)
/***********************************************************************
* 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);
/* pr_info("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;
/* pr_info("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;
/* pr_info("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);
/* pr_info("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);
/* pr_info("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...) seq_printf(m, ##args)
static int write_info(struct Scsi_Host *host, char *buffer, int length)
{
return length;
}
static int show_info(struct seq_file *m, struct Scsi_Host *host)
{
struct us_data *us = host_to_us(host);
const char *string;
/* 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 */
SPRINTF(" Quirks:");
#define US_FLAG(name, value) \
do { \
if (us->fflags & value) \
SPRINTF(" " #name); \
} while (0);
US_DO_ALL_FLAGS
#undef US_FLAG
seq_putc(m, '\n');
return 0;
}
/***********************************************************************
* 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);
/* pr_info("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;
/* pr_info("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",
.write_info = write_info,
.show_info = show_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;
/* pr_info("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;
/* pr_info("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);
}

View File

@@ -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

View File

@@ -0,0 +1,29 @@
/*----- < SMCommon.h> --------------------------------------------------*/
#ifndef SMCOMMON_INCD
#define SMCOMMON_INCD
/***************************************************************************
Define Difinetion
***************************************************************************/
#define SMSUCCESS 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 */
/***************************************************************************/
#endif

View File

@@ -0,0 +1,311 @@
/*----- < 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 */
};
extern BYTE IsSSFDCCompliance;
extern BYTE IsXDCompliance;
extern DWORD ErrXDCode;
extern DWORD ErrCode;
extern WORD ReadBlock;
extern WORD WriteBlock;
extern DWORD MediaChange;
extern struct SSFDCTYPE Ssfdc;
extern struct ADDRESS Media;
extern struct CIS_AREA CisArea;
/*
* 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 *);
/******************************************/
extern int SM_FreeMem(void); /* ENE SM function */
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 */

View File

@@ -0,0 +1,211 @@
#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
/*
* reg2; * LP14,LP12,LP10,...
* reg3; * LP15,LP13,LP11,...
* *ecc1; * LP15,LP14,LP13,...
* *ecc2; * LP07,LP06,LP05,...
*/
static void trans_result(BYTE reg2, BYTE reg3, BYTE *ecc1, BYTE *ecc2)
{
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) */
/*
* *table; * CP0-CP5 code table
* *data; * DATA
* *ecc1; * LP15,LP14,LP13,...
* *ecc2; * LP07,LP06,LP05,...
* *ecc3; * CP5,CP4,CP3,...,"1","1"
*/
void calculate_ecc(BYTE *table, BYTE *data, BYTE *ecc1, BYTE *ecc2, BYTE *ecc3)
{
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 */
}
/*
* *data; * DATA
* *eccdata; * ECC DATA
* ecc1; * LP15,LP14,LP13,...
* ecc2; * LP07,LP06,LP05,...
* ecc3; * CP5,CP4,CP3,...,"1","1"
*/
BYTE correct_data(BYTE *data, BYTE *eccdata, BYTE ecc1, BYTE ecc2, BYTE ecc3)
{
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(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)
memcpy(calculate_ecc, redundant_ecc, 3);
if (err == 0 || err == 1 || err == 2)
return 0;
return -1;
}
void _Calculate_D_SwECC(BYTE *buf, BYTE *ecc)
{
calculate_ecc(ecctable, buf, ecc+1, ecc+0, ecc+2);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,693 @@
#include <linux/slab.h>
#include "usb.h"
#include "scsiglue.h"
#include "transport.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 *);
struct SSFDCTYPE Ssfdc;
struct ADDRESS Media;
struct CIS_AREA CisArea;
static BYTE EccBuf[6];
extern PBYTE SMHostAddr;
extern DWORD ErrXDCode;
extern WORD ReadBlock;
extern WORD WriteBlock;
#define EVEN 0 /* Even Page for 256byte/page */
#define ODD 1 /* Odd Page for 256byte/page */
/* SmartMedia Redundant buffer data Control Subroutine
*----- Check_D_DataBlank() --------------------------------------------
*/
int Check_D_DataBlank(BYTE *redundant)
{
char i;
for (i = 0; i < REDTSIZE; i++)
if (*redundant++ != 0xFF)
return ERROR;
return SMSUCCESS;
}
/* ----- Check_D_FailBlock() -------------------------------------------- */
int Check_D_FailBlock(BYTE *redundant)
{
redundant += REDT_BLOCK;
if (*redundant == 0xFF)
return SMSUCCESS;
if (!*redundant)
return ERROR;
if (hweight8(*redundant) < 7)
return ERROR;
return SMSUCCESS;
}
/* ----- Check_D_DataStatus() ------------------------------------------- */
int Check_D_DataStatus(BYTE *redundant)
{
redundant += REDT_DATA;
if (*redundant == 0xFF)
return SMSUCCESS;
if (!*redundant) {
ErrXDCode = ERR_DataStatus;
return ERROR;
} else
ErrXDCode = NO_ERROR;
if (hweight8(*redundant) < 5)
return ERROR;
return SMSUCCESS;
}
/* ----- Load_D_LogBlockAddr() ------------------------------------------ */
int Load_D_LogBlockAddr(BYTE *redundant)
{
WORD addr1, addr2;
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 SMSUCCESS;
}
if (hweight16((WORD)(addr1^addr2)) != 0x01)
return ERROR;
if ((addr1 & 0xF000) == 0x1000)
if (!(hweight16(addr1) & 0x01)) {
Media.LogBlock = (addr1 & 0x0FFF) / 2;
return SMSUCCESS;
}
if ((addr2 & 0xF000) == 0x1000)
if (!(hweight16(addr2) & 0x01)) {
Media.LogBlock = (addr2 & 0x0FFF) / 2;
return SMSUCCESS;
}
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 ((hweight16(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)
{
return;
}
/* ----- Ssfdc_D_ReadCisSect() ------------------------------------------ */
int Ssfdc_D_ReadCisSect(struct us_data *us, BYTE *buf, BYTE *redundant)
{
BYTE zone, sector;
WORD block;
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 SMSUCCESS;
}
/* 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(struct bulk_cb_wrap));
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(struct bulk_cb_wrap));
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;
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(struct bulk_cb_wrap));
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(struct bulk_cb_wrap));
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_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;
WORD ReadAddr, WriteAddr;
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(struct bulk_cb_wrap));
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_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;
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;
/* Write sect data */
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
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(struct bulk_cb_wrap));
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(struct bulk_cb_wrap));
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, 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;
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(struct bulk_cb_wrap));
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)
{
return SMSUCCESS;
}
/* 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 SMSUCCESS;
}
/* ----- _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 ECC Control Subroutine
* ----- Check_D_ReadError() ----------------------------------------------
*/
int Check_D_ReadError(BYTE *redundant)
{
return SMSUCCESS;
}
/* ----- Check_D_Correct() ---------------------------------------------- */
int Check_D_Correct(BYTE *buf, BYTE *redundant)
{
return SMSUCCESS;
}
/* ----- Check_D_CISdata() ---------------------------------------------- */
int Check_D_CISdata(BYTE *buf, BYTE *redundant)
{
BYTE cis[] = {0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02,
0xDF, 0x01, 0x20};
int cis_len = sizeof(cis);
if (!IsSSFDCCompliance && !IsXDCompliance)
return SMSUCCESS;
if (!memcmp(redundant + 0x0D, EccBuf, 3))
return memcmp(buf, cis, cis_len);
if (!_Correct_D_SwECC(buf, redundant + 0x0D, EccBuf))
return memcmp(buf, cis, cis_len);
buf += 0x100;
if (!memcmp(redundant + 0x08, EccBuf + 0x03, 3))
return memcmp(buf, cis, cis_len);
if (!_Correct_D_SwECC(buf, redundant + 0x08, EccBuf + 0x03))
return memcmp(buf, cis, cis_len);
return ERROR;
}
/* ----- Set_D_RightECC() ---------------------------------------------- */
void Set_D_RightECC(BYTE *redundant)
{
/* Driver ECC Check */
return;
}

View File

@@ -0,0 +1,188 @@
#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 "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 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)
{
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)
{
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;
us->bl_num = bl_num;
printk("bl_len = %x\n", bl_len);
printk("bl_num = %x\n", bl_num);
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);
return USB_STOR_TRANSPORT_GOOD;
}
/* ----- SM_SCSI_Read() -------------------------------------------------- */
int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb)
{
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;
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)
{
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;
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;
}

View File

@@ -0,0 +1,823 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#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;
/* pr_info("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;
/* pr_info("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 = 0;
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)) {
/* pr_info("-- 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) {
/* pr_info("%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;
/* pr_info("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);
/* pr_info("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)
{
/* pr_info("transport --- interpret_urb_result\n"); */
switch (result) {
/* no error code; did we send all the data? */
case 0:
if (partial != length) {
/* pr_info("-- short transfer\n"); */
return USB_STOR_XFER_SHORT;
}
/* pr_info("-- transfer complete\n"); */
return USB_STOR_XFER_GOOD;
case -EPIPE:
if (usb_pipecontrol(pipe)) {
/* pr_info("-- stall on control pipe\n"); */
return USB_STOR_XFER_STALLED;
}
/* pr_info("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:
/* pr_info("-- babble\n"); */
return USB_STOR_XFER_LONG;
case -ECONNRESET:
/* pr_info("-- transfer cancelled\n"); */
return USB_STOR_XFER_ERROR;
case -EREMOTEIO:
/* pr_info("-- short read transfer\n"); */
return USB_STOR_XFER_SHORT;
case -EIO:
/* pr_info("-- abort or disconnect in progress\n"); */
return USB_STOR_XFER_ERROR;
default:
/* pr_info("-- 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;
/* pr_info("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;
/* pr_info("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) {
/* pr_info("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)) {
/* pr_info("-- 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;
/* pr_info("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;
/* pr_info("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)) {
/* pr_info("-- 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) {
/* pr_info("-- 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 == USB_PR_CB || us->protocol == USB_PR_DPCM_USB) &&
srb->sc_data_direction != DMA_FROM_DEVICE) {
/* pr_info("-- CB transport device requiring auto-sense\n"); */
need_auto_sense = 1;
}
if (result == USB_STOR_TRANSPORT_FAILED) {
/* pr_info("-- 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;
pr_info("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 == USB_SC_RBC ||
us->subclass == USB_SC_SCSI ||
us->subclass == USB_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)) {
/* pr_info("-- auto-sense aborted\n"); */
srb->result = DID_ABORT << 16;
goto Handle_Errors;
}
if (temp_result != USB_STOR_TRANSPORT_GOOD) {
/* pr_info("-- 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;
/* pr_info("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->SM_Status.Ready))
result = ENE_InitMedia(us);
if (us->Power_IsResum == true) {
result = ENE_InitMedia(us);
us->Power_IsResum = false;
}
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)) {
/* pr_info("-- 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) {
/* pr_info("-- 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) {
/* pr_info("-- 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;
pr_info("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)
{
/* pr_info("transport --- usb_stor_stop_transport\n"); */
if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
/* pr_info("-- cancelling URB\n"); */
usb_unlink_urb(us->current_urb);
}
if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
/* pr_info("-- 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;
/* pr_info("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);
/* pr_info("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;
/* pr_info("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 */
/* pr_info("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);
/* pr_info("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;
if (srb->sc_data_direction == DMA_FROM_DEVICE)
pipe = us->recv_bulk_pipe;
else
pipe = us->send_bulk_pipe;
result = usb_stor_bulk_srb(us, pipe, srb);
/* pr_info("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 */
/* pr_info("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) {
/* pr_info("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 */
/* pr_info("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 */
/* pr_info("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);
/* pr_info("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) {
/* pr_info("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)) */
/* pr_info("Learnt BCS signature 0x%08X\n",
le32_to_cpu(us->bcs_signature)); */
} else if (bcs->Signature != us->bcs_signature) {
/* pr_info("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;
/* pr_info("transport --- usb_stor_reset_common\n"); */
if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
/* pr_info("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) {
/* pr_info("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)) {
/* pr_info("Reset interrupted by disconnect\n"); */
return -EIO;
}
/* pr_info("Soft reset: clearing bulk-in endpoint halt\n"); */
result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
/* pr_info("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) */
/* pr_info("Soft reset failed\n"); */
/* else */
/* pr_info("Soft reset done\n"); */
return result;
}
/*
* usb_stor_Bulk_reset()
*/
int usb_stor_Bulk_reset(struct us_data *us)
{
/* pr_info("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;
/* pr_info("transport --- usb_stor_port_reset\n"); */
result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
if (result < 0)
pr_info("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;
/* pr_info("No reset during disconnect\n"); */
} else {
result = usb_reset_device(us->pusb_dev);
/* pr_info("usb_reset_composite_device returns %d\n",
result); */
}
usb_unlock_device(us->pusb_dev);
}
return result;
}

View File

@@ -0,0 +1,74 @@
#ifndef _TRANSPORT_H_
#define _TRANSPORT_H_
#include <linux/blkdev.h>
/* 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_SMInit(struct us_data *);
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 SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
#endif

636
drivers/staging/keucr/usb.c Normal file
View File

@@ -0,0 +1,636 @@
#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 "smil.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
static int eucr_suspend(struct usb_interface *iface, pm_message_t message)
{
struct us_data *us = usb_get_intfdata(iface);
pr_info("--- eucr_suspend ---\n");
/* Wait until no command is running */
mutex_lock(&us->dev_mutex);
if (us->suspend_resume_hook)
(us->suspend_resume_hook)(us, US_SUSPEND);
mutex_unlock(&us->dev_mutex);
return 0;
}
static int eucr_resume(struct usb_interface *iface)
{
BYTE tmp = 0;
struct us_data *us = usb_get_intfdata(iface);
pr_info("--- eucr_resume---\n");
mutex_lock(&us->dev_mutex);
if (us->suspend_resume_hook)
(us->suspend_resume_hook)(us, US_RESUME);
mutex_unlock(&us->dev_mutex);
us->Power_IsResum = true;
us->SM_Status = *(PSM_STATUS)&tmp;
return 0;
}
static int eucr_reset_resume(struct usb_interface *iface)
{
BYTE tmp = 0;
struct us_data *us = usb_get_intfdata(iface);
pr_info("--- eucr_reset_resume---\n");
/* Report the reset to the SCSI core */
usb_stor_report_bus_reset(us);
/*
* FIXME: Notify the subdrivers that they need to reinitialize
* the device
*/
us->Power_IsResum = true;
us->SM_Status = *(PSM_STATUS)&tmp;
return 0;
}
#else
#define eucr_suspend NULL
#define eucr_resume NULL
#define eucr_reset_resume NULL
#endif
static int eucr_pre_reset(struct usb_interface *iface)
{
struct us_data *us = usb_get_intfdata(iface);
pr_info("usb --- eucr_pre_reset\n");
/* Make sure no command runs during the reset */
mutex_lock(&us->dev_mutex);
return 0;
}
static int eucr_post_reset(struct usb_interface *iface)
{
struct us_data *us = usb_get_intfdata(iface);
pr_info("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;
}
void fill_inquiry_response(struct us_data *us, unsigned char *data, unsigned int data_len)
{
pr_info("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);
}
static int usb_stor_control_thread(void * __us)
{
struct us_data *us = (struct us_data *)__us;
struct Scsi_Host *host = us_to_host(us);
pr_info("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);
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:
pr_info("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;
}
static int associate_dev(struct us_data *us, struct usb_interface *intf)
{
pr_info("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) {
pr_info("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) {
pr_info("I/O buffer allocation failed\n");
return -ENOMEM;
}
us->sensebuf = kmalloc(US_SENSE_SIZE, GFP_KERNEL);
if (!us->sensebuf)
return -ENOMEM;
return 0;
}
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;
pr_info("usb --- get_device_info\n");
us->subclass = idesc->bInterfaceSubClass;
us->protocol = idesc->bInterfaceProtocol;
us->fflags = id->driver_info;
us->Power_IsResum = false;
if (us->fflags & US_FL_IGNORE_DEVICE) {
pr_info("device ignored\n");
return -ENODEV;
}
if (dev->speed != USB_SPEED_HIGH)
us->fflags &= ~US_FL_GO_SLOW;
return 0;
}
static int get_transport(struct us_data *us)
{
pr_info("usb --- get_transport\n");
switch (us->protocol) {
case USB_PR_BULK:
us->transport_name = "Bulk";
us->transport = usb_stor_Bulk_transport;
us->transport_reset = usb_stor_Bulk_reset;
break;
default:
return -EIO;
}
/* fix for single-lun devices */
if (us->fflags & US_FL_SINGLE_LUN)
us->max_lun = 0;
return 0;
}
static int get_protocol(struct us_data *us)
{
pr_info("usb --- get_protocol\n");
pr_info("us->pusb_dev->descriptor.idVendor = %x\n",
us->pusb_dev->descriptor.idVendor);
pr_info("us->pusb_dev->descriptor.idProduct = %x\n",
us->pusb_dev->descriptor.idProduct);
switch (us->subclass) {
case USB_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;
}
return 0;
}
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;
pr_info("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 == USB_PR_CBI && !ep_int)) {
pr_info("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;
}
static int usb_stor_acquire_resources(struct us_data *us)
{
struct task_struct *th;
pr_info("usb --- usb_stor_acquire_resources\n");
us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!us->current_urb) {
pr_info("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)) {
pr_info("Unable to start control thread\n");
return PTR_ERR(th);
}
us->ctl_thread = th;
return 0;
}
static void usb_stor_release_resources(struct us_data *us)
{
pr_info("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) {
pr_info("-- 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);
}
static void dissociate_dev(struct us_data *us)
{
pr_info("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);
}
static void quiesce_and_remove_host(struct us_data *us)
{
struct Scsi_Host *host = us_to_host(us);
pr_info("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);
}
static void release_everything(struct us_data *us)
{
pr_info("usb --- release_everything\n");
usb_stor_release_resources(us);
dissociate_dev(us);
scsi_host_put(us_to_host(us));
}
static int usb_stor_scan_thread(void * __us)
{
struct us_data *us = (struct us_data *)__us;
pr_info("usb --- usb_stor_scan_thread\n");
pr_info("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 == USB_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));
pr_info("EUCR : device scan complete\n");
}
complete_and_exit(&us->scanning_done, 0);
}
static int eucr_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct Scsi_Host *host;
struct us_data *us;
int result;
BYTE MiscReg03 = 0;
struct task_struct *th;
pr_info("usb --- eucr_probe\n");
host = scsi_host_alloc(&usb_stor_host_template, sizeof(*us));
if (!host) {
pr_info("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) {
pr_info("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)) {
pr_info("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);
/* probe card type */
result = ENE_Read_BYTE(us, REG_CARD_STATUS, &MiscReg03);
if (result != USB_STOR_XFER_GOOD) {
result = USB_STOR_TRANSPORT_ERROR;
quiesce_and_remove_host(us);
goto BadDevice;
}
if (!(MiscReg03 & 0x02)) {
result = -ENODEV;
quiesce_and_remove_host(us);
pr_info("keucr: The driver only supports SM/MS card.\
To use SD card, \
please build driver/usb/storage/ums-eneub6250.ko\n");
goto BadDevice;
}
return 0;
/* We come here if there are any problems */
BadDevice:
pr_info("usb --- eucr_probe failed\n");
release_everything(us);
return result;
}
static void eucr_disconnect(struct usb_interface *intf)
{
struct us_data *us = usb_get_intfdata(intf);
pr_info("usb --- eucr_disconnect\n");
quiesce_and_remove_host(us);
release_everything(us);
}
/* Initialization and registration */
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,
};
module_usb_driver(usb_storage_driver);

237
drivers/staging/keucr/usb.h Normal file
View File

@@ -0,0 +1,237 @@
// 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"
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