提交 126bb03b 编写于 作者: A Al Cho 提交者: Greg Kroah-Hartman

Staging: add USB ENE card reader driver

This driver is for the ENE card reader that can be found in many
different laptops.  It was written by ENE, but cleaned up to
work properly in the kernel tree by Novell.
Signed-off-by: NAl Cho <acho@novell.com>
Cc: <yiyingc@ene.com.tw>
Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
上级 15b9e327
......@@ -159,5 +159,7 @@ source "drivers/staging/sbe-2t3e3/Kconfig"
source "drivers/staging/ath6kl/Kconfig"
source "drivers/staging/keucr/Kconfig"
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING
......@@ -60,3 +60,4 @@ obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/
obj-$(CONFIG_WESTBRIDGE_ASTORIA) += westbridge/astoria/
obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3/
obj-$(CONFIG_ATH6K_LEGACY) += ath6kl/
obj-$(CONFIG_USB_ENESTORAGE) += keucr/
config USB_ENESTORAGE
tristate "USB ENE card reader support"
depends on USB && SCSI
---help---
Say Y here if you wish to control a ENE Card reader.
This option depends on 'SCSI' support being enabled, but you
probably also need 'SCSI device support: SCSI disk support'
(BLK_DEV_SD) for most USB storage devices.
To compile this driver as a module, choose M here: the
module will be called keucr.
EXTRA_CFLAGS += -Idrivers/scsi
obj-$(CONFIG_USB_ENESTORAGE) += keucr.o
keucr-objs := \
usb.o \
scsiglue.o \
transport.o \
init.o \
sdscsi.o \
msscsi.o \
ms.o \
smscsi.o \
smilmain.o \
smilsub.o \
smilecc.o
TODO:
- checkpatch.pl clean
- sparse clean
- determine if the driver should not be using a duplicate
version of the usb-storage scsi interface code, but should
be merged into the drivers/usb/storage/ directory and
infrastructure instead.
- review by the USB developer community
Please send any patches for this driver to Al Cho <acho@novell.com> and
Greg Kroah-Hartman <gregkh@suse.de>.
#ifndef COMMON_INCD
#define COMMON_INCD
typedef void VOID;
typedef u8 BOOLEAN;
typedef u8 BYTE;
typedef u8 *PBYTE;
typedef u16 WORD;
typedef u16 *PWORD;
typedef u32 DWORD;
typedef u32 *PDWORD;
#define swapWORD(w) ((((unsigned short)(w) << 8) & 0xff00) | (((unsigned short)(w) >> 8) & 0x00ff))
#define swapDWORD(dw) ((((unsigned long)(dw) << 24) & 0xff000000) | \
(((unsigned long)(dw) << 8) & 0x00ff0000) | \
(((unsigned long)(dw) >> 8) & 0x0000ff00) | \
(((unsigned long)(dw) >> 24) & 0x000000ff))
#define LittleEndianWORD(w) (w)
#define LittleEndianDWORD(dw) (dw)
#define BigEndianWORD(w) swapWORD(w)
#define BigEndianDWORD(dw) swapDWORD(dw)
#endif
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_device.h>
#include "usb.h"
#include "scsiglue.h"
#include "transport.h"
#include "init.h"
BYTE IsSSFDCCompliance;
BYTE IsXDCompliance;
extern DWORD MediaChange;
extern int Check_D_MediaFmt(struct us_data *);
//----- ENE_InitMedia() ----------------------------------------
int ENE_InitMedia(struct us_data *us)
{
int result;
BYTE MiscReg03 = 0;
printk("--- Initial Nedia ---\n");
result = ENE_Read_BYTE(us, REG_CARD_STATUS, &MiscReg03);
if (result != USB_STOR_XFER_GOOD)
{
printk("Read register fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
printk("MiscReg03 = %x\n", MiscReg03);
if (MiscReg03 & 0x01)
{
if (!us->SD_Status.Ready)
{
result = ENE_SDInit(us);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
}
}
if (MiscReg03 & 0x02)
{
if (!us->SM_Status.Ready && !us->MS_Status.Ready)
{
result = ENE_SMInit(us);
if (result != USB_STOR_XFER_GOOD)
{
result = ENE_MSInit(us);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
}
}
}
return result;
}
//----- ENE_Read_BYTE() ----------------------------------------
int ENE_Read_BYTE(struct us_data *us, WORD index, void *buf)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
int result;
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x01;
bcb->Flags = 0x80;
bcb->CDB[0] = 0xED;
bcb->CDB[2] = (BYTE)(index>>8);
bcb->CDB[3] = (BYTE)index;
result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
return result;
}
//----- ENE_SDInit() ---------------------
int ENE_SDInit(struct us_data *us)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
int result;
BYTE buf[0x200];
printk("transport --- ENE_SDInit\n");
// SD Init Part-1
result = ENE_LoadBinCode(us, SD_INIT1_PATTERN);
if (result != USB_STOR_XFER_GOOD)
{
printk("Load SD Init Code Part-1 Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->Flags = 0x80;
bcb->CDB[0] = 0xF2;
result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
if (result != USB_STOR_XFER_GOOD)
{
printk("Exection SD Init Code Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
// SD Init Part-2
result = ENE_LoadBinCode(us, SD_INIT2_PATTERN);
if (result != USB_STOR_XFER_GOOD)
{
printk("Load SD Init Code Part-2 Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x200;
bcb->Flags = 0x80;
bcb->CDB[0] = 0xF1;
result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0);
if (result != USB_STOR_XFER_GOOD)
{
printk("Exection SD Init Code Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
us->SD_Status = *(PSD_STATUS)&buf[0];
if (us->SD_Status.Insert && us->SD_Status.Ready)
{
ENE_ReadSDReg(us, (PBYTE)&buf);
printk("Insert = %x\n", us->SD_Status.Insert);
printk("Ready = %x\n", us->SD_Status.Ready);
printk("IsMMC = %x\n", us->SD_Status.IsMMC);
printk("HiCapacity = %x\n", us->SD_Status.HiCapacity);
printk("HiSpeed = %x\n", us->SD_Status.HiSpeed);
printk("WtP = %x\n", us->SD_Status.WtP);
}
else
{
printk("SD Card Not Ready --- %x\n", buf[0]);
return USB_STOR_TRANSPORT_ERROR;
}
return USB_STOR_TRANSPORT_GOOD;
}
//----- ENE_MSInit() ----------------------------------------
int ENE_MSInit(struct us_data *us)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
int result;
BYTE buf[0x200];
WORD MSP_BlockSize, MSP_UserAreaBlocks;
printk("transport --- ENE_MSInit\n");
result = ENE_LoadBinCode(us, MS_INIT_PATTERN);
if (result != USB_STOR_XFER_GOOD)
{
printk("Load MS Init Code Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x200;
bcb->Flags = 0x80;
bcb->CDB[0] = 0xF1;
bcb->CDB[1] = 0x01;
result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0);
if (result != USB_STOR_XFER_GOOD)
{
printk("Exection MS Init Code Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
us->MS_Status = *(PMS_STATUS)&buf[0];
if (us->MS_Status.Insert && us->MS_Status.Ready)
{
printk("Insert = %x\n", us->MS_Status.Insert);
printk("Ready = %x\n", us->MS_Status.Ready);
printk("IsMSPro = %x\n", us->MS_Status.IsMSPro);
printk("IsMSPHG = %x\n", us->MS_Status.IsMSPHG);
printk("WtP = %x\n", us->MS_Status.WtP);
if (us->MS_Status.IsMSPro)
{
MSP_BlockSize = (buf[6] <<8) | buf[7];
MSP_UserAreaBlocks = (buf[10]<<8) | buf[11];
us->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks;
}
else
MS_CardInit(us);
printk("MS Init Code OK !!\n");
}
else
{
printk("MS Card Not Ready --- %x\n", buf[0]);
return USB_STOR_TRANSPORT_ERROR;
}
return USB_STOR_TRANSPORT_GOOD;
}
//----- ENE_SMInit() ----------------------------------------
int ENE_SMInit(struct us_data *us)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
int result;
BYTE buf[0x200];
printk("transport --- ENE_SMInit\n");
result = ENE_LoadBinCode(us, SM_INIT_PATTERN);
if (result != USB_STOR_XFER_GOOD)
{
printk("Load SM Init Code Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x200;
bcb->Flags = 0x80;
bcb->CDB[0] = 0xF1;
bcb->CDB[1] = 0x01;
result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0);
if (result != USB_STOR_XFER_GOOD)
{
printk("Exection SM Init Code Fail !! result = %x\n", result);
return USB_STOR_TRANSPORT_ERROR;
}
us->SM_Status = *(PSM_STATUS)&buf[0];
us->SM_DeviceID = buf[1];
us->SM_CardID = buf[2];
if (us->SM_Status.Insert && us->SM_Status.Ready)
{
printk("Insert = %x\n", us->SM_Status.Insert);
printk("Ready = %x\n", us->SM_Status.Ready);
printk("WtP = %x\n", us->SM_Status.WtP);
printk("DeviceID = %x\n", us->SM_DeviceID);
printk("CardID = %x\n", us->SM_CardID);
MediaChange = 1;
Check_D_MediaFmt(us);
}
else
{
printk("SM Card Not Ready --- %x\n", buf[0]);
return USB_STOR_TRANSPORT_ERROR;
}
return USB_STOR_TRANSPORT_GOOD;
}
//----- ENE_ReadSDReg() ----------------------------------------------
int ENE_ReadSDReg(struct us_data *us, u8 *RdBuf)
{
WORD tmpreg;
DWORD reg4b;
//printk("transport --- ENE_ReadSDReg\n");
reg4b = *(PDWORD)&RdBuf[0x18];
us->SD_READ_BL_LEN = (BYTE)((reg4b >> 8) & 0x0f);
tmpreg = (WORD) reg4b;
reg4b = *(PDWORD)(&RdBuf[0x14]);
if (us->SD_Status.HiCapacity && !us->SD_Status.IsMMC)
us->HC_C_SIZE = (reg4b >> 8) & 0x3fffff;
us->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (WORD)(reg4b >> 22);
us->SD_C_SIZE_MULT = (BYTE)(reg4b >> 7) & 0x07;
if (us->SD_Status.HiCapacity && us->SD_Status.IsMMC)
us->HC_C_SIZE = *(PDWORD)(&RdBuf[0x100]);
if (us->SD_READ_BL_LEN > SD_BLOCK_LEN)
{
us->SD_Block_Mult = 1 << (us->SD_READ_BL_LEN - SD_BLOCK_LEN); us->SD_READ_BL_LEN = SD_BLOCK_LEN;
}
else
{ us->SD_Block_Mult = 1;
}
return USB_STOR_TRANSPORT_GOOD;
}
//----- ENE_LoadBinCode() ---------------------
int ENE_LoadBinCode(struct us_data *us, BYTE flag)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
int result;
//void *buf;
PBYTE buf;
//printk("transport --- ENE_LoadBinCode\n");
if (us->BIN_FLAG == flag)
return USB_STOR_TRANSPORT_GOOD;
buf = kmalloc(0x800, GFP_KERNEL);
switch ( flag )
{
// For SD
case SD_INIT1_PATTERN:
printk("SD_INIT1_PATTERN\n");
memcpy(buf, SD_Init1, 0x800);
break;
case SD_INIT2_PATTERN:
printk("SD_INIT2_PATTERN\n");
memcpy(buf, SD_Init2, 0x800);
break;
case SD_RW_PATTERN:
printk("SD_RW_PATTERN\n");
memcpy(buf, SD_Rdwr, 0x800);
break;
// For MS
case MS_INIT_PATTERN:
printk("MS_INIT_PATTERN\n");
memcpy(buf, MS_Init, 0x800);
break;
case MSP_RW_PATTERN:
printk("MSP_RW_PATTERN\n");
memcpy(buf, MSP_Rdwr, 0x800);
break;
case MS_RW_PATTERN:
printk("MS_RW_PATTERN\n");
memcpy(buf, MS_Rdwr, 0x800);
break;
// For SS
case SM_INIT_PATTERN:
printk("SM_INIT_PATTERN\n");
memcpy(buf, SM_Init, 0x800);
break;
case SM_RW_PATTERN:
printk("SM_RW_PATTERN\n");
memcpy(buf, SM_Rdwr, 0x800);
break;
}
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x800;
bcb->Flags =0x00;
bcb->CDB[0] = 0xEF;
result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
kfree(buf);
us->BIN_FLAG = flag;
return result;
}
//----- ENE_SendScsiCmd() ---------------------
int ENE_SendScsiCmd(struct us_data *us, BYTE fDir, void *buf, int use_sg)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
int result;
unsigned int transfer_length=bcb->DataTransferLength, cswlen=0, partial=0;
unsigned int residue;
//printk("transport --- ENE_SendScsiCmd\n");
// send cmd to out endpoint
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, US_BULK_CB_WRAP_LEN, NULL);
if (result != USB_STOR_XFER_GOOD)
{
printk("send cmd to out endpoint fail ---\n");
return USB_STOR_TRANSPORT_ERROR;
}
if (buf)
{
unsigned int pipe = fDir == FDIR_READ ? us->recv_bulk_pipe : us->send_bulk_pipe;
// Bulk
if (use_sg)
result = usb_stor_bulk_srb(us, pipe, us->srb);
else
result = usb_stor_bulk_transfer_sg(us, pipe, buf, transfer_length, 0, &partial);
if (result != USB_STOR_XFER_GOOD)
{
printk("data transfer fail ---\n");
return USB_STOR_TRANSPORT_ERROR;
}
}
// Get CSW for device status
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, &cswlen);
if (result == USB_STOR_XFER_SHORT && cswlen == 0)
{
printk("Received 0-length CSW; retrying...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, &cswlen);
}
if (result == USB_STOR_XFER_STALLED)
{
/* get the status again */
printk("Attempting to get CSW (2nd try)...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, NULL);
}
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
/* check bulk status */
residue = le32_to_cpu(bcs->Residue);
/* try to compute the actual residue, based on how much data
* was really transferred and what the device tells us */
if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE))
{
residue = min(residue, transfer_length);
scsi_set_resid(us->srb, max(scsi_get_resid(us->srb), (int) residue));
}
if (bcs->Status != US_BULK_STAT_OK)
return USB_STOR_TRANSPORT_ERROR;
return USB_STOR_TRANSPORT_GOOD;
}
//----- ENE_Read_Data() ---------------------
int ENE_Read_Data(struct us_data *us, void *buf, unsigned int length)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
int result;
//printk("transport --- ENE_Read_Data\n");
// set up the command wrapper
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = length;
bcb->Flags =0x80;
bcb->CDB[0] = 0xED;
bcb->CDB[2] = 0xFF;
bcb->CDB[3] = 0x81;
// send cmd to out endpoint
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, US_BULK_CB_WRAP_LEN, NULL);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
// R/W data
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, buf, length, NULL);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
// Get CSW for device status
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, NULL);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (bcs->Status != US_BULK_STAT_OK)
return USB_STOR_TRANSPORT_ERROR;
return USB_STOR_TRANSPORT_GOOD;
}
//----- ENE_Write_Data() ---------------------
int ENE_Write_Data(struct us_data *us, void *buf, unsigned int length)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
int result;
//printk("transport --- ENE_Write_Data\n");
// set up the command wrapper
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = length;
bcb->Flags =0x00;
bcb->CDB[0] = 0xEE;
bcb->CDB[2] = 0xFF;
bcb->CDB[3] = 0x81;
// send cmd to out endpoint
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, US_BULK_CB_WRAP_LEN, NULL);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
// R/W data
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, buf, length, NULL);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
// Get CSW for device status
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, NULL);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (bcs->Status != US_BULK_STAT_OK)
return USB_STOR_TRANSPORT_ERROR;
return USB_STOR_TRANSPORT_GOOD;
}
//----- usb_stor_print_cmd() ---------------------
void usb_stor_print_cmd(struct scsi_cmnd *srb)
{
PBYTE Cdb = srb->cmnd;
DWORD cmd = Cdb[0];
DWORD bn = ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
WORD blen = ((Cdb[7]<< 8) & 0xff00) | ((Cdb[8]<< 0) & 0x00ff);
switch (cmd) {
case TEST_UNIT_READY:
//printk("scsi cmd %X --- SCSIOP_TEST_UNIT_READY\n", cmd);
break;
case INQUIRY:
printk("scsi cmd %X --- SCSIOP_INQUIRY\n", cmd);
break;
case MODE_SENSE:
printk("scsi cmd %X --- SCSIOP_MODE_SENSE\n", cmd);
break;
case START_STOP:
printk("scsi cmd %X --- SCSIOP_START_STOP\n", cmd);
break;
case READ_CAPACITY:
printk("scsi cmd %X --- SCSIOP_READ_CAPACITY\n", cmd);
break;
case READ_10:
//printk("scsi cmd %X --- SCSIOP_READ, bn = %X, blen = %X\n", cmd, bn, blen);
break;
case WRITE_10:
//printk("scsi cmd %X --- SCSIOP_WRITE, bn = %X, blen = %X\n", cmd, bn, blen);
break;
case ALLOW_MEDIUM_REMOVAL:
printk("scsi cmd %X --- SCSIOP_ALLOW_MEDIUM_REMOVAL\n", cmd);
break;
default:
printk("scsi cmd %X --- Other cmd\n", cmd);
break;
}
bn = 0;
blen = 0;
}
此差异已折叠。
此差异已折叠。
#ifndef MS_INCD
#define MS_INCD
#include <linux/blkdev.h>
#include "common.h"
// MemoryStick Register
// Status Register 0
#define MS_REG_ST0_MB 0x80 // media busy
#define MS_REG_ST0_FB0 0x40 // flush busy 0
#define MS_REG_ST0_BE 0x20 // buffer empty
#define MS_REG_ST0_BF 0x10 // buffer full
#define MS_REG_ST0_SL 0x02 // sleep
#define MS_REG_ST0_WP 0x01 // write protected
#define MS_REG_ST0_WP_ON MS_REG_ST0_WP
#define MS_REG_ST0_WP_OFF 0x00
// Status Register 1
#define MS_REG_ST1_MB 0x80 // media busy
#define MS_REG_ST1_FB1 0x40 // flush busy 1
#define MS_REG_ST1_DTER 0x20 // error on data(corrected)
#define MS_REG_ST1_UCDT 0x10 // unable to correct data
#define MS_REG_ST1_EXER 0x08 // error on extra(corrected)
#define MS_REG_ST1_UCEX 0x04 // unable to correct extra
#define MS_REG_ST1_FGER 0x02 // error on overwrite flag(corrected)
#define MS_REG_ST1_UCFG 0x01 // unable to correct overwrite flag
#define MS_REG_ST1_DEFAULT (MS_REG_ST1_MB | MS_REG_ST1_FB1 | \
MS_REG_ST1_DTER | MS_REG_ST1_UCDT | \
MS_REG_ST1_EXER | MS_REG_ST1_UCEX | \
MS_REG_ST1_FGER | MS_REG_ST1_UCFG)
// System Parameter
#define MS_REG_SYSPAR_BAMD 0x80 // block address mode
#define MS_REG_SYSPAR_BAND_LINEAR MS_REG_SYSPAR_BAMD // linear mode
#define MS_REG_SYSPAR_BAND_CHIP 0x00 // chip mode
#define MS_REG_SYSPAR_ATEN 0x40 // attribute ROM enable
#define MS_REG_SYSPAR_ATEN_ENABLE MS_REG_SYSPAR_ATEN // enable
#define MS_REG_SYSPAR_ATEN_DISABLE 0x00 // disable
#define MS_REG_SYSPAR_RESERVED 0x2f
// Command Parameter
#define MS_REG_CMDPAR_CP2 0x80
#define MS_REG_CMDPAR_CP1 0x40
#define MS_REG_CMDPAR_CP0 0x20
#define MS_REG_CMDPAR_BLOCK_ACCESS 0
#define MS_REG_CMDPAR_PAGE_ACCESS MS_REG_CMDPAR_CP0
#define MS_REG_CMDPAR_EXTRA_DATA MS_REG_CMDPAR_CP1
#define MS_REG_CMDPAR_OVERWRITE MS_REG_CMDPAR_CP2
#define MS_REG_CMDPAR_RESERVED 0x1f
// Overwrite Area
#define MS_REG_OVR_BKST 0x80 // block status
#define MS_REG_OVR_BKST_OK MS_REG_OVR_BKST // OK
#define MS_REG_OVR_BKST_NG 0x00 // NG
#define MS_REG_OVR_PGST0 0x40 // page status
#define MS_REG_OVR_PGST1 0x20
#define MS_REG_OVR_PGST_MASK (MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1)
#define MS_REG_OVR_PGST_OK (MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1) // OK
#define MS_REG_OVR_PGST_NG MS_REG_OVR_PGST1 // NG
#define MS_REG_OVR_PGST_DATA_ERROR 0x00 // data error
#define MS_REG_OVR_UDST 0x10 // update status
#define MS_REG_OVR_UDST_UPDATING 0x00 // updating
#define MS_REG_OVR_UDST_NO_UPDATE MS_REG_OVR_UDST
#define MS_REG_OVR_RESERVED 0x08
#define MS_REG_OVR_DEFAULT (MS_REG_OVR_BKST_OK | \
MS_REG_OVR_PGST_OK | \
MS_REG_OVR_UDST_NO_UPDATE | \
MS_REG_OVR_RESERVED)
// Management Flag
#define MS_REG_MNG_SCMS0 0x20 // serial copy management system
#define MS_REG_MNG_SCMS1 0x10
#define MS_REG_MNG_SCMS_MASK (MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1)
#define MS_REG_MNG_SCMS_COPY_OK (MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1)
#define MS_REG_MNG_SCMS_ONE_COPY MS_REG_MNG_SCMS1
#define MS_REG_MNG_SCMS_NO_COPY 0x00
#define MS_REG_MNG_ATFLG 0x08 // address transfer table flag
#define MS_REG_MNG_ATFLG_OTHER MS_REG_MNG_ATFLG // other
#define MS_REG_MNG_ATFLG_ATTBL 0x00 // address transfer table
#define MS_REG_MNG_SYSFLG 0x04 // system flag
#define MS_REG_MNG_SYSFLG_USER MS_REG_MNG_SYSFLG // user block
#define MS_REG_MNG_SYSFLG_BOOT 0x00 // system block
#define MS_REG_MNG_RESERVED 0xc3
#define MS_REG_MNG_DEFAULT (MS_REG_MNG_SCMS_COPY_OK | \
MS_REG_MNG_ATFLG_OTHER | \
MS_REG_MNG_SYSFLG_USER | \
MS_REG_MNG_RESERVED)
// Error codes
#define MS_STATUS_SUCCESS 0x0000
#define MS_ERROR_OUT_OF_SPACE 0x0103
#define MS_STATUS_WRITE_PROTECT 0x0106
#define MS_ERROR_READ_DATA 0x8002
#define MS_ERROR_FLASH_READ 0x8003
#define MS_ERROR_FLASH_WRITE 0x8004
#define MS_ERROR_FLASH_ERASE 0x8005
#define MS_ERROR_FLASH_COPY 0x8006
#define MS_STATUS_ERROR 0xfffe
#define MS_FIFO_ERROR 0xfffd
#define MS_UNDEFINED_ERROR 0xfffc
#define MS_KETIMEOUT_ERROR 0xfffb
#define MS_STATUS_INT_ERROR 0xfffa
#define MS_NO_MEMORY_ERROR 0xfff9
#define MS_NOCARD_ERROR 0xfff8
#define MS_LB_NOT_USED 0xffff
#define MS_LB_ERROR 0xfff0
#define MS_LB_BOOT_BLOCK 0xfff1
#define MS_LB_INITIAL_ERROR 0xfff2
#define MS_STATUS_SUCCESS_WITH_ECC 0xfff3
#define MS_LB_ACQUIRED_ERROR 0xfff4
#define MS_LB_NOT_USED_ERASED 0xfff5
#define MS_LibConv2Physical(pdx, LogBlock) (((LogBlock) >= (pdx)->MS_Lib.NumberOfLogBlock) ? MS_STATUS_ERROR : (pdx)->MS_Lib.Log2PhyMap[LogBlock])
#define MS_LibConv2Logical(pdx, PhyBlock) (((PhyBlock) >= (pdx)->MS_Lib.NumberOfPhyBlock) ? MS_STATUS_ERROR : (pdx)->MS_Lib.Phy2LogMap[PhyBlock]) //dphy->log table
#define MS_LIB_CTRL_RDONLY 0
#define MS_LIB_CTRL_WRPROTECT 1
#define MS_LibCtrlCheck(pdx, Flag) ((pdx)->MS_Lib.flags & (1 << (Flag)))
#define MS_LibCtrlSet(pdx, Flag) (pdx)->MS_Lib.flags |= (1 << (Flag))
#define MS_LibCtrlReset(pdx, Flag) (pdx)->MS_Lib.flags &= ~(1 << (Flag))
#define MS_LibIsWritable(pdx) ((MS_LibCtrlCheck((pdx), MS_LIB_CTRL_RDONLY) == 0) && (MS_LibCtrlCheck(pdx, MS_LIB_CTRL_WRPROTECT) == 0))
#define MS_MAX_PAGES_PER_BLOCK 32
#define MS_LIB_BITS_PER_BYTE 8
#define MS_LibPageMapIdx(n) ((n) / MS_LIB_BITS_PER_BYTE)
#define MS_LibPageMapBit(n) (1 << ((n) % MS_LIB_BITS_PER_BYTE))
#define MS_LibCheckPageMapBit(pdx, n) ((pdx)->MS_Lib.pagemap[MS_LibPageMapIdx(n)] & MS_LibPageMapBit(n))
#define MS_LibSetPageMapBit(pdx, n) ((pdx)->MS_Lib.pagemap[MS_LibPageMapIdx(n)] |= MS_LibPageMapBit(n))
#define MS_LibResetPageMapBit(pdx, n) ((pdx)->MS_Lib.pagemap[MS_LibPageMapIdx(n)] &= ~MS_LibPageMapBit(n))
#define MS_LibClearPageMap(pdx) memset((pdx)->MS_Lib.pagemap, 0, sizeof((pdx)->MS_Lib.pagemap))
#define MemStickLogAddr(logadr1, logadr0) ((((WORD)(logadr1)) << 8) | (logadr0))
#define MS_BYTES_PER_PAGE 512
#define MS_MAX_INITIAL_ERROR_BLOCKS 10
#define MS_NUMBER_OF_PAGES_FOR_BOOT_BLOCK 3
#define MS_NUMBER_OF_PAGES_FOR_LPCTBL 2
#define MS_NUMBER_OF_BOOT_BLOCK 2
#define MS_NUMBER_OF_SYSTEM_BLOCK 4
#define MS_LOGICAL_BLOCKS_PER_SEGMENT 496
#define MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT 494
#define MS_PHYSICAL_BLOCKS_PER_SEGMENT 0x200 // 512
#define MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK 0x1ff
#define MS_SECTOR_SIZE 512
#define MBR_SIGNATURE 0xAA55
#define PBR_SIGNATURE 0xAA55
#define PARTITION_FAT_12 1
#define PARTITION_FAT_16 2
#define MS_BOOT_BLOCK_ID 0x0001
#define MS_BOOT_BLOCK_FORMAT_VERSION 0x0100
#define MS_BOOT_BLOCK_DATA_ENTRIES 2
#define MS_SYSINF_MSCLASS_TYPE_1 1
#define MS_SYSINF_CARDTYPE_RDONLY 1
#define MS_SYSINF_CARDTYPE_RDWR 2
#define MS_SYSINF_CARDTYPE_HYBRID 3
#define MS_SYSINF_SECURITY 0x01
#define MS_SYSINF_SECURITY_NO_SUPPORT MS_SYSINF_SECURITY
#define MS_SYSINF_SECURITY_SUPPORT 0
#define MS_SYSINF_FORMAT_MAT 0 // ?
#define MS_SYSINF_FORMAT_FAT 1
#define MS_SYSINF_USAGE_GENERAL 0
#define MS_SYSINF_PAGE_SIZE MS_BYTES_PER_PAGE // fixed
#define MS_SYSINF_RESERVED1 1
#define MS_SYSINF_RESERVED2 1
#define MS_SYSENT_TYPE_INVALID_BLOCK 0x01
#define MS_SYSENT_TYPE_CIS_IDI 0x0a // CIS/IDI
#define SIZE_OF_KIRO 1024
// BOOT BLOCK
#define MS_NUMBER_OF_SYSTEM_ENTRY 4
//----- MemStickRegisters --------------------------------------------
// Status registers (16 bytes)
typedef struct {
BYTE Reserved0; // 00
BYTE INTRegister; // 01
BYTE StatusRegister0; // 02
BYTE StatusRegister1; // 03
BYTE Reserved1[12]; // 04-0F
} MemStickStatusRegisters;
// Parameter registers (6 bytes)
typedef struct {
BYTE SystemParameter; // 10
BYTE BlockAddress2; // 11
BYTE BlockAddress1; // 12
BYTE BlockAddress0; // 13
BYTE CMDParameter; // 14
BYTE PageAddress; // 15
} MemStickParameterRegisters;
// Extra registers (9 bytes)
typedef struct {
BYTE OverwriteFlag; // 16
BYTE ManagementFlag; // 17
BYTE LogicalAddress1; // 18
BYTE LogicalAddress0; // 19
BYTE ReservedArea[5]; // 1A-1E
} MemStickExtraDataRegisters;
// All registers in Memory Stick (32 bytes, includes 1 byte padding)
typedef struct {
MemStickStatusRegisters status;
MemStickParameterRegisters param;
MemStickExtraDataRegisters extra;
BYTE padding;
} MemStickRegisters, *PMemStickRegisters;
//----- MemStickBootBlockPage0 ---------------------------------------
typedef struct {
WORD wBlockID;
WORD wFormatVersion;
BYTE bReserved1[184];
BYTE bNumberOfDataEntry;
BYTE bReserved2[179];
} MemStickBootBlockHeader;
typedef struct {
DWORD dwStart;
DWORD dwSize;
BYTE bType;
BYTE bReserved[3];
} MemStickBootBlockSysEntRec;
typedef struct {
MemStickBootBlockSysEntRec entry[MS_NUMBER_OF_SYSTEM_ENTRY];
} MemStickBootBlockSysEnt;
typedef struct {
BYTE bMsClass; // must be 1
BYTE bCardType; // see below
WORD wBlockSize; // n KB
WORD wBlockNumber; // number of physical block
WORD wTotalBlockNumber; // number of logical block
WORD wPageSize; // must be 0x200
BYTE bExtraSize; // 0x10
BYTE bSecuritySupport;
BYTE bAssemblyDate[8];
BYTE bFactoryArea[4];
BYTE bAssemblyMakerCode;
BYTE bAssemblyMachineCode[3];
WORD wMemoryMakerCode;
WORD wMemoryDeviceCode;
WORD wMemorySize;
BYTE bReserved1;
BYTE bReserved2;
BYTE bVCC;
BYTE bVPP;
WORD wControllerChipNumber;
WORD wControllerFunction; // New MS
BYTE bReserved3[9]; // New MS
BYTE bParallelSupport; // New MS
WORD wFormatValue; // New MS
BYTE bFormatType;
BYTE bUsage;
BYTE bDeviceType;
BYTE bReserved4[22];
BYTE bFUValue3;
BYTE bFUValue4;
BYTE bReserved5[15];
} MemStickBootBlockSysInf;
typedef struct {
MemStickBootBlockHeader header;
MemStickBootBlockSysEnt sysent;
MemStickBootBlockSysInf sysinf;
} MemStickBootBlockPage0;
//----- MemStickBootBlockCIS_IDI -------------------------------------
typedef struct {
BYTE bCistplDEVICE[6]; // 0
BYTE bCistplDEVICE0C[6]; // 6
BYTE bCistplJEDECC[4]; // 12
BYTE bCistplMANFID[6]; // 16
BYTE bCistplVER1[32]; // 22
BYTE bCistplFUNCID[4]; // 54
BYTE bCistplFUNCE0[4]; // 58
BYTE bCistplFUNCE1[5]; // 62
BYTE bCistplCONF[7]; // 67
BYTE bCistplCFTBLENT0[10]; // 74
BYTE bCistplCFTBLENT1[8]; // 84
BYTE bCistplCFTBLENT2[12]; // 92
BYTE bCistplCFTBLENT3[8]; // 104
BYTE bCistplCFTBLENT4[17]; // 112
BYTE bCistplCFTBLENT5[8]; // 129
BYTE bCistplCFTBLENT6[17]; // 137
BYTE bCistplCFTBLENT7[8]; // 154
BYTE bCistplNOLINK[3]; // 162
} MemStickBootBlockCIS;
typedef struct {
#define MS_IDI_GENERAL_CONF 0x848A
WORD wIDIgeneralConfiguration; // 0
WORD wIDInumberOfCylinder; // 1
WORD wIDIreserved0; // 2
WORD wIDInumberOfHead; // 3
WORD wIDIbytesPerTrack; // 4
WORD wIDIbytesPerSector; // 5
WORD wIDIsectorsPerTrack; // 6
WORD wIDItotalSectors[2]; // 7-8 high,low
WORD wIDIreserved1[11]; // 9-19
WORD wIDIbufferType; // 20
WORD wIDIbufferSize; // 21
WORD wIDIlongCmdECC; // 22
WORD wIDIfirmVersion[4]; // 23-26
WORD wIDImodelName[20]; // 27-46
WORD wIDIreserved2; // 47
WORD wIDIlongWordSupported; // 48
WORD wIDIdmaSupported; // 49
WORD wIDIreserved3; // 50
WORD wIDIpioTiming; // 51
WORD wIDIdmaTiming; // 52
WORD wIDItransferParameter; // 53
WORD wIDIformattedCylinder; // 54
WORD wIDIformattedHead; // 55
WORD wIDIformattedSectorsPerTrack; // 56
WORD wIDIformattedTotalSectors[2]; // 57-58
WORD wIDImultiSector; // 59
WORD wIDIlbaSectors[2]; // 60-61
WORD wIDIsingleWordDMA; // 62
WORD wIDImultiWordDMA; // 63
WORD wIDIreserved4[192]; // 64-255
} MemStickBootBlockIDI;
typedef struct {
union
{
MemStickBootBlockCIS cis;
BYTE dmy[256];
} cis;
union
{
MemStickBootBlockIDI idi;
BYTE dmy[256];
} idi;
} MemStickBootBlockCIS_IDI;
//----- MS_LibControl ------------------------------------------------
typedef struct {
BYTE reserved;
BYTE intr;
BYTE status0;
BYTE status1;
BYTE ovrflg;
BYTE mngflg;
WORD logadr;
} MS_LibTypeExtdat;
typedef struct {
DWORD flags;
DWORD BytesPerSector;
DWORD NumberOfCylinder;
DWORD SectorsPerCylinder;
WORD cardType; // R/W, RO, Hybrid
WORD blockSize;
WORD PagesPerBlock;
WORD NumberOfPhyBlock;
WORD NumberOfLogBlock;
WORD NumberOfSegment;
WORD *Phy2LogMap; //phy2log table
WORD *Log2PhyMap; //log2phy table
WORD wrtblk;
BYTE pagemap[(MS_MAX_PAGES_PER_BLOCK+(MS_LIB_BITS_PER_BYTE-1))/MS_LIB_BITS_PER_BYTE];
BYTE *blkpag;
MS_LibTypeExtdat *blkext;
BYTE copybuf[512];
} MS_LibControl;
#endif
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_device.h>
#include "usb.h"
#include "scsiglue.h"
#include "transport.h"
int MS_SCSI_Test_Unit_Ready (struct us_data *us, struct scsi_cmnd *srb);
int MS_SCSI_Inquiry (struct us_data *us, struct scsi_cmnd *srb);
int MS_SCSI_Mode_Sense (struct us_data *us, struct scsi_cmnd *srb);
int MS_SCSI_Start_Stop (struct us_data *us, struct scsi_cmnd *srb);
int MS_SCSI_Read_Capacity (struct us_data *us, struct scsi_cmnd *srb);
int MS_SCSI_Read (struct us_data *us, struct scsi_cmnd *srb);
int MS_SCSI_Write (struct us_data *us, struct scsi_cmnd *srb);
//----- MS_SCSIIrp() --------------------------------------------------
int MS_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb)
{
int result;
us->SrbStatus = SS_SUCCESS;
switch (srb->cmnd[0])
{
case TEST_UNIT_READY : result = MS_SCSI_Test_Unit_Ready (us, srb); break; //0x00
case INQUIRY : result = MS_SCSI_Inquiry (us, srb); break; //0x12
case MODE_SENSE : result = MS_SCSI_Mode_Sense (us, srb); break; //0x1A
case READ_CAPACITY : result = MS_SCSI_Read_Capacity (us, srb); break; //0x25
case READ_10 : result = MS_SCSI_Read (us, srb); break; //0x28
case WRITE_10 : result = MS_SCSI_Write (us, srb); break; //0x2A
default:
us->SrbStatus = SS_ILLEGAL_REQUEST;
result = USB_STOR_TRANSPORT_FAILED;
break;
}
return result;
}
//----- MS_SCSI_Test_Unit_Ready() --------------------------------------------------
int MS_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb)
{
//printk("MS_SCSI_Test_Unit_Ready\n");
if (us->MS_Status.Insert && us->MS_Status.Ready)
return USB_STOR_TRANSPORT_GOOD;
else
{
ENE_MSInit(us);
return USB_STOR_TRANSPORT_GOOD;
}
return USB_STOR_TRANSPORT_GOOD;
}
//----- MS_SCSI_Inquiry() --------------------------------------------------
int MS_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb)
{
//printk("MS_SCSI_Inquiry\n");
BYTE data_ptr[36] = {0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
usb_stor_set_xfer_buf(us, data_ptr, 36, srb, TO_XFER_BUF);
return USB_STOR_TRANSPORT_GOOD;
}
//----- MS_SCSI_Mode_Sense() --------------------------------------------------
int MS_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb)
{
BYTE mediaNoWP[12] = {0x0b,0x00,0x00,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
BYTE mediaWP[12] = {0x0b,0x00,0x80,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
if (us->MS_Status.WtP)
usb_stor_set_xfer_buf(us, mediaWP, 12, srb, TO_XFER_BUF);
else
usb_stor_set_xfer_buf(us, mediaNoWP, 12, srb, TO_XFER_BUF);
return USB_STOR_TRANSPORT_GOOD;
}
//----- MS_SCSI_Read_Capacity() --------------------------------------------------
int MS_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb)
{
unsigned int offset = 0;
struct scatterlist *sg = NULL;
DWORD bl_num;
WORD bl_len;
BYTE buf[8];
printk("MS_SCSI_Read_Capacity\n");
bl_len = 0x200;
if ( us->MS_Status.IsMSPro )
bl_num = us->MSP_TotalBlock - 1;
else
bl_num = us->MS_Lib.NumberOfLogBlock * us->MS_Lib.blockSize * 2 - 1;
us->bl_num = bl_num;
printk("bl_len = %x\n", bl_len);
printk("bl_num = %x\n", bl_num);
//srb->request_bufflen = 8;
buf[0] = (bl_num>>24) & 0xff;
buf[1] = (bl_num>>16) & 0xff;
buf[2] = (bl_num>> 8) & 0xff;
buf[3] = (bl_num>> 0) & 0xff;
buf[4] = (bl_len>>24) & 0xff;
buf[5] = (bl_len>>16) & 0xff;
buf[6] = (bl_len>> 8) & 0xff;
buf[7] = (bl_len>> 0) & 0xff;
usb_stor_access_xfer_buf(us, buf, 8, srb, &sg, &offset, TO_XFER_BUF);
//usb_stor_set_xfer_buf(us, buf, srb->request_bufflen, srb, TO_XFER_BUF);
return USB_STOR_TRANSPORT_GOOD;
}
//----- MS_SCSI_Read() --------------------------------------------------
int MS_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
int result=0;
PBYTE Cdb = srb->cmnd;
DWORD bn = ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
WORD blen = ((Cdb[7]<< 8) & 0xff00) | ((Cdb[8]<< 0) & 0x00ff);
DWORD blenByte = blen * 0x200;
//printk("SCSIOP_READ --- bn = %X, blen = %X, srb->use_sg = %X\n", bn, blen, srb->use_sg);
if (bn > us->bl_num)
return USB_STOR_TRANSPORT_ERROR;
if (us->MS_Status.IsMSPro)
{
result = ENE_LoadBinCode(us, MSP_RW_PATTERN);
if (result != USB_STOR_XFER_GOOD)
{
printk("Load MSP RW pattern Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
// set up the command wrapper
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = blenByte;
bcb->Flags = 0x80;
bcb->CDB[0] = 0xF1;
bcb->CDB[1] = 0x02;
bcb->CDB[5] = (BYTE)(bn);
bcb->CDB[4] = (BYTE)(bn>>8);
bcb->CDB[3] = (BYTE)(bn>>16);
bcb->CDB[2] = (BYTE)(bn>>24);
result = ENE_SendScsiCmd(us, FDIR_READ, scsi_sglist(srb), 1);
}
else
{
void *buf;
int offset=0;
WORD phyblk, logblk;
BYTE PageNum;
WORD len;
DWORD blkno;
buf = kmalloc(blenByte, GFP_KERNEL);
result = ENE_LoadBinCode(us, MS_RW_PATTERN);
if (result != USB_STOR_XFER_GOOD)
{
printk("Load MS RW pattern Fail !!\n");
result = USB_STOR_TRANSPORT_ERROR;
goto exit;
}
logblk = (WORD)(bn / us->MS_Lib.PagesPerBlock);
PageNum = (BYTE)(bn % us->MS_Lib.PagesPerBlock);
while(1)
{
if (blen > (us->MS_Lib.PagesPerBlock-PageNum) )
len = us->MS_Lib.PagesPerBlock-PageNum;
else
len = blen;
phyblk = MS_LibConv2Physical(us, logblk);
blkno = phyblk * 0x20 + PageNum;
// set up the command wrapper
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x200 * len;
bcb->Flags = 0x80;
bcb->CDB[0] = 0xF1;
bcb->CDB[1] = 0x02;
bcb->CDB[5] = (BYTE)(blkno);
bcb->CDB[4] = (BYTE)(blkno>>8);
bcb->CDB[3] = (BYTE)(blkno>>16);
bcb->CDB[2] = (BYTE)(blkno>>24);
result = ENE_SendScsiCmd(us, FDIR_READ, buf+offset, 0);
if (result != USB_STOR_XFER_GOOD)
{
printk("MS_SCSI_Read --- result = %x\n", result);
result = USB_STOR_TRANSPORT_ERROR;
goto exit;
}
blen -= len;
if (blen<=0)
break;
logblk++;
PageNum = 0;
offset += MS_BYTES_PER_PAGE*len;
}
usb_stor_set_xfer_buf(us, buf, blenByte, srb, TO_XFER_BUF);
exit:
kfree(buf);
}
return result;
}
//----- MS_SCSI_Write() --------------------------------------------------
int MS_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
int result=0;
PBYTE Cdb = srb->cmnd;
DWORD bn = ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
WORD blen = ((Cdb[7]<< 8) & 0xff00) | ((Cdb[8]<< 0) & 0x00ff);
DWORD blenByte = blen * 0x200;
if (bn > us->bl_num)
return USB_STOR_TRANSPORT_ERROR;
if (us->MS_Status.IsMSPro)
{
result = ENE_LoadBinCode(us, MSP_RW_PATTERN);
if (result != USB_STOR_XFER_GOOD)
{
printk("Load MSP RW pattern Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
// set up the command wrapper
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = blenByte;
bcb->Flags = 0x00;
bcb->CDB[0] = 0xF0;
bcb->CDB[1] = 0x04;
bcb->CDB[5] = (BYTE)(bn);
bcb->CDB[4] = (BYTE)(bn>>8);
bcb->CDB[3] = (BYTE)(bn>>16);
bcb->CDB[2] = (BYTE)(bn>>24);
result = ENE_SendScsiCmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
}
else
{
void *buf;
int offset=0;
WORD PhyBlockAddr;
BYTE PageNum;
DWORD result;
WORD len, oldphy, newphy;
buf = kmalloc(blenByte, GFP_KERNEL);
usb_stor_set_xfer_buf(us, buf, blenByte, srb, FROM_XFER_BUF);
result = ENE_LoadBinCode(us, MS_RW_PATTERN);
if (result != USB_STOR_XFER_GOOD)
{
printk("Load MS RW pattern Fail !!\n");
result = USB_STOR_TRANSPORT_ERROR;
goto exit;
}
PhyBlockAddr = (WORD)(bn / us->MS_Lib.PagesPerBlock);
PageNum = (BYTE)(bn % us->MS_Lib.PagesPerBlock);
while(1)
{
if (blen > (us->MS_Lib.PagesPerBlock-PageNum) )
len = us->MS_Lib.PagesPerBlock-PageNum;
else
len = blen;
oldphy = MS_LibConv2Physical(us, PhyBlockAddr);
newphy = MS_LibSearchBlockFromLogical(us, PhyBlockAddr);
result = MS_ReaderCopyBlock(us, oldphy, newphy, PhyBlockAddr, PageNum, buf+offset, len);
if (result != USB_STOR_XFER_GOOD)
{
printk("MS_SCSI_Write --- result = %x\n", result);
result = USB_STOR_TRANSPORT_ERROR;
goto exit;
}
us->MS_Lib.Phy2LogMap[oldphy] = MS_LB_NOT_USED_ERASED;
MS_LibForceSetLogicalPair(us, PhyBlockAddr, newphy);
blen -= len;
if (blen<=0)
break;
PhyBlockAddr++;
PageNum = 0;
offset += MS_BYTES_PER_PAGE*len;
}
exit:
kfree(buf);
}
return result;
}
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_devinfo.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_eh.h>
#include "usb.h"
#include "scsiglue.h"
#include "transport.h"
/* Host functions */
//----- host_info() ---------------------
static const char* host_info(struct Scsi_Host *host)
{
//printk("scsiglue --- host_info\n");
return "SCSI emulation for USB Mass Storage devices";
}
//----- slave_alloc() ---------------------
static int slave_alloc(struct scsi_device *sdev)
{
struct us_data *us = host_to_us(sdev->host);
//printk("scsiglue --- slave_alloc\n");
sdev->inquiry_len = 36;
blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
if (us->subclass == US_SC_UFI)
sdev->sdev_target->pdt_1f_for_no_lun = 1;
return 0;
}
//----- slave_configure() ---------------------
static int slave_configure(struct scsi_device *sdev)
{
struct us_data *us = host_to_us(sdev->host);
//printk("scsiglue --- slave_configure\n");
if (us->fflags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN))
{
unsigned int max_sectors = 64;
if (us->fflags & US_FL_MAX_SECTORS_MIN)
max_sectors = PAGE_CACHE_SIZE >> 9;
if (queue_max_sectors(sdev->request_queue) > max_sectors)
blk_queue_max_hw_sectors(sdev->request_queue,
max_sectors);
}
if (sdev->type == TYPE_DISK)
{
if (us->subclass != US_SC_SCSI && us->subclass != US_SC_CYP_ATACB)
sdev->use_10_for_ms = 1;
sdev->use_192_bytes_for_3f = 1;
if (us->fflags & US_FL_NO_WP_DETECT)
sdev->skip_ms_page_3f = 1;
sdev->skip_ms_page_8 = 1;
if (us->fflags & US_FL_FIX_CAPACITY)
sdev->fix_capacity = 1;
if (us->fflags & US_FL_CAPACITY_HEURISTICS)
sdev->guess_capacity = 1;
if (sdev->scsi_level > SCSI_2)
sdev->sdev_target->scsi_level = sdev->scsi_level = SCSI_2;
sdev->retry_hwerror = 1;
sdev->allow_restart = 1;
sdev->last_sector_bug = 1;
}
else
{
sdev->use_10_for_ms = 1;
}
if ((us->protocol == US_PR_CB || us->protocol == US_PR_CBI) && sdev->scsi_level == SCSI_UNKNOWN)
us->max_lun = 0;
if (us->fflags & US_FL_NOT_LOCKABLE)
sdev->lockable = 0;
return 0;
}
/* This is always called with scsi_lock(host) held */
//----- queuecommand() ---------------------
static int queuecommand(struct scsi_cmnd *srb, void (*done)(struct scsi_cmnd *))
{
struct us_data *us = host_to_us(srb->device->host);
//printk("scsiglue --- queuecommand\n");
/* check for state-transition errors */
if (us->srb != NULL)
{
printk("Error in %s: us->srb = %p\n", __FUNCTION__, us->srb);
return SCSI_MLQUEUE_HOST_BUSY;
}
/* fail the command if we are disconnecting */
if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags))
{
printk("Fail command during disconnect\n");
srb->result = DID_NO_CONNECT << 16;
done(srb);
return 0;
}
/* enqueue the command and wake up the control thread */
srb->scsi_done = done;
us->srb = srb;
complete(&us->cmnd_ready);
return 0;
}
/***********************************************************************
* Error handling functions
***********************************************************************/
/* Command timeout and abort */
//----- command_abort() ---------------------
static int command_abort(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
//printk("scsiglue --- command_abort\n");
scsi_lock(us_to_host(us));
if (us->srb != srb)
{
scsi_unlock(us_to_host(us));
printk ("-- nothing to abort\n");
return FAILED;
}
set_bit(US_FLIDX_TIMED_OUT, &us->dflags);
if (!test_bit(US_FLIDX_RESETTING, &us->dflags))
{
set_bit(US_FLIDX_ABORTING, &us->dflags);
usb_stor_stop_transport(us);
}
scsi_unlock(us_to_host(us));
/* Wait for the aborted command to finish */
wait_for_completion(&us->notify);
return SUCCESS;
}
/* This invokes the transport reset mechanism to reset the state of the device */
//----- device_reset() ---------------------
static int device_reset(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
int result;
//printk("scsiglue --- device_reset\n");
/* lock the device pointers and do the reset */
mutex_lock(&(us->dev_mutex));
result = us->transport_reset(us);
mutex_unlock(&us->dev_mutex);
return result < 0 ? FAILED : SUCCESS;
}
//----- bus_reset() ---------------------
static int bus_reset(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
int result;
//printk("scsiglue --- bus_reset\n");
result = usb_stor_port_reset(us);
return result < 0 ? FAILED : SUCCESS;
}
//----- usb_stor_report_device_reset() ---------------------
void usb_stor_report_device_reset(struct us_data *us)
{
int i;
struct Scsi_Host *host = us_to_host(us);
//printk("scsiglue --- usb_stor_report_device_reset\n");
scsi_report_device_reset(host, 0, 0);
if (us->fflags & US_FL_SCM_MULT_TARG)
{
for (i = 1; i < host->max_id; ++i)
scsi_report_device_reset(host, 0, i);
}
}
//----- usb_stor_report_bus_reset() ---------------------
void usb_stor_report_bus_reset(struct us_data *us)
{
struct Scsi_Host *host = us_to_host(us);
//printk("scsiglue --- usb_stor_report_bus_reset\n");
scsi_lock(host);
scsi_report_bus_reset(host, 0);
scsi_unlock(host);
}
/***********************************************************************
* /proc/scsi/ functions
***********************************************************************/
/* we use this macro to help us write into the buffer */
#undef SPRINTF
#define SPRINTF(args...) \
do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
//----- proc_info() ---------------------
static int proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout)
{
struct us_data *us = host_to_us(host);
char *pos = buffer;
const char *string;
//printk("scsiglue --- proc_info\n");
if (inout)
return length;
/* print the controller name */
SPRINTF(" Host scsi%d: usb-storage\n", host->host_no);
/* print product, vendor, and serial number strings */
if (us->pusb_dev->manufacturer)
string = us->pusb_dev->manufacturer;
else if (us->unusual_dev->vendorName)
string = us->unusual_dev->vendorName;
else
string = "Unknown";
SPRINTF(" Vendor: %s\n", string);
if (us->pusb_dev->product)
string = us->pusb_dev->product;
else if (us->unusual_dev->productName)
string = us->unusual_dev->productName;
else
string = "Unknown";
SPRINTF(" Product: %s\n", string);
if (us->pusb_dev->serial)
string = us->pusb_dev->serial;
else
string = "None";
SPRINTF("Serial Number: %s\n", string);
/* show the protocol and transport */
SPRINTF(" Protocol: %s\n", us->protocol_name);
SPRINTF(" Transport: %s\n", us->transport_name);
/* show the device flags */
if (pos < buffer + length)
{
pos += sprintf(pos, " Quirks:");
#define US_FLAG(name, value) \
if (us->fflags & value) pos += sprintf(pos, " " #name);
US_DO_ALL_FLAGS
#undef US_FLAG
*(pos++) = '\n';
}
/* Calculate start of next buffer, and return value. */
*start = buffer + offset;
if ((pos - buffer) < offset)
return (0);
else if ((pos - buffer - offset) < length)
return (pos - buffer - offset);
else
return (length);
}
/***********************************************************************
* Sysfs interface
***********************************************************************/
/* Output routine for the sysfs max_sectors file */
//----- show_max_sectors() ---------------------
static ssize_t show_max_sectors(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
//printk("scsiglue --- ssize_t show_max_sectors\n");
return sprintf(buf, "%u\n", queue_max_sectors(sdev->request_queue));
}
/* Input routine for the sysfs max_sectors file */
//----- store_max_sectors() ---------------------
static ssize_t store_max_sectors(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct scsi_device *sdev = to_scsi_device(dev);
unsigned short ms;
//printk("scsiglue --- ssize_t store_max_sectors\n");
if (sscanf(buf, "%hu", &ms) > 0 && ms <= SCSI_DEFAULT_MAX_SECTORS)
{
blk_queue_max_hw_sectors(sdev->request_queue, ms);
return strlen(buf);
}
return -EINVAL;
}
static DEVICE_ATTR(max_sectors, S_IRUGO | S_IWUSR, show_max_sectors, store_max_sectors);
static struct device_attribute *sysfs_device_attr_list[] = {&dev_attr_max_sectors, NULL, };
/* this defines our host template, with which we'll allocate hosts */
//----- usb_stor_host_template() ---------------------
struct scsi_host_template usb_stor_host_template = {
/* basic userland interface stuff */
.name = "eucr-storage",
.proc_name = "eucr-storage",
.proc_info = proc_info,
.info = host_info,
/* command interface -- queued only */
.queuecommand = queuecommand,
/* error and abort handlers */
.eh_abort_handler = command_abort,
.eh_device_reset_handler = device_reset,
.eh_bus_reset_handler = bus_reset,
/* queue commands only, only one command per LUN */
.can_queue = 1,
.cmd_per_lun = 1,
/* unknown initiator id */
.this_id = -1,
.slave_alloc = slave_alloc,
.slave_configure = slave_configure,
/* lots of sg segments can be handled */
.sg_tablesize = SG_ALL,
/* limit the total size of a transfer to 120 KB */
.max_sectors = 240,
/* merge commands... this seems to help performance, but
* periodically someone should test to see which setting is more
* optimal.
*/
.use_clustering = 1,
/* emulated HBA */
.emulated = 1,
/* we do our own delay after a device or bus reset */
.skip_settle_delay = 1,
/* sysfs device attributes */
.sdev_attrs = sysfs_device_attr_list,
/* module management */
.module = THIS_MODULE
};
/* To Report "Illegal Request: Invalid Field in CDB */
unsigned char usb_stor_sense_invalidCDB[18] = {
[0] = 0x70, /* current error */
[2] = ILLEGAL_REQUEST, /* Illegal Request = 0x05 */
[7] = 0x0a, /* additional length */
[12] = 0x24 /* Invalid Field in CDB */
};
/***********************************************************************
* Scatter-gather transfer buffer access routines
***********************************************************************/
//----- usb_stor_access_xfer_buf() ---------------------
unsigned int usb_stor_access_xfer_buf(struct us_data *us, unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
unsigned int *offset, enum xfer_buf_dir dir)
{
unsigned int cnt;
//printk("transport --- usb_stor_access_xfer_buf\n");
struct scatterlist *sg = *sgptr;
if (!sg)
sg = scsi_sglist(srb);
cnt = 0;
while (cnt < buflen && sg)
{
struct page *page = sg_page(sg) + ((sg->offset + *offset) >> PAGE_SHIFT);
unsigned int poff = (sg->offset + *offset) & (PAGE_SIZE-1);
unsigned int sglen = sg->length - *offset;
if (sglen > buflen - cnt)
{
/* Transfer ends within this s-g entry */
sglen = buflen - cnt;
*offset += sglen;
}
else
{
/* Transfer continues to next s-g entry */
*offset = 0;
sg = sg_next(sg);
}
while (sglen > 0)
{
unsigned int plen = min(sglen, (unsigned int)PAGE_SIZE - poff);
unsigned char *ptr = kmap(page);
if (dir == TO_XFER_BUF)
memcpy(ptr + poff, buffer + cnt, plen);
else
memcpy(buffer + cnt, ptr + poff, plen);
kunmap(page);
/* Start at the beginning of the next page */
poff = 0;
++page;
cnt += plen;
sglen -= plen;
}
}
*sgptr = sg;
/* Return the amount actually transferred */
return cnt;
}
/* Store the contents of buffer into srb's transfer buffer and set the SCSI residue. */
//----- usb_stor_set_xfer_buf() ---------------------
void usb_stor_set_xfer_buf(struct us_data *us, unsigned char *buffer, unsigned int buflen, struct scsi_cmnd *srb,
unsigned int dir)
{
unsigned int offset = 0;
struct scatterlist *sg = NULL;
//printk("transport --- usb_stor_set_xfer_buf\n");
// TO_XFER_BUF = 0, FROM_XFER_BUF = 1
buflen = min(buflen, scsi_bufflen(srb));
buflen = usb_stor_access_xfer_buf(us, buffer, buflen, srb, &sg, &offset, dir);
if (buflen < scsi_bufflen(srb))
scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
}
#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
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_device.h>
#include "usb.h"
#include "scsiglue.h"
#include "transport.h"
int SD_SCSI_Test_Unit_Ready (struct us_data *us, struct scsi_cmnd *srb);
int SD_SCSI_Inquiry (struct us_data *us, struct scsi_cmnd *srb);
int SD_SCSI_Mode_Sense (struct us_data *us, struct scsi_cmnd *srb);
int SD_SCSI_Start_Stop (struct us_data *us, struct scsi_cmnd *srb);
int SD_SCSI_Read_Capacity (struct us_data *us, struct scsi_cmnd *srb);
int SD_SCSI_Read (struct us_data *us, struct scsi_cmnd *srb);
int SD_SCSI_Write (struct us_data *us, struct scsi_cmnd *srb);
//----- SD_SCSIIrp() --------------------------------------------------
int SD_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb)
{
int result;
us->SrbStatus = SS_SUCCESS;
switch (srb->cmnd[0])
{
case TEST_UNIT_READY : result = SD_SCSI_Test_Unit_Ready (us, srb); break; //0x00
case INQUIRY : result = SD_SCSI_Inquiry (us, srb); break; //0x12
case MODE_SENSE : result = SD_SCSI_Mode_Sense (us, srb); break; //0x1A
// case START_STOP : result = SD_SCSI_Start_Stop (us, srb); break; //0x1B
case READ_CAPACITY : result = SD_SCSI_Read_Capacity (us, srb); break; //0x25
case READ_10 : result = SD_SCSI_Read (us, srb); break; //0x28
case WRITE_10 : result = SD_SCSI_Write (us, srb); break; //0x2A
default:
us->SrbStatus = SS_ILLEGAL_REQUEST;
result = USB_STOR_TRANSPORT_FAILED;
break;
}
return result;
}
//----- SD_SCSI_Test_Unit_Ready() --------------------------------------------------
int SD_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb)
{
//printk("SD_SCSI_Test_Unit_Ready\n");
if (us->SD_Status.Insert && us->SD_Status.Ready)
return USB_STOR_TRANSPORT_GOOD;
else
{
ENE_SDInit(us);
return USB_STOR_TRANSPORT_GOOD;
}
return USB_STOR_TRANSPORT_GOOD;
}
//----- SD_SCSI_Inquiry() --------------------------------------------------
int SD_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb)
{
//printk("SD_SCSI_Inquiry\n");
BYTE data_ptr[36] = {0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
usb_stor_set_xfer_buf(us, data_ptr, 36, srb, TO_XFER_BUF);
return USB_STOR_TRANSPORT_GOOD;
}
//----- SD_SCSI_Mode_Sense() --------------------------------------------------
int SD_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb)
{
BYTE mediaNoWP[12] = {0x0b,0x00,0x00,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
BYTE mediaWP[12] = {0x0b,0x00,0x80,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
if (us->SD_Status.WtP)
usb_stor_set_xfer_buf(us, mediaWP, 12, srb, TO_XFER_BUF);
else
usb_stor_set_xfer_buf(us, mediaNoWP, 12, srb, TO_XFER_BUF);
return USB_STOR_TRANSPORT_GOOD;
}
//----- SD_SCSI_Read_Capacity() --------------------------------------------------
int SD_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb)
{
unsigned int offset = 0;
struct scatterlist *sg = NULL;
DWORD bl_num;
WORD bl_len;
BYTE buf[8];
printk("SD_SCSI_Read_Capacity\n");
if ( us->SD_Status.HiCapacity )
{
bl_len = 0x200;
if (us->SD_Status.IsMMC)
bl_num = us->HC_C_SIZE-1;
else
bl_num = (us->HC_C_SIZE + 1) * 1024 - 1;
}
else
{
bl_len = 1<<(us->SD_READ_BL_LEN);
bl_num = us->SD_Block_Mult*(us->SD_C_SIZE+1)*(1<<(us->SD_C_SIZE_MULT+2)) - 1;
}
us->bl_num = bl_num;
printk("bl_len = %x\n", bl_len);
printk("bl_num = %x\n", bl_num);
//srb->request_bufflen = 8;
buf[0] = (bl_num>>24) & 0xff;
buf[1] = (bl_num>>16) & 0xff;
buf[2] = (bl_num>> 8) & 0xff;
buf[3] = (bl_num>> 0) & 0xff;
buf[4] = (bl_len>>24) & 0xff;
buf[5] = (bl_len>>16) & 0xff;
buf[6] = (bl_len>> 8) & 0xff;
buf[7] = (bl_len>> 0) & 0xff;
usb_stor_access_xfer_buf(us, buf, 8, srb, &sg, &offset, TO_XFER_BUF);
//usb_stor_set_xfer_buf(us, buf, srb->request_bufflen, srb, TO_XFER_BUF);
return USB_STOR_TRANSPORT_GOOD;
}
//----- SD_SCSI_Read() --------------------------------------------------
int SD_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
int result;
PBYTE Cdb = srb->cmnd;
DWORD bn = ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
WORD blen = ((Cdb[7]<< 8) & 0xff00) | ((Cdb[8]<< 0) & 0x00ff);
DWORD bnByte = bn * 0x200;
DWORD blenByte = blen * 0x200;
if (bn > us->bl_num)
return USB_STOR_TRANSPORT_ERROR;
result = ENE_LoadBinCode(us, SD_RW_PATTERN);
if (result != USB_STOR_XFER_GOOD)
{
printk("Load SD RW pattern Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
if ( us->SD_Status.HiCapacity )
bnByte = bn;
// set up the command wrapper
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = blenByte;
bcb->Flags = 0x80;
bcb->CDB[0] = 0xF1;
bcb->CDB[5] = (BYTE)(bnByte);
bcb->CDB[4] = (BYTE)(bnByte>>8);
bcb->CDB[3] = (BYTE)(bnByte>>16);
bcb->CDB[2] = (BYTE)(bnByte>>24);
result = ENE_SendScsiCmd(us, FDIR_READ, scsi_sglist(srb), 1);
return result;
}
//----- SD_SCSI_Write() --------------------------------------------------
int SD_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
int result;
PBYTE Cdb = srb->cmnd;
DWORD bn = ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
WORD blen = ((Cdb[7]<< 8) & 0xff00) | ((Cdb[8]<< 0) & 0x00ff);
DWORD bnByte = bn * 0x200;
DWORD blenByte = blen * 0x200;
if (bn > us->bl_num)
return USB_STOR_TRANSPORT_ERROR;
result = ENE_LoadBinCode(us, SD_RW_PATTERN);
if (result != USB_STOR_XFER_GOOD)
{
printk("Load SD RW pattern Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
if ( us->SD_Status.HiCapacity )
bnByte = bn;
// set up the command wrapper
memset(bcb, 0, sizeof(bcb));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = blenByte;
bcb->Flags = 0x00;
bcb->CDB[0] = 0xF0;
bcb->CDB[5] = (BYTE)(bnByte);
bcb->CDB[4] = (BYTE)(bnByte>>8);
bcb->CDB[3] = (BYTE)(bnByte>>16);
bcb->CDB[2] = (BYTE)(bnByte>>24);
result = ENE_SendScsiCmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
return result;
}
//----- < SMCommon.h> --------------------------------------------------
#ifndef SMCOMMON_INCD
#define SMCOMMON_INCD
/***************************************************************************
Define Difinetion
***************************************************************************/
#define SUCCESS 0x0000 /* SUCCESS */
#define ERROR 0xFFFF /* ERROR */
#define CORRECT 0x0001 /* CORRECTABLE */
/***************************************************************************/
#define NO_ERROR 0x0000 /* NO ERROR */
#define ERR_WriteFault 0x0003 /* Peripheral Device Write Fault */
#define ERR_HwError 0x0004 /* Hardware Error */
#define ERR_DataStatus 0x0010 /* DataStatus Error */
#define ERR_EccReadErr 0x0011 /* Unrecovered Read Error */
#define ERR_CorReadErr 0x0018 /* Recovered Read Data with ECC */
#define ERR_OutOfLBA 0x0021 /* Illegal Logical Block Address */
#define ERR_WrtProtect 0x0027 /* Write Protected */
#define ERR_ChangedMedia 0x0028 /* Medium Changed */
#define ERR_UnknownMedia 0x0030 /* Incompatible Medium Installed */
#define ERR_IllegalFmt 0x0031 /* Medium Format Corrupted */
#define ERR_NoSmartMedia 0x003A /* Medium Not Present */
/***************************************************************************/
//#define SUCCESS 0 /* SUCCESS */
//#define ERROR -1 /* ERROR */
/***************************************************************************/
char Bit_D_Count (BYTE);
char Bit_D_CountWord (WORD);
void StringCopy (char *, char *, int);
int StringCmp (char *, char *, int);
#endif // already included
//----- < smil.h> ----------------------------------------------------
#ifndef SMIL_INCD
#define SMIL_INCD
/***************************************************************************
Define Definition
***************************************************************************/
#define K_BYTE 1024 /* Kilo Byte */
#define SECTSIZE 512 /* Sector buffer size */
#define REDTSIZE 16 /* Redundant buffer size */
/***************************************************************************/
#define DUMMY_DATA 0xFF /* No Assign Sector Read Data */
/***************************************************************************
Max Zone/Block/Sectors Data Definition
***************************************************************************/
#define MAX_ZONENUM 128 /* Max Zone Numbers in a SmartMedia */
#define MAX_BLOCKNUM 0x0400 /* Max Block Numbers in a Zone */
#define MAX_SECTNUM 0x20 /* Max Sector Numbers in a Block */
#define MAX_LOGBLOCK 1000 /* Max Logical Block Numbers in a Zone */
/***************************************************************************/
#define CIS_SEARCH_SECT 0x08 /* Max CIS Search Sector Number */
/***************************************************************************
Logical to Physical Block Table Data Definition
***************************************************************************/
#define NO_ASSIGN 0xFFFF /* No Assign Logical Block Address */
/***************************************************************************
'SectCopyMode' Data
***************************************************************************/
#define COMPLETED 0 /* Sector Copy Completed */
#define REQ_ERASE 1 /* Request Read Block Erase */
#define REQ_FAIL 2 /* Request Read Block Failed */
/***************************************************************************
Retry Counter Definition
***************************************************************************/
#define RDERR_REASSIGN 1 /* Reassign with Read Error */
#define L2P_ERR_ERASE 1 /* BlockErase for Contradicted L2P Table */
/***************************************************************************
Hardware ECC Definition
***************************************************************************/
#define HW_ECC_SUPPORTED 1 /* Hardware ECC Supported */ /* No difinition for Software ECC */
/***************************************************************************
SmartMedia Command & Status Definition
***************************************************************************/
/* SmartMedia Command */
#define WRDATA 0x80
//#define READ 0x00
#define READ_REDT 0x50
//#define WRITE 0x10
#define RDSTATUS 0x70
#define READ1 0x00 //NO
#define READ2 0x01 //NO
#define READ3 0x50 //NO
#define RST_CHIP 0xFF
#define ERASE1 0x60
#define ERASE2 0xD0
#define READ_ID_1 0x90
#define READ_ID_2 0x91
#define READ_ID_3 0x9A
/* 712 SmartMedia Command */
#define SM_CMD_RESET 0x00 // 0xFF
#define SM_CMD_READ_ID_1 0x10 // 0x90
#define SM_CMD_READ_ID_2 0x20 // 0x91
#define SM_CMD_READ_STAT 0x30 // 0x70
#define SM_CMD_RDMULTPL_STAT 0x40 // 0x71
#define SM_CMD_READ_1 0x50 // 0x00
#define SM_CMD_READ_2 0x60 // 0x01
#define SM_CMD_READ_3 0x70 // 0x50
#define SM_CMD_PAGPRGM_TRUE 0x80 // {0x80, 0x10}
#define SM_CMD_PAGPRGM_DUMY 0x90 // {0x80, 0x11}
#define SM_CMD_PAGPRGM_MBLK 0xA0 // {0x80, 0x15}
#define SM_CMD_BLKERASE 0xB0 // {0x60, 0xD0}
#define SM_CMD_BLKERASE_MULTPL 0xC0 // {0x60-0x60, 0xD0}
#define SM_CRADDTCT_DEBNCETIMER_EN 0x02
#define SM_CMD_START_BIT 0x01
#define SM_WaitCmdDone { while (!SM_CmdDone); }
#define SM_WaitDmaDone { while (!SM_DmaDone); }
// SmartMedia Status
#define WR_FAIL 0x01 // 0:Pass, 1:Fail
#define SUSPENDED 0x20 // 0:Not Suspended, 1:Suspended
#define READY 0x40 // 0:Busy, 1:Ready
#define WR_PRTCT 0x80 // 0:Protect, 1:Not Protect
// SmartMedia Busy Time (1bit:0.1ms)
#define BUSY_PROG 200 // tPROG : 20ms ----- Program Time old : 200
#define BUSY_ERASE 4000 // tBERASE : 400ms ----- Block Erase Time old : 4000
//for 712 Test
//#define BUSY_READ 1 // tR : 100us ----- Data transfer Time old : 1
//#define BUSY_READ 10 // tR : 100us ----- Data transfer Time old : 1
#define BUSY_READ 200 // tR : 20ms ----- Data transfer Time old : 1
//#define BUSY_RESET 60 // tRST : 6ms ----- Device Resetting Time old : 60
#define BUSY_RESET 600 // tRST : 60ms ----- Device Resetting Time old : 60
// Hardware Timer (1bit:0.1ms)
#define TIME_PON 3000 // 300ms ------ Power On Wait Time
#define TIME_CDCHK 200 // 20ms ------ Card Check Interval Timer
#define TIME_WPCHK 50 // 5ms ------ WP Check Interval Timer
#define TIME_5VCHK 10 // 1ms ------ 5V Check Interval Timer
/***************************************************************************
Redundant Data
***************************************************************************/
#define REDT_DATA 0x04
#define REDT_BLOCK 0x05
#define REDT_ADDR1H 0x06
#define REDT_ADDR1L 0x07
#define REDT_ADDR2H 0x0B
#define REDT_ADDR2L 0x0C
#define REDT_ECC10 0x0D
#define REDT_ECC11 0x0E
#define REDT_ECC12 0x0F
#define REDT_ECC20 0x08
#define REDT_ECC21 0x09
#define REDT_ECC22 0x0A
/***************************************************************************
SmartMedia Model & Attribute
***************************************************************************/
/* SmartMedia Attribute */
#define NOWP 0x00 // 0... .... No Write Protect
#define WP 0x80 // 1... .... Write Protected
#define MASK 0x00 // .00. .... NAND MASK ROM Model
#define FLASH 0x20 // .01. .... NAND Flash ROM Model
#define AD3CYC 0x00 // ...0 .... Address 3-cycle
#define AD4CYC 0x10 // ...1 .... Address 4-cycle
#define BS16 0x00 // .... 00.. 16page/block
#define BS32 0x04 // .... 01.. 32page/block
#define PS256 0x00 // .... ..00 256byte/page
#define PS512 0x01 // .... ..01 512byte/page
#define MWP 0x80 // WriteProtect mask
#define MFLASH 0x60 // Flash Rom mask
#define MADC 0x10 // Address Cycle
#define MBS 0x0C // BlockSize mask
#define MPS 0x03 // PageSize mask
/* SmartMedia Model */
#define NOSSFDC 0x00 // NO SmartMedia
#define SSFDC1MB 0x01 // 1MB SmartMedia
#define SSFDC2MB 0x02 // 2MB SmartMedia
#define SSFDC4MB 0x03 // 4MB SmartMedia
#define SSFDC8MB 0x04 // 8MB SmartMedia
#define SSFDC16MB 0x05 // 16MB SmartMedia
#define SSFDC32MB 0x06 // 32MB SmartMedia
#define SSFDC64MB 0x07 // 64MB SmartMedia
#define SSFDC128MB 0x08 //128MB SmartMedia
#define SSFDC256MB 0x09
#define SSFDC512MB 0x0A
#define SSFDC1GB 0x0B
#define SSFDC2GB 0x0C
/***************************************************************************
Struct Definition
***************************************************************************/
struct SSFDCTYPE
{
BYTE Model;
BYTE Attribute;
BYTE MaxZones;
BYTE MaxSectors;
WORD MaxBlocks;
WORD MaxLogBlocks;
};
typedef struct SSFDCTYPE_T
{
BYTE Model;
BYTE Attribute;
BYTE MaxZones;
BYTE MaxSectors;
WORD MaxBlocks;
WORD MaxLogBlocks;
} *SSFDCTYPE_T;
struct ADDRESS
{
BYTE Zone; /* Zone Number */
BYTE Sector; /* Sector(512byte) Number on Block */
WORD PhyBlock; /* Physical Block Number on Zone */
WORD LogBlock; /* Logical Block Number of Zone */
};
typedef struct ADDRESS_T
{
BYTE Zone; /* Zone Number */
BYTE Sector; /* Sector(512byte) Number on Block */
WORD PhyBlock; /* Physical Block Number on Zone */
WORD LogBlock; /* Logical Block Number of Zone */
}*ADDRESS_T;
struct CIS_AREA
{
BYTE Sector; /* Sector(512byte) Number on Block */
WORD PhyBlock; /* Physical Block Number on Zone 0 */
};
//----- SMILMain.c ---------------------------------------------------
/******************************************/
int Init_D_SmartMedia (void);
int Pwoff_D_SmartMedia (void);
int Check_D_SmartMedia (void);
int Check_D_Parameter (struct us_data *,WORD *,BYTE *,BYTE *);
int Media_D_ReadSector (struct us_data *,DWORD,WORD,BYTE *);
int Media_D_WriteSector (struct us_data *,DWORD,WORD,BYTE *);
int Media_D_CopySector (struct us_data *,DWORD,WORD,BYTE *);
int Media_D_EraseBlock (struct us_data *,DWORD,WORD);
int Media_D_EraseAll (struct us_data *);
/******************************************/
int Media_D_OneSectWriteStart (struct us_data *,DWORD,BYTE *);
int Media_D_OneSectWriteNext (struct us_data *,BYTE *);
int Media_D_OneSectWriteFlush (struct us_data *);
/******************************************/
void SM_EnableLED (struct us_data *,BOOLEAN);
void Led_D_TernOn (void);
void Led_D_TernOff (void);
int Media_D_EraseAllRedtData (DWORD Index, BOOLEAN CheckBlock);
//DWORD Media_D_GetMediaInfo (struct us_data * fdoExt, PIOCTL_MEDIA_INFO_IN pParamIn, PIOCTL_MEDIA_INFO_OUT pParamOut);
//----- SMILSub.c ----------------------------------------------------
/******************************************/
int Check_D_DataBlank (BYTE *);
int Check_D_FailBlock (BYTE *);
int Check_D_DataStatus (BYTE *);
int Load_D_LogBlockAddr (BYTE *);
void Clr_D_RedundantData (BYTE *);
void Set_D_LogBlockAddr (BYTE *);
void Set_D_FailBlock (BYTE *);
void Set_D_DataStaus (BYTE *);
/******************************************/
void Ssfdc_D_Reset (struct us_data *);
int Ssfdc_D_ReadCisSect (struct us_data *, BYTE *,BYTE *);
void Ssfdc_D_WriteRedtMode (void);
void Ssfdc_D_ReadID (BYTE *, BYTE);
int Ssfdc_D_ReadSect (struct us_data *, BYTE *,BYTE *);
int Ssfdc_D_ReadBlock (struct us_data *, WORD, BYTE *,BYTE *);
int Ssfdc_D_WriteSect (struct us_data *, BYTE *,BYTE *);
int Ssfdc_D_WriteBlock (struct us_data *, WORD, BYTE *,BYTE *);
int Ssfdc_D_CopyBlock (struct us_data *, WORD, BYTE *,BYTE *);
int Ssfdc_D_WriteSectForCopy (struct us_data *, BYTE *,BYTE *);
int Ssfdc_D_EraseBlock (struct us_data *);
int Ssfdc_D_ReadRedtData (struct us_data *, BYTE *);
int Ssfdc_D_WriteRedtData (struct us_data *, BYTE *);
int Ssfdc_D_CheckStatus (void);
int Set_D_SsfdcModel (BYTE);
void Cnt_D_Reset (void);
int Cnt_D_PowerOn (void);
void Cnt_D_PowerOff (void);
void Cnt_D_LedOn (void);
void Cnt_D_LedOff (void);
int Check_D_CntPower (void);
int Check_D_CardExist (void);
int Check_D_CardStsChg (void);
int Check_D_SsfdcWP (void);
int SM_ReadBlock (struct us_data *, BYTE *,BYTE *);
int Ssfdc_D_ReadSect_DMA (struct us_data *, BYTE *,BYTE *);
int Ssfdc_D_ReadSect_PIO (struct us_data *, BYTE *,BYTE *);
int Ssfdc_D_WriteSect_DMA (struct us_data *, BYTE *,BYTE *);
int Ssfdc_D_WriteSect_PIO (struct us_data *, BYTE *,BYTE *);
/******************************************/
int Check_D_ReadError (BYTE *);
int Check_D_Correct (BYTE *,BYTE *);
int Check_D_CISdata (BYTE *,BYTE *);
void Set_D_RightECC (BYTE *);
//----- SMILECC.c ----------------------------------------------------
void calculate_ecc (BYTE *, BYTE *, BYTE *, BYTE *, BYTE *);
BYTE correct_data (BYTE *, BYTE *, BYTE, BYTE, BYTE);
int _Correct_D_SwECC (BYTE *,BYTE *,BYTE *);
void _Calculate_D_SwECC (BYTE *,BYTE *);
void SM_Init (void);
#endif // already included
#include "usb.h"
#include "scsiglue.h"
#include "transport.h"
//#include "stdlib.h"
//#include "EUCR6SK.h"
#include "smcommon.h"
#include "smil.h"
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//#include <dos.h>
//
//#include "EMCRIOS.h"
// CP0-CP5 code table
static BYTE ecctable[256] = {
0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00,
0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00
};
static void trans_result (BYTE, BYTE, BYTE *, BYTE *);
#define BIT7 0x80
#define BIT6 0x40
#define BIT5 0x20
#define BIT4 0x10
#define BIT3 0x08
#define BIT2 0x04
#define BIT1 0x02
#define BIT0 0x01
#define BIT1BIT0 0x03
#define BIT23 0x00800000L
#define MASK_CPS 0x3f
#define CORRECTABLE 0x00555554L
static void trans_result(reg2,reg3,ecc1,ecc2)
BYTE reg2; // LP14,LP12,LP10,...
BYTE reg3; // LP15,LP13,LP11,...
BYTE *ecc1; // LP15,LP14,LP13,...
BYTE *ecc2; // LP07,LP06,LP05,...
{
BYTE a; // Working for reg2,reg3
BYTE b; // Working for ecc1,ecc2
BYTE i; // For counting
a=BIT7; b=BIT7; // 80h=10000000b
*ecc1=*ecc2=0; // Clear ecc1,ecc2
for(i=0; i<4; ++i) {
if ((reg3&a)!=0)
*ecc1|=b; // LP15,13,11,9 -> ecc1
b=b>>1; // Right shift
if ((reg2&a)!=0)
*ecc1|=b; // LP14,12,10,8 -> ecc1
b=b>>1; // Right shift
a=a>>1; // Right shift
}
b=BIT7; // 80h=10000000b
for(i=0; i<4; ++i) {
if ((reg3&a)!=0)
*ecc2|=b; // LP7,5,3,1 -> ecc2
b=b>>1; // Right shift
if ((reg2&a)!=0)
*ecc2|=b; // LP6,4,2,0 -> ecc2
b=b>>1; // Right shift
a=a>>1; // Right shift
}
}
//static void calculate_ecc(table,data,ecc1,ecc2,ecc3)
void calculate_ecc(table,data,ecc1,ecc2,ecc3)
BYTE *table; // CP0-CP5 code table
BYTE *data; // DATA
BYTE *ecc1; // LP15,LP14,LP13,...
BYTE *ecc2; // LP07,LP06,LP05,...
BYTE *ecc3; // CP5,CP4,CP3,...,"1","1"
{
DWORD i; // For counting
BYTE a; // Working for table
BYTE reg1; // D-all,CP5,CP4,CP3,...
BYTE reg2; // LP14,LP12,L10,...
BYTE reg3; // LP15,LP13,L11,...
reg1=reg2=reg3=0; // Clear parameter
for(i=0; i<256; ++i) {
a=table[data[i]]; // Get CP0-CP5 code from table
reg1^=(a&MASK_CPS); // XOR with a
if ((a&BIT6)!=0)
{ // If D_all(all bit XOR) = 1
reg3^=(BYTE)i; // XOR with counter
reg2^=~((BYTE)i); // XOR with inv. of counter
}
}
// Trans LP14,12,10,... & LP15,13,11,... -> LP15,14,13,... & LP7,6,5,..
trans_result(reg2,reg3,ecc1,ecc2);
*ecc1=~(*ecc1); *ecc2=~(*ecc2); // Inv. ecc2 & ecc3
*ecc3=((~reg1)<<2)|BIT1BIT0; // Make TEL format
}
BYTE correct_data(data,eccdata,ecc1,ecc2,ecc3)
BYTE *data; // DATA
BYTE *eccdata; // ECC DATA
BYTE ecc1; // LP15,LP14,LP13,...
BYTE ecc2; // LP07,LP06,LP05,...
BYTE ecc3; // CP5,CP4,CP3,...,"1","1"
{
DWORD l; // Working to check d
DWORD d; // Result of comparison
DWORD i; // For counting
BYTE d1,d2,d3; // Result of comparison
BYTE a; // Working for add
BYTE add; // Byte address of cor. DATA
BYTE b; // Working for bit
BYTE bit; // Bit address of cor. DATA
d1=ecc1^eccdata[1]; d2=ecc2^eccdata[0]; // Compare LP's
d3=ecc3^eccdata[2]; // Comapre CP's
d=((DWORD)d1<<16) // Result of comparison
+((DWORD)d2<<8)
+(DWORD)d3;
if (d==0) return(0); // If No error, return
if (((d^(d>>1))&CORRECTABLE)==CORRECTABLE)
{ // If correctable
l=BIT23;
add=0; // Clear parameter
a=BIT7;
for(i=0; i<8; ++i) { // Checking 8 bit
if ((d&l)!=0) add|=a; // Make byte address from LP's
l>>=2; a>>=1; // Right Shift
}
bit=0; // Clear parameter
b=BIT2;
for(i=0; i<3; ++i) { // Checking 3 bit
if ((d&l)!=0) bit|=b; // Make bit address from CP's
l>>=2; b>>=1; // Right shift
}
b=BIT0;
data[add]^=(b<<bit); // Put corrected data
return(1);
}
i=0; // Clear count
d&=0x00ffffffL; // Masking
while(d) { // If d=0 finish counting
if (d&BIT0) ++i; // Count number of 1 bit
d>>=1; // Right shift
}
if (i==1)
{ // If ECC error
eccdata[1]=ecc1; eccdata[0]=ecc2; // Put right ECC code
eccdata[2]=ecc3;
return(2);
}
return(3); // Uncorrectable error
}
int _Correct_D_SwECC(buf,redundant_ecc,calculate_ecc)
BYTE *buf;
BYTE *redundant_ecc;
BYTE *calculate_ecc;
{
DWORD err;
err=correct_data(buf,redundant_ecc,*(calculate_ecc+1),*(calculate_ecc),*(calculate_ecc+2));
if (err==1) StringCopy(calculate_ecc,redundant_ecc,3);
if (err==0 || err==1 || err==2)
return(0);
return(-1);
}
void _Calculate_D_SwECC(buf,ecc)
BYTE *buf;
BYTE *ecc;
{
calculate_ecc(ecctable,buf,ecc+1,ecc+0,ecc+2);
}
此差异已折叠。
此差异已折叠。
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_device.h>
#include "usb.h"
#include "scsiglue.h"
#include "transport.h"
//#include "smcommon.h"
#include "smil.h"
int SM_SCSI_Test_Unit_Ready (struct us_data *us, struct scsi_cmnd *srb);
int SM_SCSI_Inquiry (struct us_data *us, struct scsi_cmnd *srb);
int SM_SCSI_Mode_Sense (struct us_data *us, struct scsi_cmnd *srb);
int SM_SCSI_Start_Stop (struct us_data *us, struct scsi_cmnd *srb);
int SM_SCSI_Read_Capacity (struct us_data *us, struct scsi_cmnd *srb);
int SM_SCSI_Read (struct us_data *us, struct scsi_cmnd *srb);
int SM_SCSI_Write (struct us_data *us, struct scsi_cmnd *srb);
extern struct SSFDCTYPE Ssfdc;
extern struct ADDRESS Media;
extern PBYTE SMHostAddr;
extern DWORD ErrXDCode;
//----- SM_SCSIIrp() --------------------------------------------------
int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb)
{
int result;
us->SrbStatus = SS_SUCCESS;
switch (srb->cmnd[0])
{
case TEST_UNIT_READY : result = SM_SCSI_Test_Unit_Ready (us, srb); break; //0x00
case INQUIRY : result = SM_SCSI_Inquiry (us, srb); break; //0x12
case MODE_SENSE : result = SM_SCSI_Mode_Sense (us, srb); break; //0x1A
case READ_CAPACITY : result = SM_SCSI_Read_Capacity (us, srb); break; //0x25
case READ_10 : result = SM_SCSI_Read (us, srb); break; //0x28
case WRITE_10 : result = SM_SCSI_Write (us, srb); break; //0x2A
default:
us->SrbStatus = SS_ILLEGAL_REQUEST;
result = USB_STOR_TRANSPORT_FAILED;
break;
}
return result;
}
//----- SM_SCSI_Test_Unit_Ready() --------------------------------------------------
int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb)
{
//printk("SM_SCSI_Test_Unit_Ready\n");
if (us->SM_Status.Insert && us->SM_Status.Ready)
return USB_STOR_TRANSPORT_GOOD;
else
{
ENE_SMInit(us);
return USB_STOR_TRANSPORT_GOOD;
}
return USB_STOR_TRANSPORT_GOOD;
}
//----- SM_SCSI_Inquiry() --------------------------------------------------
int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb)
{
//printk("SM_SCSI_Inquiry\n");
BYTE data_ptr[36] = {0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
usb_stor_set_xfer_buf(us, data_ptr, 36, srb, TO_XFER_BUF);
return USB_STOR_TRANSPORT_GOOD;
}
//----- SM_SCSI_Mode_Sense() --------------------------------------------------
int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb)
{
BYTE mediaNoWP[12] = {0x0b,0x00,0x00,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
BYTE mediaWP[12] = {0x0b,0x00,0x80,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
if (us->SM_Status.WtP)
usb_stor_set_xfer_buf(us, mediaWP, 12, srb, TO_XFER_BUF);
else
usb_stor_set_xfer_buf(us, mediaNoWP, 12, srb, TO_XFER_BUF);
return USB_STOR_TRANSPORT_GOOD;
}
//----- SM_SCSI_Read_Capacity() --------------------------------------------------
int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb)
{
unsigned int offset = 0;
struct scatterlist *sg = NULL;
DWORD bl_num;
WORD bl_len;
BYTE buf[8];
printk("SM_SCSI_Read_Capacity\n");
bl_len = 0x200;
bl_num = Ssfdc.MaxLogBlocks * Ssfdc.MaxSectors * Ssfdc.MaxZones - 1;
//printk("MaxLogBlocks = %x\n", Ssfdc.MaxLogBlocks);
//printk("MaxSectors = %x\n", Ssfdc.MaxSectors);
//printk("MaxZones = %x\n", Ssfdc.MaxZones);
//printk("bl_num = %x\n", bl_num);
us->bl_num = bl_num;
printk("bl_len = %x\n", bl_len);
printk("bl_num = %x\n", bl_num);
//srb->request_bufflen = 8;
buf[0] = (bl_num>>24) & 0xff;
buf[1] = (bl_num>>16) & 0xff;
buf[2] = (bl_num>> 8) & 0xff;
buf[3] = (bl_num>> 0) & 0xff;
buf[4] = (bl_len>>24) & 0xff;
buf[5] = (bl_len>>16) & 0xff;
buf[6] = (bl_len>> 8) & 0xff;
buf[7] = (bl_len>> 0) & 0xff;
usb_stor_access_xfer_buf(us, buf, 8, srb, &sg, &offset, TO_XFER_BUF);
//usb_stor_set_xfer_buf(us, buf, srb->request_bufflen, srb, TO_XFER_BUF);
return USB_STOR_TRANSPORT_GOOD;
}
//----- SM_SCSI_Read() --------------------------------------------------
int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb)
{
//struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
int result=0;
PBYTE Cdb = srb->cmnd;
DWORD bn = ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
WORD blen = ((Cdb[7]<< 8) & 0xff00) | ((Cdb[8]<< 0) & 0x00ff);
DWORD blenByte = blen * 0x200;
void *buf;
//printk("SCSIOP_READ --- bn = %X, blen = %X, srb->use_sg = %X\n", bn, blen, srb->use_sg);
if (bn > us->bl_num)
return USB_STOR_TRANSPORT_ERROR;
buf = kmalloc(blenByte, GFP_KERNEL);
result = Media_D_ReadSector(us, bn, blen, buf);
usb_stor_set_xfer_buf(us, buf, blenByte, srb, TO_XFER_BUF);
kfree(buf);
if (!result)
return USB_STOR_TRANSPORT_GOOD;
else
return USB_STOR_TRANSPORT_ERROR;
return USB_STOR_TRANSPORT_GOOD;
}
//----- SM_SCSI_Write() --------------------------------------------------
int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb)
{
//struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
int result=0;
PBYTE Cdb = srb->cmnd;
DWORD bn = ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
WORD blen = ((Cdb[7]<< 8) & 0xff00) | ((Cdb[8]<< 0) & 0x00ff);
DWORD blenByte = blen * 0x200;
void *buf;
//printk("SCSIOP_Write --- bn = %X, blen = %X, srb->use_sg = %X\n", bn, blen, srb->use_sg);
if (bn > us->bl_num)
return USB_STOR_TRANSPORT_ERROR;
buf = kmalloc(blenByte, GFP_KERNEL);
usb_stor_set_xfer_buf(us, buf, blenByte, srb, FROM_XFER_BUF);
result = Media_D_CopySector(us, bn, blen, buf);
kfree(buf);
if (!result)
return USB_STOR_TRANSPORT_GOOD;
else
return USB_STOR_TRANSPORT_ERROR;
return USB_STOR_TRANSPORT_GOOD;
}
此差异已折叠。
#ifndef _TRANSPORT_H_
#define _TRANSPORT_H_
#include <linux/blkdev.h>
/* Bulk only data structures */
/* command block wrapper */
struct bulk_cb_wrap {
__le32 Signature; /* contains 'USBC' */
__u32 Tag; /* unique per command id */
__le32 DataTransferLength; /* size of data */
__u8 Flags; /* direction in bit 0 */
__u8 Lun; /* LUN normally 0 */
__u8 Length; /* of of the CDB */
__u8 CDB[16]; /* max command */
};
#define US_BULK_CB_WRAP_LEN 31
#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */
#define US_BULK_FLAG_IN 1
#define US_BULK_FLAG_OUT 0
/* command status wrapper */
struct bulk_cs_wrap {
__le32 Signature; /* should = 'USBS' */
__u32 Tag; /* same as original command */
__le32 Residue; /* amount not transferred */
__u8 Status; /* see below */
__u8 Filler[18];
};
#define US_BULK_CS_WRAP_LEN 13
#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */
#define US_BULK_STAT_OK 0
#define US_BULK_STAT_FAIL 1
#define US_BULK_STAT_PHASE 2
/* bulk-only class specific requests */
#define US_BULK_RESET_REQUEST 0xff
#define US_BULK_GET_MAX_LUN 0xfe
/* usb_stor_bulk_transfer_xxx() return codes, in order of severity */
#define USB_STOR_XFER_GOOD 0 /* good transfer */
#define USB_STOR_XFER_SHORT 1 /* transferred less than expected */
#define USB_STOR_XFER_STALLED 2 /* endpoint stalled */
#define USB_STOR_XFER_LONG 3 /* device tried to send too much */
#define USB_STOR_XFER_ERROR 4 /* transfer died in the middle */
/* Transport return codes */
#define USB_STOR_TRANSPORT_GOOD 0 /* Transport good, command good */
#define USB_STOR_TRANSPORT_FAILED 1 /* Transport good, command failed */
#define USB_STOR_TRANSPORT_NO_SENSE 2 /* Command failed, no auto-sense */
#define USB_STOR_TRANSPORT_ERROR 3 /* Transport bad (i.e. device dead) */
/*
* We used to have USB_STOR_XFER_ABORTED and USB_STOR_TRANSPORT_ABORTED
* return codes. But now the transport and low-level transfer routines
* treat an abort as just another error (-ENOENT for a cancelled URB).
* It is up to the invoke_transport() function to test for aborts and
* distinguish them from genuine communication errors.
*/
/* CBI accept device specific command */
#define US_CBI_ADSC 0
extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data*);
extern int usb_stor_Bulk_max_lun(struct us_data*);
extern int usb_stor_Bulk_reset(struct us_data*);
extern void usb_stor_print_cmd(struct scsi_cmnd *);
extern void usb_stor_invoke_transport(struct scsi_cmnd *, struct us_data*);
extern void usb_stor_stop_transport(struct us_data*);
extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size, int timeout);
extern int usb_stor_clear_halt(struct us_data *us, unsigned int pipe);
extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
void *buf, unsigned int length, unsigned int *act_len);
extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
void *buf, unsigned int length, int use_sg, int *residual);
extern int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe,
struct scsi_cmnd* srb);
extern int usb_stor_port_reset(struct us_data *us);
/* Protocol handling routines */
enum xfer_buf_dir {TO_XFER_BUF, FROM_XFER_BUF};
extern unsigned int usb_stor_access_xfer_buf(struct us_data*, unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **,
unsigned int *offset, enum xfer_buf_dir dir);
extern void usb_stor_set_xfer_buf(struct us_data*, unsigned char *buffer, unsigned int buflen, struct scsi_cmnd *srb,
unsigned int dir);
// ENE scsi function
extern void ENE_stor_invoke_transport(struct scsi_cmnd *, struct us_data*);
extern int ENE_InitMedia(struct us_data*);
extern int ENE_SDInit(struct us_data*);
extern int ENE_MSInit(struct us_data*);
extern int ENE_SMInit(struct us_data*);
extern int ENE_ReadSDReg(struct us_data*, u8*);
extern int ENE_SendScsiCmd(struct us_data*, BYTE, void*, int);
extern int ENE_LoadBinCode(struct us_data*, BYTE);
extern int ENE_Read_BYTE(struct us_data*, WORD index, void *buf);
extern int ENE_Read_Data(struct us_data*, void *buf, unsigned int length);
extern int ENE_Write_Data(struct us_data*, void *buf, unsigned int length);
extern void BuildSenseBuffer(struct scsi_cmnd *, int);
// ENE scsi function
extern int SD_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
extern int MS_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
extern int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
// ENE MS function
extern int MS_CardInit(struct us_data *us);
extern void MS_LibFreeAllocatedArea(struct us_data *us);
extern void MS_LibFreeWriteBuf(struct us_data *us);
extern int MS_LibFreeLogicalMap(struct us_data *us);
extern int MS_LibForceSetLogicalPair(struct us_data *us, WORD logblk, WORD phyblk);
extern int MS_ReaderReadPage(struct us_data *us, DWORD PhyBlockAddr, BYTE PageNum, DWORD *PageBuf, MS_LibTypeExtdat *ExtraDat);
extern int MS_ReaderCopyBlock(struct us_data *us, WORD oldphy, WORD newphy, WORD PhyBlockAddr, BYTE PageNum, PBYTE buf, WORD len);
extern int MS_ReaderEraseBlock(struct us_data *us, DWORD PhyBlockAddr);
extern int MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData);
extern int MS_LibAllocLogicalMap(struct us_data *us);
extern int MS_LibSetBootBlockMark(struct us_data *us, WORD phyblk);
extern int MS_LibSetLogicalBlockMark(struct us_data *us, WORD phyblk, WORD mark);
extern int MS_LibSetInitialErrorBlock(struct us_data *us, WORD phyblk);
extern int MS_LibScanLogicalBlockNumber(struct us_data *us, WORD phyblk);
extern int MS_LibAllocWriteBuf(struct us_data *us);
void MS_LibClearWriteBuf(struct us_data *us);
void MS_LibPhy2LogRange(WORD PhyBlock, WORD *LogStart, WORD *LogEnde);
extern int MS_LibReadExtra(struct us_data *us, DWORD PhyBlock, BYTE PageNum, MS_LibTypeExtdat *ExtraDat);
extern int MS_LibReadExtraBlock(struct us_data *us, DWORD PhyBlock, BYTE PageNum, BYTE blen, void *buf);
extern int MS_LibSetAcquiredErrorBlock(struct us_data *us, WORD phyblk);
extern int MS_LibErasePhyBlock(struct us_data *us, WORD phyblk);
extern int MS_LibErrorPhyBlock(struct us_data *us, WORD phyblk);
extern int MS_LibOverwriteExtra(struct us_data *us, DWORD PhyBlockAddr, BYTE PageNum, BYTE OverwriteFlag);
extern int MS_LibSetLogicalPair(struct us_data *us, WORD logblk, WORD phyblk);
extern int MS_LibCheckDisableBlock(struct us_data *us, WORD PhyBlock);
extern int MS_CountFreeBlock(struct us_data *us, WORD PhyBlock);
extern int MS_LibSearchBlockFromLogical(struct us_data *us, WORD logblk);
extern int MS_LibSearchBlockFromPhysical(struct us_data *us, WORD phyblk);
// ENE SM function
extern int SM_FreeMem(void);
#endif
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册