Commit 16fae052 authored by Kristina Martšenko's avatar Kristina Martšenko Committed by Greg Kroah-Hartman

staging: keucr: remove driver

The driver hasn't been fully cleaned up and it doesn't look like anyone
is working on it anymore (including the original author). So remove the
driver and all references to it. If someone wants to finish cleaning
the driver up and moving it out of staging, this commit can be reverted.
Signed-off-by: default avatarKristina Martšenko <kristina.martsenko@gmail.com>
Cc: Cho, Yu-Chen <acho@novell.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0d317b91
......@@ -8619,11 +8619,6 @@ W: http://www.linux-speakup.org/
S: Odd Fixes
F: drivers/staging/speakup/
STAGING - USB ENE SM/MS CARD READER DRIVER
M: Al Cho <acho@novell.com>
S: Odd Fixes
F: drivers/staging/keucr/
STAGING - VIA VT665X DRIVERS
M: Forest Bond <forest@alittletooquiet.net>
S: Odd Fixes
......
......@@ -76,8 +76,6 @@ source "drivers/staging/quickstart/Kconfig"
source "drivers/staging/emxx_udc/Kconfig"
source "drivers/staging/keucr/Kconfig"
source "drivers/staging/bcm/Kconfig"
source "drivers/staging/ft1000/Kconfig"
......
......@@ -32,7 +32,6 @@ obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_FB_XGI) += xgifb/
obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/
obj-$(CONFIG_USB_EMXX) += emxx_udc/
obj-$(CONFIG_USB_ENESTORAGE) += keucr/
obj-$(CONFIG_BCM_WIMAX) += bcm/
obj-$(CONFIG_FT1000) += ft1000/
obj-$(CONFIG_SPEAKUP) += speakup/
......
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.
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
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>.
#ifndef COMMON_INCD
#define COMMON_INCD
#define BYTE_MASK 0xff
#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 "smil.h"
#include "init.h"
/*
* ENE_InitMedia():
*/
int ENE_InitMedia(struct us_data *us)
{
int result;
u8 MiscReg03 = 0;
dev_info(&us->pusb_dev->dev, "--- Init Media ---\n");
result = ene_read_byte(us, REG_CARD_STATUS, &MiscReg03);
if (result != USB_STOR_XFER_GOOD) {
dev_err(&us->pusb_dev->dev, "Failed to read register\n");
return USB_STOR_TRANSPORT_ERROR;
}
dev_info(&us->pusb_dev->dev, "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, u16 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] = (u8)(index>>8);
bcb->CDB[3] = (u8)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;
u8 buf[0x200];
dev_dbg(&us->pusb_dev->dev, "transport --- ENE_SMInit\n");
result = ENE_LoadBinCode(us, SM_INIT_PATTERN);
if (result != USB_STOR_XFER_GOOD) {
dev_info(&us->pusb_dev->dev,
"Failed to load SmartMedia init code\n: result= %x\n",
result);
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) {
dev_err(&us->pusb_dev->dev,
"Failed to load SmartMedia init code: result = %x\n",
result);
return USB_STOR_TRANSPORT_ERROR;
}
us->SM_Status = *(struct keucr_sm_status *)&buf[0];
us->SM_DeviceID = buf[1];
us->SM_CardID = buf[2];
if (us->SM_Status.Insert && us->SM_Status.Ready) {
dev_info(&us->pusb_dev->dev, "Insert = %x\n",
us->SM_Status.Insert);
dev_info(&us->pusb_dev->dev, "Ready = %x\n",
us->SM_Status.Ready);
dev_info(&us->pusb_dev->dev, "WtP = %x\n",
us->SM_Status.WtP);
dev_info(&us->pusb_dev->dev, "DeviceID = %x\n",
us->SM_DeviceID);
dev_info(&us->pusb_dev->dev, "CardID = %x\n",
us->SM_CardID);
MediaChange = 1;
Check_D_MediaFmt(us);
} else {
dev_err(&us->pusb_dev->dev,
"SmartMedia 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, u8 flag)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
int result;
/* void *buf; */
u8 *buf;
/* dev_info(&us->pusb_dev->dev, "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:
dev_dbg(&us->pusb_dev->dev, "SM_INIT_PATTERN\n");
memcpy(buf, SM_Init, 0x800);
break;
case SM_RW_PATTERN:
dev_dbg(&us->pusb_dev->dev, "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, u8 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;
/* dev_dbg(&us->pusb_dev->dev, "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) {
dev_err(&us->pusb_dev->dev,
"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) {
dev_err(&us->pusb_dev->dev, "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) {
dev_warn(&us->pusb_dev->dev,
"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 */
dev_warn(&us->pusb_dev->dev,
"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;
/* dev_dbg(&us->pusb_dev->dev, "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;
}
This diff is collapsed.
This diff is collapsed.
#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
/*----- < SMCommon.h> --------------------------------------------------*/
#ifndef SMCOMMON_INCD
#define SMCOMMON_INCD
/***************************************************************************
Define Definition
***************************************************************************/
#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
This diff is collapsed.
#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 u8 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(u8, u8, u8 *, u8 *);
#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(u8 reg2, u8 reg3, u8 *ecc1, u8 *ecc2)
{
u8 a; /* Working for reg2,reg3 */
u8 b; /* Working for ecc1,ecc2 */
u8 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(u8 *table, u8 *data, u8 *ecc1, u8 *ecc2, u8 *ecc3)
{
u32 i; /* For counting */
u8 a; /* Working for table */
u8 reg1; /* D-all,CP5,CP4,CP3,... */
u8 reg2; /* LP14,LP12,L10,... */
u8 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 ^= (u8)i; /* XOR with counter */
reg2 ^= ~((u8)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"
*/
u8 correct_data(u8 *data, u8 *eccdata, u8 ecc1, u8 ecc2, u8 ecc3)
{
u32 l; /* Working to check d */
u32 d; /* Result of comparison */
u32 i; /* For counting */
u8 d1, d2, d3; /* Result of comparison */
u8 a; /* Working for add */
u8 add; /* Byte address of cor. DATA */
u8 b; /* Working for bit */
u8 bit; /* Bit address of cor. DATA */
d1 = ecc1^eccdata[1]; d2 = ecc2^eccdata[0]; /* Compare LP's */
d3 = ecc3^eccdata[2]; /* Compare CP's */
d = ((u32)d1<<16) /* Result of comparison */
+((u32)d2<<8)
+(u32)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(u8 *buf, u8 *redundant_ecc, u8 *calculate_ecc)
{
u32 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(u8 *buf, u8 *ecc)
{
calculate_ecc(ecctable, buf, ecc+1, ecc+0, ecc+2);
}
This diff is collapsed.
This diff is collapsed.
#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"
static int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb);
static int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb);
static int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb);
static int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb);
static int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb);
static int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb);
/* ----- 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() ------------------------------------- */
static 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() --------------------------------------------- */
static int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb)
{
u8 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() ------------------------------------------ */
static int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb)
{
u8 mediaNoWP[12] = {0x0b, 0x00, 0x00, 0x08, 0x00, 0x00,
0x71, 0xc0, 0x00, 0x00, 0x02, 0x00};
u8 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() --------------------------------------- */
static int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb)
{
unsigned int offset = 0;
struct scatterlist *sg = NULL;
u32 bl_num;
u16 bl_len;
u8 buf[8];
dev_dbg(&us->pusb_dev->dev, "SM_SCSI_Read_Capacity\n");
bl_len = 0x200;
bl_num = Ssfdc.MaxLogBlocks * Ssfdc.MaxSectors * Ssfdc.MaxZones - 1;
us->bl_num = bl_num;
dev_dbg(&us->pusb_dev->dev, "bl_len = %x\n", bl_len);
dev_dbg(&us->pusb_dev->dev, "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() -------------------------------------------------- */
static int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb)
{
int result = 0;
u8 *Cdb = srb->cmnd;
u32 bn = ((Cdb[2] << 24) & 0xff000000) |
((Cdb[3] << 16) & 0x00ff0000) |
((Cdb[4] << 8) & 0x0000ff00) |
((Cdb[5] << 0) & 0x000000ff);
u16 blen = ((Cdb[7] << 8) & 0xff00) | ((Cdb[8] << 0) & 0x00ff);
u32 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() -------------------------------------------------- */
static int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb)
{
int result = 0;
u8 *Cdb = srb->cmnd;
u32 bn = ((Cdb[2] << 24) & 0xff000000) |
((Cdb[3] << 16) & 0x00ff0000) |
((Cdb[4] << 8) & 0x0000ff00) |
((Cdb[5] << 0) & 0x000000ff);
u16 blen = ((Cdb[7] << 8) & 0xff00) | ((Cdb[8] << 0) & 0x00ff);
u32 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;
}
This diff is collapsed.
#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_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*, u8, void*, int);
extern int ENE_LoadBinCode(struct us_data*, u8);
extern int ene_read_byte(struct us_data*, u16 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
This diff is collapsed.
/* 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
struct keucr_sd_status {
u8 Insert:1;
u8 Ready:1;
u8 MediaChange:1;
u8 IsMMC:1;
u8 HiCapacity:1;
u8 HiSpeed:1;
u8 WtP:1;
u8 Reserved:1;
};
struct keucr_ms_status {
u8 Insert:1;
u8 Ready:1;
u8 MediaChange:1;
u8 IsMSPro:1;
u8 IsMSPHG:1;
u8 Reserved1:1;
u8 WtP:1;
u8 Reserved2:1;
};
struct keucr_sm_status {
u8 Insert:1;
u8 Ready:1;
u8 MediaChange:1;
u8 Reserved:3;
u8 WtP:1;
u8 IsMS:1;
};
/* 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 */
struct keucr_sd_status SD_Status;
struct keucr_ms_status MS_Status;
struct keucr_sm_status SM_Status;
/* ----- SD Control Data ---------------- */
/* SD_REGISTER SD_Regs; */
u16 SD_Block_Mult;
u8 SD_READ_BL_LEN;
u16 SD_C_SIZE;
u8 SD_C_SIZE_MULT;
/* SD/MMC New spec. */
u8 SD_SPEC_VER;
u8 SD_CSD_VER;
u8 SD20_HIGH_CAPACITY;
u32 HC_C_SIZE;
u8 MMC_SPEC_VER;
u8 MMC_BusWidth;
u8 MMC_HIGH_CAPACITY;
/* ----- MS Control Data ---------------- */
bool MS_SWWP;
u32 MSP_TotalBlock;
/* MS_LibControl MS_Lib; */
bool MS_IsRWPage;
u16 MS_Model;
/* ----- SM Control Data ---------------- */
u8 SM_DeviceID;
u8 SM_CardID;
u8 *testbuf;
u8 BIN_FLAG;
u32 bl_num;
int SrbStatus;
/* ------Power Managerment --------------- */
bool 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
......@@ -193,7 +193,7 @@ config USB_STORAGE_ENE_UB6250
depends on USB_STORAGE
---help---
Say Y here if you wish to control a ENE SD/MS Card reader.
To use SM card, please build driver/staging/keucr/keucr.ko
Note that this driver does not support SM cards.
This option depends on 'SCSI' support being enabled, but you
probably also need 'SCSI device support: SCSI disk support'
......
......@@ -2344,8 +2344,8 @@ static int ene_ub6250_probe(struct usb_interface *intf,
}
if (!(misc_reg03 & 0x01)) {
pr_info("ums_eneub6250: The driver only supports SD/MS card. "
"To use SM card, please build driver/staging/keucr\n");
pr_info("ums_eneub6250: This driver only supports SD/MS cards. "
"It does not support SM cards.\n");
}
return result;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment