141e568d1Shuajun li /* 241e568d1Shuajun li * 341e568d1Shuajun li * This program is free software; you can redistribute it and/or modify it 441e568d1Shuajun li * under the terms of the GNU General Public License as published by the 541e568d1Shuajun li * Free Software Foundation; either version 2, or (at your option) any 641e568d1Shuajun li * later version. 741e568d1Shuajun li * 841e568d1Shuajun li * This program is distributed in the hope that it will be useful, but 941e568d1Shuajun li * WITHOUT ANY WARRANTY; without even the implied warranty of 1041e568d1Shuajun li * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1141e568d1Shuajun li * General Public License for more details. 1241e568d1Shuajun li * 1341e568d1Shuajun li * You should have received a copy of the GNU General Public License along 1441e568d1Shuajun li * with this program; if not, write to the Free Software Foundation, Inc., 1541e568d1Shuajun li * 675 Mass Ave, Cambridge, MA 02139, USA. 1641e568d1Shuajun li */ 1741e568d1Shuajun li #include <linux/jiffies.h> 1841e568d1Shuajun li #include <linux/errno.h> 1941e568d1Shuajun li #include <linux/module.h> 2041e568d1Shuajun li #include <linux/slab.h> 2141e568d1Shuajun li 2241e568d1Shuajun li #include <scsi/scsi.h> 2341e568d1Shuajun li #include <scsi/scsi_cmnd.h> 2441e568d1Shuajun li 2541e568d1Shuajun li #include <linux/firmware.h> 2641e568d1Shuajun li 2741e568d1Shuajun li #include "usb.h" 2841e568d1Shuajun li #include "transport.h" 2941e568d1Shuajun li #include "protocol.h" 3041e568d1Shuajun li #include "debug.h" 31aa519be3SAkinobu Mita #include "scsiglue.h" 3241e568d1Shuajun li 33595c8970STim Gardner #define SD_INIT1_FIRMWARE "ene-ub6250/sd_init1.bin" 34595c8970STim Gardner #define SD_INIT2_FIRMWARE "ene-ub6250/sd_init2.bin" 35595c8970STim Gardner #define SD_RW_FIRMWARE "ene-ub6250/sd_rdwr.bin" 36595c8970STim Gardner #define MS_INIT_FIRMWARE "ene-ub6250/ms_init.bin" 37595c8970STim Gardner #define MSP_RW_FIRMWARE "ene-ub6250/msp_rdwr.bin" 38595c8970STim Gardner #define MS_RW_FIRMWARE "ene-ub6250/ms_rdwr.bin" 39595c8970STim Gardner 40aa519be3SAkinobu Mita #define DRV_NAME "ums_eneub6250" 41aa519be3SAkinobu Mita 4241e568d1Shuajun li MODULE_DESCRIPTION("Driver for ENE UB6250 reader"); 4341e568d1Shuajun li MODULE_LICENSE("GPL"); 44595c8970STim Gardner MODULE_FIRMWARE(SD_INIT1_FIRMWARE); 45595c8970STim Gardner MODULE_FIRMWARE(SD_INIT2_FIRMWARE); 46595c8970STim Gardner MODULE_FIRMWARE(SD_RW_FIRMWARE); 47595c8970STim Gardner MODULE_FIRMWARE(MS_INIT_FIRMWARE); 48595c8970STim Gardner MODULE_FIRMWARE(MSP_RW_FIRMWARE); 49595c8970STim Gardner MODULE_FIRMWARE(MS_RW_FIRMWARE); 5041e568d1Shuajun li 5141e568d1Shuajun li /* 5241e568d1Shuajun li * The table of devices 5341e568d1Shuajun li */ 5441e568d1Shuajun li #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ 5541e568d1Shuajun li vendorName, productName, useProtocol, useTransport, \ 5641e568d1Shuajun li initFunction, flags) \ 5741e568d1Shuajun li { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ 58f61870eeSSebastian Andrzej Siewior .driver_info = (flags)} 5941e568d1Shuajun li 6036f3a14dSFelipe Balbi static struct usb_device_id ene_ub6250_usb_ids[] = { 6141e568d1Shuajun li # include "unusual_ene_ub6250.h" 6241e568d1Shuajun li { } /* Terminating entry */ 6341e568d1Shuajun li }; 6441e568d1Shuajun li MODULE_DEVICE_TABLE(usb, ene_ub6250_usb_ids); 6541e568d1Shuajun li 6641e568d1Shuajun li #undef UNUSUAL_DEV 6741e568d1Shuajun li 6841e568d1Shuajun li /* 6941e568d1Shuajun li * The flags table 7041e568d1Shuajun li */ 7141e568d1Shuajun li #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ 7241e568d1Shuajun li vendor_name, product_name, use_protocol, use_transport, \ 7341e568d1Shuajun li init_function, Flags) \ 7441e568d1Shuajun li { \ 7541e568d1Shuajun li .vendorName = vendor_name, \ 7641e568d1Shuajun li .productName = product_name, \ 7741e568d1Shuajun li .useProtocol = use_protocol, \ 7841e568d1Shuajun li .useTransport = use_transport, \ 7941e568d1Shuajun li .initFunction = init_function, \ 8041e568d1Shuajun li } 8141e568d1Shuajun li 8241e568d1Shuajun li static struct us_unusual_dev ene_ub6250_unusual_dev_list[] = { 8341e568d1Shuajun li # include "unusual_ene_ub6250.h" 8441e568d1Shuajun li { } /* Terminating entry */ 8541e568d1Shuajun li }; 8641e568d1Shuajun li 8741e568d1Shuajun li #undef UNUSUAL_DEV 8841e568d1Shuajun li 8941e568d1Shuajun li 9041e568d1Shuajun li 9141e568d1Shuajun li /* ENE bin code len */ 9241e568d1Shuajun li #define ENE_BIN_CODE_LEN 0x800 9341e568d1Shuajun li /* EnE HW Register */ 9441e568d1Shuajun li #define REG_CARD_STATUS 0xFF83 9541e568d1Shuajun li #define REG_HW_TRAP1 0xFF89 9641e568d1Shuajun li 9741e568d1Shuajun li /* SRB Status */ 9841e568d1Shuajun li #define SS_SUCCESS 0x00 /* No Sense */ 9941e568d1Shuajun li #define SS_NOT_READY 0x02 10041e568d1Shuajun li #define SS_MEDIUM_ERR 0x03 10141e568d1Shuajun li #define SS_HW_ERR 0x04 10241e568d1Shuajun li #define SS_ILLEGAL_REQUEST 0x05 10341e568d1Shuajun li #define SS_UNIT_ATTENTION 0x06 10441e568d1Shuajun li 10541e568d1Shuajun li /* ENE Load FW Pattern */ 10641e568d1Shuajun li #define SD_INIT1_PATTERN 1 10741e568d1Shuajun li #define SD_INIT2_PATTERN 2 10841e568d1Shuajun li #define SD_RW_PATTERN 3 10941e568d1Shuajun li #define MS_INIT_PATTERN 4 11041e568d1Shuajun li #define MSP_RW_PATTERN 5 11141e568d1Shuajun li #define MS_RW_PATTERN 6 11241e568d1Shuajun li #define SM_INIT_PATTERN 7 11341e568d1Shuajun li #define SM_RW_PATTERN 8 11441e568d1Shuajun li 11541e568d1Shuajun li #define FDIR_WRITE 0 11641e568d1Shuajun li #define FDIR_READ 1 11741e568d1Shuajun li 11833842cedSCho, Yu-Chen /* For MS Card */ 11933842cedSCho, Yu-Chen 12033842cedSCho, Yu-Chen /* Status Register 1 */ 12133842cedSCho, Yu-Chen #define MS_REG_ST1_MB 0x80 /* media busy */ 12233842cedSCho, Yu-Chen #define MS_REG_ST1_FB1 0x40 /* flush busy 1 */ 12333842cedSCho, Yu-Chen #define MS_REG_ST1_DTER 0x20 /* error on data(corrected) */ 12433842cedSCho, Yu-Chen #define MS_REG_ST1_UCDT 0x10 /* unable to correct data */ 12533842cedSCho, Yu-Chen #define MS_REG_ST1_EXER 0x08 /* error on extra(corrected) */ 12633842cedSCho, Yu-Chen #define MS_REG_ST1_UCEX 0x04 /* unable to correct extra */ 12733842cedSCho, Yu-Chen #define MS_REG_ST1_FGER 0x02 /* error on overwrite flag(corrected) */ 12833842cedSCho, Yu-Chen #define MS_REG_ST1_UCFG 0x01 /* unable to correct overwrite flag */ 12933842cedSCho, Yu-Chen #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) 13033842cedSCho, Yu-Chen 13133842cedSCho, Yu-Chen /* Overwrite Area */ 13233842cedSCho, Yu-Chen #define MS_REG_OVR_BKST 0x80 /* block status */ 13333842cedSCho, Yu-Chen #define MS_REG_OVR_BKST_OK MS_REG_OVR_BKST /* OK */ 13433842cedSCho, Yu-Chen #define MS_REG_OVR_BKST_NG 0x00 /* NG */ 13533842cedSCho, Yu-Chen #define MS_REG_OVR_PGST0 0x40 /* page status */ 13633842cedSCho, Yu-Chen #define MS_REG_OVR_PGST1 0x20 13733842cedSCho, Yu-Chen #define MS_REG_OVR_PGST_MASK (MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1) 13833842cedSCho, Yu-Chen #define MS_REG_OVR_PGST_OK (MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1) /* OK */ 13933842cedSCho, Yu-Chen #define MS_REG_OVR_PGST_NG MS_REG_OVR_PGST1 /* NG */ 14033842cedSCho, Yu-Chen #define MS_REG_OVR_PGST_DATA_ERROR 0x00 /* data error */ 14133842cedSCho, Yu-Chen #define MS_REG_OVR_UDST 0x10 /* update status */ 14233842cedSCho, Yu-Chen #define MS_REG_OVR_UDST_UPDATING 0x00 /* updating */ 14333842cedSCho, Yu-Chen #define MS_REG_OVR_UDST_NO_UPDATE MS_REG_OVR_UDST 14433842cedSCho, Yu-Chen #define MS_REG_OVR_RESERVED 0x08 14533842cedSCho, Yu-Chen #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) 14633842cedSCho, Yu-Chen 14733842cedSCho, Yu-Chen /* Management Flag */ 14833842cedSCho, Yu-Chen #define MS_REG_MNG_SCMS0 0x20 /* serial copy management system */ 14933842cedSCho, Yu-Chen #define MS_REG_MNG_SCMS1 0x10 15033842cedSCho, Yu-Chen #define MS_REG_MNG_SCMS_MASK (MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1) 15133842cedSCho, Yu-Chen #define MS_REG_MNG_SCMS_COPY_OK (MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1) 15233842cedSCho, Yu-Chen #define MS_REG_MNG_SCMS_ONE_COPY MS_REG_MNG_SCMS1 15333842cedSCho, Yu-Chen #define MS_REG_MNG_SCMS_NO_COPY 0x00 15433842cedSCho, Yu-Chen #define MS_REG_MNG_ATFLG 0x08 /* address transfer table flag */ 15533842cedSCho, Yu-Chen #define MS_REG_MNG_ATFLG_OTHER MS_REG_MNG_ATFLG /* other */ 15633842cedSCho, Yu-Chen #define MS_REG_MNG_ATFLG_ATTBL 0x00 /* address transfer table */ 15733842cedSCho, Yu-Chen #define MS_REG_MNG_SYSFLG 0x04 /* system flag */ 15833842cedSCho, Yu-Chen #define MS_REG_MNG_SYSFLG_USER MS_REG_MNG_SYSFLG /* user block */ 15933842cedSCho, Yu-Chen #define MS_REG_MNG_SYSFLG_BOOT 0x00 /* system block */ 16033842cedSCho, Yu-Chen #define MS_REG_MNG_RESERVED 0xc3 16133842cedSCho, Yu-Chen #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) 16233842cedSCho, Yu-Chen 16333842cedSCho, Yu-Chen 16433842cedSCho, Yu-Chen #define MS_MAX_PAGES_PER_BLOCK 32 16533842cedSCho, Yu-Chen #define MS_MAX_INITIAL_ERROR_BLOCKS 10 16633842cedSCho, Yu-Chen #define MS_LIB_BITS_PER_BYTE 8 16733842cedSCho, Yu-Chen 16833842cedSCho, Yu-Chen #define MS_SYSINF_FORMAT_FAT 1 16933842cedSCho, Yu-Chen #define MS_SYSINF_USAGE_GENERAL 0 17033842cedSCho, Yu-Chen 17133842cedSCho, Yu-Chen #define MS_SYSINF_MSCLASS_TYPE_1 1 17233842cedSCho, Yu-Chen #define MS_SYSINF_PAGE_SIZE MS_BYTES_PER_PAGE /* fixed */ 17333842cedSCho, Yu-Chen 17433842cedSCho, Yu-Chen #define MS_SYSINF_CARDTYPE_RDONLY 1 17533842cedSCho, Yu-Chen #define MS_SYSINF_CARDTYPE_RDWR 2 17633842cedSCho, Yu-Chen #define MS_SYSINF_CARDTYPE_HYBRID 3 17733842cedSCho, Yu-Chen #define MS_SYSINF_SECURITY 0x01 17833842cedSCho, Yu-Chen #define MS_SYSINF_SECURITY_NO_SUPPORT MS_SYSINF_SECURITY 17933842cedSCho, Yu-Chen #define MS_SYSINF_SECURITY_SUPPORT 0 18033842cedSCho, Yu-Chen 18133842cedSCho, Yu-Chen #define MS_SYSINF_RESERVED1 1 18233842cedSCho, Yu-Chen #define MS_SYSINF_RESERVED2 1 18333842cedSCho, Yu-Chen 18433842cedSCho, Yu-Chen #define MS_SYSENT_TYPE_INVALID_BLOCK 0x01 18533842cedSCho, Yu-Chen #define MS_SYSENT_TYPE_CIS_IDI 0x0a /* CIS/IDI */ 18633842cedSCho, Yu-Chen 18733842cedSCho, Yu-Chen #define SIZE_OF_KIRO 1024 18833842cedSCho, Yu-Chen #define BYTE_MASK 0xff 18933842cedSCho, Yu-Chen 19033842cedSCho, Yu-Chen /* ms error code */ 19133842cedSCho, Yu-Chen #define MS_STATUS_WRITE_PROTECT 0x0106 19233842cedSCho, Yu-Chen #define MS_STATUS_SUCCESS 0x0000 19333842cedSCho, Yu-Chen #define MS_ERROR_FLASH_READ 0x8003 19433842cedSCho, Yu-Chen #define MS_ERROR_FLASH_ERASE 0x8005 19533842cedSCho, Yu-Chen #define MS_LB_ERROR 0xfff0 19633842cedSCho, Yu-Chen #define MS_LB_BOOT_BLOCK 0xfff1 19733842cedSCho, Yu-Chen #define MS_LB_INITIAL_ERROR 0xfff2 19833842cedSCho, Yu-Chen #define MS_STATUS_SUCCESS_WITH_ECC 0xfff3 19933842cedSCho, Yu-Chen #define MS_LB_ACQUIRED_ERROR 0xfff4 20033842cedSCho, Yu-Chen #define MS_LB_NOT_USED_ERASED 0xfff5 20133842cedSCho, Yu-Chen #define MS_NOCARD_ERROR 0xfff8 20233842cedSCho, Yu-Chen #define MS_NO_MEMORY_ERROR 0xfff9 20333842cedSCho, Yu-Chen #define MS_STATUS_INT_ERROR 0xfffa 20433842cedSCho, Yu-Chen #define MS_STATUS_ERROR 0xfffe 20533842cedSCho, Yu-Chen #define MS_LB_NOT_USED 0xffff 20633842cedSCho, Yu-Chen 20733842cedSCho, Yu-Chen #define MS_REG_MNG_SYSFLG 0x04 /* system flag */ 20833842cedSCho, Yu-Chen #define MS_REG_MNG_SYSFLG_USER MS_REG_MNG_SYSFLG /* user block */ 20933842cedSCho, Yu-Chen 21033842cedSCho, Yu-Chen #define MS_BOOT_BLOCK_ID 0x0001 21133842cedSCho, Yu-Chen #define MS_BOOT_BLOCK_FORMAT_VERSION 0x0100 21233842cedSCho, Yu-Chen #define MS_BOOT_BLOCK_DATA_ENTRIES 2 21333842cedSCho, Yu-Chen 21433842cedSCho, Yu-Chen #define MS_NUMBER_OF_SYSTEM_ENTRY 4 21533842cedSCho, Yu-Chen #define MS_NUMBER_OF_BOOT_BLOCK 2 21633842cedSCho, Yu-Chen #define MS_BYTES_PER_PAGE 512 21733842cedSCho, Yu-Chen #define MS_LOGICAL_BLOCKS_PER_SEGMENT 496 21833842cedSCho, Yu-Chen #define MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT 494 21933842cedSCho, Yu-Chen 22033842cedSCho, Yu-Chen #define MS_PHYSICAL_BLOCKS_PER_SEGMENT 0x200 /* 512 */ 22133842cedSCho, Yu-Chen #define MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK 0x1ff 22233842cedSCho, Yu-Chen 22333842cedSCho, Yu-Chen /* overwrite area */ 22433842cedSCho, Yu-Chen #define MS_REG_OVR_BKST 0x80 /* block status */ 22533842cedSCho, Yu-Chen #define MS_REG_OVR_BKST_OK MS_REG_OVR_BKST /* OK */ 22633842cedSCho, Yu-Chen #define MS_REG_OVR_BKST_NG 0x00 /* NG */ 22733842cedSCho, Yu-Chen 22833842cedSCho, Yu-Chen /* Status Register 1 */ 22933842cedSCho, Yu-Chen #define MS_REG_ST1_DTER 0x20 /* error on data(corrected) */ 23033842cedSCho, Yu-Chen #define MS_REG_ST1_EXER 0x08 /* error on extra(corrected) */ 23133842cedSCho, Yu-Chen #define MS_REG_ST1_FGER 0x02 /* error on overwrite flag(corrected) */ 23233842cedSCho, Yu-Chen 23333842cedSCho, Yu-Chen /* MemoryStick Register */ 23433842cedSCho, Yu-Chen /* Status Register 0 */ 23533842cedSCho, Yu-Chen #define MS_REG_ST0_WP 0x01 /* write protected */ 23633842cedSCho, Yu-Chen #define MS_REG_ST0_WP_ON MS_REG_ST0_WP 23733842cedSCho, Yu-Chen 23833842cedSCho, Yu-Chen #define MS_LIB_CTRL_RDONLY 0 23933842cedSCho, Yu-Chen #define MS_LIB_CTRL_WRPROTECT 1 24033842cedSCho, Yu-Chen 24133842cedSCho, Yu-Chen /*dphy->log table */ 24233842cedSCho, Yu-Chen #define ms_libconv_to_logical(pdx, PhyBlock) (((PhyBlock) >= (pdx)->MS_Lib.NumberOfPhyBlock) ? MS_STATUS_ERROR : (pdx)->MS_Lib.Phy2LogMap[PhyBlock]) 24333842cedSCho, Yu-Chen #define ms_libconv_to_physical(pdx, LogBlock) (((LogBlock) >= (pdx)->MS_Lib.NumberOfLogBlock) ? MS_STATUS_ERROR : (pdx)->MS_Lib.Log2PhyMap[LogBlock]) 24433842cedSCho, Yu-Chen 24533842cedSCho, Yu-Chen #define ms_lib_ctrl_set(pdx, Flag) ((pdx)->MS_Lib.flags |= (1 << (Flag))) 24633842cedSCho, Yu-Chen #define ms_lib_ctrl_reset(pdx, Flag) ((pdx)->MS_Lib.flags &= ~(1 << (Flag))) 24733842cedSCho, Yu-Chen #define ms_lib_ctrl_check(pdx, Flag) ((pdx)->MS_Lib.flags & (1 << (Flag))) 24833842cedSCho, Yu-Chen 24933842cedSCho, Yu-Chen #define ms_lib_iswritable(pdx) ((ms_lib_ctrl_check((pdx), MS_LIB_CTRL_RDONLY) == 0) && (ms_lib_ctrl_check(pdx, MS_LIB_CTRL_WRPROTECT) == 0)) 25033842cedSCho, Yu-Chen #define ms_lib_clear_pagemap(pdx) memset((pdx)->MS_Lib.pagemap, 0, sizeof((pdx)->MS_Lib.pagemap)) 25133842cedSCho, Yu-Chen #define memstick_logaddr(logadr1, logadr0) ((((u16)(logadr1)) << 8) | (logadr0)) 25233842cedSCho, Yu-Chen 25341e568d1Shuajun li 25441e568d1Shuajun li struct SD_STATUS { 25541e568d1Shuajun li u8 Insert:1; 25641e568d1Shuajun li u8 Ready:1; 25741e568d1Shuajun li u8 MediaChange:1; 25841e568d1Shuajun li u8 IsMMC:1; 25941e568d1Shuajun li u8 HiCapacity:1; 26041e568d1Shuajun li u8 HiSpeed:1; 26141e568d1Shuajun li u8 WtP:1; 26241e568d1Shuajun li u8 Reserved:1; 26341e568d1Shuajun li }; 26441e568d1Shuajun li 26541e568d1Shuajun li struct MS_STATUS { 26641e568d1Shuajun li u8 Insert:1; 26741e568d1Shuajun li u8 Ready:1; 26841e568d1Shuajun li u8 MediaChange:1; 26941e568d1Shuajun li u8 IsMSPro:1; 27041e568d1Shuajun li u8 IsMSPHG:1; 27141e568d1Shuajun li u8 Reserved1:1; 27241e568d1Shuajun li u8 WtP:1; 27341e568d1Shuajun li u8 Reserved2:1; 27441e568d1Shuajun li }; 27541e568d1Shuajun li 27641e568d1Shuajun li struct SM_STATUS { 27741e568d1Shuajun li u8 Insert:1; 27841e568d1Shuajun li u8 Ready:1; 27941e568d1Shuajun li u8 MediaChange:1; 28041e568d1Shuajun li u8 Reserved:3; 28141e568d1Shuajun li u8 WtP:1; 28241e568d1Shuajun li u8 IsMS:1; 28341e568d1Shuajun li }; 28441e568d1Shuajun li 28533842cedSCho, Yu-Chen struct ms_bootblock_cis { 28633842cedSCho, Yu-Chen u8 bCistplDEVICE[6]; /* 0 */ 28733842cedSCho, Yu-Chen u8 bCistplDEVICE0C[6]; /* 6 */ 28833842cedSCho, Yu-Chen u8 bCistplJEDECC[4]; /* 12 */ 28933842cedSCho, Yu-Chen u8 bCistplMANFID[6]; /* 16 */ 29033842cedSCho, Yu-Chen u8 bCistplVER1[32]; /* 22 */ 29133842cedSCho, Yu-Chen u8 bCistplFUNCID[4]; /* 54 */ 29233842cedSCho, Yu-Chen u8 bCistplFUNCE0[4]; /* 58 */ 29333842cedSCho, Yu-Chen u8 bCistplFUNCE1[5]; /* 62 */ 29433842cedSCho, Yu-Chen u8 bCistplCONF[7]; /* 67 */ 29533842cedSCho, Yu-Chen u8 bCistplCFTBLENT0[10];/* 74 */ 29633842cedSCho, Yu-Chen u8 bCistplCFTBLENT1[8]; /* 84 */ 29733842cedSCho, Yu-Chen u8 bCistplCFTBLENT2[12];/* 92 */ 29833842cedSCho, Yu-Chen u8 bCistplCFTBLENT3[8]; /* 104 */ 29933842cedSCho, Yu-Chen u8 bCistplCFTBLENT4[17];/* 112 */ 30033842cedSCho, Yu-Chen u8 bCistplCFTBLENT5[8]; /* 129 */ 30133842cedSCho, Yu-Chen u8 bCistplCFTBLENT6[17];/* 137 */ 30233842cedSCho, Yu-Chen u8 bCistplCFTBLENT7[8]; /* 154 */ 30333842cedSCho, Yu-Chen u8 bCistplNOLINK[3]; /* 162 */ 30433842cedSCho, Yu-Chen } ; 30533842cedSCho, Yu-Chen 30633842cedSCho, Yu-Chen struct ms_bootblock_idi { 30733842cedSCho, Yu-Chen #define MS_IDI_GENERAL_CONF 0x848A 30833842cedSCho, Yu-Chen u16 wIDIgeneralConfiguration; /* 0 */ 30933842cedSCho, Yu-Chen u16 wIDInumberOfCylinder; /* 1 */ 31033842cedSCho, Yu-Chen u16 wIDIreserved0; /* 2 */ 31133842cedSCho, Yu-Chen u16 wIDInumberOfHead; /* 3 */ 31233842cedSCho, Yu-Chen u16 wIDIbytesPerTrack; /* 4 */ 31333842cedSCho, Yu-Chen u16 wIDIbytesPerSector; /* 5 */ 31433842cedSCho, Yu-Chen u16 wIDIsectorsPerTrack; /* 6 */ 31533842cedSCho, Yu-Chen u16 wIDItotalSectors[2]; /* 7-8 high,low */ 31633842cedSCho, Yu-Chen u16 wIDIreserved1[11]; /* 9-19 */ 31733842cedSCho, Yu-Chen u16 wIDIbufferType; /* 20 */ 31833842cedSCho, Yu-Chen u16 wIDIbufferSize; /* 21 */ 31933842cedSCho, Yu-Chen u16 wIDIlongCmdECC; /* 22 */ 32033842cedSCho, Yu-Chen u16 wIDIfirmVersion[4]; /* 23-26 */ 32133842cedSCho, Yu-Chen u16 wIDImodelName[20]; /* 27-46 */ 32233842cedSCho, Yu-Chen u16 wIDIreserved2; /* 47 */ 32333842cedSCho, Yu-Chen u16 wIDIlongWordSupported; /* 48 */ 32433842cedSCho, Yu-Chen u16 wIDIdmaSupported; /* 49 */ 32533842cedSCho, Yu-Chen u16 wIDIreserved3; /* 50 */ 32633842cedSCho, Yu-Chen u16 wIDIpioTiming; /* 51 */ 32733842cedSCho, Yu-Chen u16 wIDIdmaTiming; /* 52 */ 32833842cedSCho, Yu-Chen u16 wIDItransferParameter; /* 53 */ 32933842cedSCho, Yu-Chen u16 wIDIformattedCylinder; /* 54 */ 33033842cedSCho, Yu-Chen u16 wIDIformattedHead; /* 55 */ 33133842cedSCho, Yu-Chen u16 wIDIformattedSectorsPerTrack;/* 56 */ 33233842cedSCho, Yu-Chen u16 wIDIformattedTotalSectors[2];/* 57-58 */ 33333842cedSCho, Yu-Chen u16 wIDImultiSector; /* 59 */ 33433842cedSCho, Yu-Chen u16 wIDIlbaSectors[2]; /* 60-61 */ 33533842cedSCho, Yu-Chen u16 wIDIsingleWordDMA; /* 62 */ 33633842cedSCho, Yu-Chen u16 wIDImultiWordDMA; /* 63 */ 33733842cedSCho, Yu-Chen u16 wIDIreserved4[192]; /* 64-255 */ 33833842cedSCho, Yu-Chen }; 33933842cedSCho, Yu-Chen 34033842cedSCho, Yu-Chen struct ms_bootblock_sysent_rec { 34133842cedSCho, Yu-Chen u32 dwStart; 34233842cedSCho, Yu-Chen u32 dwSize; 34333842cedSCho, Yu-Chen u8 bType; 34433842cedSCho, Yu-Chen u8 bReserved[3]; 34533842cedSCho, Yu-Chen }; 34633842cedSCho, Yu-Chen 34733842cedSCho, Yu-Chen struct ms_bootblock_sysent { 34833842cedSCho, Yu-Chen struct ms_bootblock_sysent_rec entry[MS_NUMBER_OF_SYSTEM_ENTRY]; 34933842cedSCho, Yu-Chen }; 35033842cedSCho, Yu-Chen 35133842cedSCho, Yu-Chen struct ms_bootblock_sysinf { 35233842cedSCho, Yu-Chen u8 bMsClass; /* must be 1 */ 35333842cedSCho, Yu-Chen u8 bCardType; /* see below */ 35433842cedSCho, Yu-Chen u16 wBlockSize; /* n KB */ 35533842cedSCho, Yu-Chen u16 wBlockNumber; /* number of physical block */ 35633842cedSCho, Yu-Chen u16 wTotalBlockNumber; /* number of logical block */ 35733842cedSCho, Yu-Chen u16 wPageSize; /* must be 0x200 */ 35833842cedSCho, Yu-Chen u8 bExtraSize; /* 0x10 */ 35933842cedSCho, Yu-Chen u8 bSecuritySupport; 36033842cedSCho, Yu-Chen u8 bAssemblyDate[8]; 36133842cedSCho, Yu-Chen u8 bFactoryArea[4]; 36233842cedSCho, Yu-Chen u8 bAssemblyMakerCode; 36333842cedSCho, Yu-Chen u8 bAssemblyMachineCode[3]; 36433842cedSCho, Yu-Chen u16 wMemoryMakerCode; 36533842cedSCho, Yu-Chen u16 wMemoryDeviceCode; 36633842cedSCho, Yu-Chen u16 wMemorySize; 36733842cedSCho, Yu-Chen u8 bReserved1; 36833842cedSCho, Yu-Chen u8 bReserved2; 36933842cedSCho, Yu-Chen u8 bVCC; 37033842cedSCho, Yu-Chen u8 bVPP; 37133842cedSCho, Yu-Chen u16 wControllerChipNumber; 37233842cedSCho, Yu-Chen u16 wControllerFunction; /* New MS */ 37333842cedSCho, Yu-Chen u8 bReserved3[9]; /* New MS */ 37433842cedSCho, Yu-Chen u8 bParallelSupport; /* New MS */ 37533842cedSCho, Yu-Chen u16 wFormatValue; /* New MS */ 37633842cedSCho, Yu-Chen u8 bFormatType; 37733842cedSCho, Yu-Chen u8 bUsage; 37833842cedSCho, Yu-Chen u8 bDeviceType; 37933842cedSCho, Yu-Chen u8 bReserved4[22]; 38033842cedSCho, Yu-Chen u8 bFUValue3; 38133842cedSCho, Yu-Chen u8 bFUValue4; 38233842cedSCho, Yu-Chen u8 bReserved5[15]; 38333842cedSCho, Yu-Chen }; 38433842cedSCho, Yu-Chen 38533842cedSCho, Yu-Chen struct ms_bootblock_header { 38633842cedSCho, Yu-Chen u16 wBlockID; 38733842cedSCho, Yu-Chen u16 wFormatVersion; 38833842cedSCho, Yu-Chen u8 bReserved1[184]; 38933842cedSCho, Yu-Chen u8 bNumberOfDataEntry; 39033842cedSCho, Yu-Chen u8 bReserved2[179]; 39133842cedSCho, Yu-Chen }; 39233842cedSCho, Yu-Chen 39333842cedSCho, Yu-Chen struct ms_bootblock_page0 { 39433842cedSCho, Yu-Chen struct ms_bootblock_header header; 39533842cedSCho, Yu-Chen struct ms_bootblock_sysent sysent; 39633842cedSCho, Yu-Chen struct ms_bootblock_sysinf sysinf; 39733842cedSCho, Yu-Chen }; 39833842cedSCho, Yu-Chen 39933842cedSCho, Yu-Chen struct ms_bootblock_cis_idi { 40033842cedSCho, Yu-Chen union { 40133842cedSCho, Yu-Chen struct ms_bootblock_cis cis; 40233842cedSCho, Yu-Chen u8 dmy[256]; 40333842cedSCho, Yu-Chen } cis; 40433842cedSCho, Yu-Chen 40533842cedSCho, Yu-Chen union { 40633842cedSCho, Yu-Chen struct ms_bootblock_idi idi; 40733842cedSCho, Yu-Chen u8 dmy[256]; 40833842cedSCho, Yu-Chen } idi; 40933842cedSCho, Yu-Chen 41033842cedSCho, Yu-Chen }; 41133842cedSCho, Yu-Chen 41233842cedSCho, Yu-Chen /* ENE MS Lib struct */ 41333842cedSCho, Yu-Chen struct ms_lib_type_extdat { 41433842cedSCho, Yu-Chen u8 reserved; 41533842cedSCho, Yu-Chen u8 intr; 41633842cedSCho, Yu-Chen u8 status0; 41733842cedSCho, Yu-Chen u8 status1; 41833842cedSCho, Yu-Chen u8 ovrflg; 41933842cedSCho, Yu-Chen u8 mngflg; 42033842cedSCho, Yu-Chen u16 logadr; 42133842cedSCho, Yu-Chen }; 42233842cedSCho, Yu-Chen 42333842cedSCho, Yu-Chen struct ms_lib_ctrl { 42433842cedSCho, Yu-Chen u32 flags; 42533842cedSCho, Yu-Chen u32 BytesPerSector; 42633842cedSCho, Yu-Chen u32 NumberOfCylinder; 42733842cedSCho, Yu-Chen u32 SectorsPerCylinder; 42833842cedSCho, Yu-Chen u16 cardType; /* R/W, RO, Hybrid */ 42933842cedSCho, Yu-Chen u16 blockSize; 43033842cedSCho, Yu-Chen u16 PagesPerBlock; 43133842cedSCho, Yu-Chen u16 NumberOfPhyBlock; 43233842cedSCho, Yu-Chen u16 NumberOfLogBlock; 43333842cedSCho, Yu-Chen u16 NumberOfSegment; 43433842cedSCho, Yu-Chen u16 *Phy2LogMap; /* phy2log table */ 43533842cedSCho, Yu-Chen u16 *Log2PhyMap; /* log2phy table */ 43633842cedSCho, Yu-Chen u16 wrtblk; 43733842cedSCho, Yu-Chen unsigned char *pagemap[(MS_MAX_PAGES_PER_BLOCK + (MS_LIB_BITS_PER_BYTE-1)) / MS_LIB_BITS_PER_BYTE]; 43833842cedSCho, Yu-Chen unsigned char *blkpag; 43933842cedSCho, Yu-Chen struct ms_lib_type_extdat *blkext; 44033842cedSCho, Yu-Chen unsigned char copybuf[512]; 44133842cedSCho, Yu-Chen }; 44233842cedSCho, Yu-Chen 44341e568d1Shuajun li 44441e568d1Shuajun li /* SD Block Length */ 44541e568d1Shuajun li /* 2^9 = 512 Bytes, The HW maximum read/write data length */ 44641e568d1Shuajun li #define SD_BLOCK_LEN 9 44741e568d1Shuajun li 44841e568d1Shuajun li struct ene_ub6250_info { 44941e568d1Shuajun li /* for 6250 code */ 45041e568d1Shuajun li struct SD_STATUS SD_Status; 45141e568d1Shuajun li struct MS_STATUS MS_Status; 45241e568d1Shuajun li struct SM_STATUS SM_Status; 45341e568d1Shuajun li 45441e568d1Shuajun li /* ----- SD Control Data ---------------- */ 45541e568d1Shuajun li /*SD_REGISTER SD_Regs; */ 45641e568d1Shuajun li u16 SD_Block_Mult; 45741e568d1Shuajun li u8 SD_READ_BL_LEN; 45841e568d1Shuajun li u16 SD_C_SIZE; 45941e568d1Shuajun li u8 SD_C_SIZE_MULT; 46041e568d1Shuajun li 46141e568d1Shuajun li /* SD/MMC New spec. */ 46241e568d1Shuajun li u8 SD_SPEC_VER; 46341e568d1Shuajun li u8 SD_CSD_VER; 46441e568d1Shuajun li u8 SD20_HIGH_CAPACITY; 46541e568d1Shuajun li u32 HC_C_SIZE; 46641e568d1Shuajun li u8 MMC_SPEC_VER; 46741e568d1Shuajun li u8 MMC_BusWidth; 46841e568d1Shuajun li u8 MMC_HIGH_CAPACITY; 46941e568d1Shuajun li 47041e568d1Shuajun li /*----- MS Control Data ---------------- */ 47141e568d1Shuajun li bool MS_SWWP; 47241e568d1Shuajun li u32 MSP_TotalBlock; 47333842cedSCho, Yu-Chen struct ms_lib_ctrl MS_Lib; 47441e568d1Shuajun li bool MS_IsRWPage; 47541e568d1Shuajun li u16 MS_Model; 47641e568d1Shuajun li 47741e568d1Shuajun li /*----- SM Control Data ---------------- */ 47841e568d1Shuajun li u8 SM_DeviceID; 47941e568d1Shuajun li u8 SM_CardID; 48041e568d1Shuajun li 48141e568d1Shuajun li unsigned char *testbuf; 48241e568d1Shuajun li u8 BIN_FLAG; 48341e568d1Shuajun li u32 bl_num; 48441e568d1Shuajun li int SrbStatus; 48541e568d1Shuajun li 48641e568d1Shuajun li /*------Power Managerment ---------------*/ 48741e568d1Shuajun li bool Power_IsResum; 48841e568d1Shuajun li }; 48941e568d1Shuajun li 49041e568d1Shuajun li static int ene_sd_init(struct us_data *us); 49133842cedSCho, Yu-Chen static int ene_ms_init(struct us_data *us); 49241e568d1Shuajun li static int ene_load_bincode(struct us_data *us, unsigned char flag); 49341e568d1Shuajun li 49441e568d1Shuajun li static void ene_ub6250_info_destructor(void *extra) 49541e568d1Shuajun li { 49641e568d1Shuajun li if (!extra) 49741e568d1Shuajun li return; 49841e568d1Shuajun li } 49941e568d1Shuajun li 50041e568d1Shuajun li static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg) 50141e568d1Shuajun li { 50241e568d1Shuajun li struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 50341e568d1Shuajun li struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; 50441e568d1Shuajun li 50541e568d1Shuajun li int result; 50641e568d1Shuajun li unsigned int residue; 50741e568d1Shuajun li unsigned int cswlen = 0, partial = 0; 50841e568d1Shuajun li unsigned int transfer_length = bcb->DataTransferLength; 50941e568d1Shuajun li 510191648d0SJoe Perches /* usb_stor_dbg(us, "transport --- ene_send_scsi_cmd\n"); */ 51141e568d1Shuajun li /* send cmd to out endpoint */ 51241e568d1Shuajun li result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, 51341e568d1Shuajun li bcb, US_BULK_CB_WRAP_LEN, NULL); 51441e568d1Shuajun li if (result != USB_STOR_XFER_GOOD) { 515191648d0SJoe Perches usb_stor_dbg(us, "send cmd to out endpoint fail ---\n"); 51641e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 51741e568d1Shuajun li } 51841e568d1Shuajun li 51941e568d1Shuajun li if (buf) { 52041e568d1Shuajun li unsigned int pipe = fDir; 52141e568d1Shuajun li 52241e568d1Shuajun li if (fDir == FDIR_READ) 52341e568d1Shuajun li pipe = us->recv_bulk_pipe; 52441e568d1Shuajun li else 52541e568d1Shuajun li pipe = us->send_bulk_pipe; 52641e568d1Shuajun li 52741e568d1Shuajun li /* Bulk */ 52841e568d1Shuajun li if (use_sg) { 52941e568d1Shuajun li result = usb_stor_bulk_srb(us, pipe, us->srb); 53041e568d1Shuajun li } else { 53141e568d1Shuajun li result = usb_stor_bulk_transfer_sg(us, pipe, buf, 53241e568d1Shuajun li transfer_length, 0, &partial); 53341e568d1Shuajun li } 53441e568d1Shuajun li if (result != USB_STOR_XFER_GOOD) { 535191648d0SJoe Perches usb_stor_dbg(us, "data transfer fail ---\n"); 53641e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 53741e568d1Shuajun li } 53841e568d1Shuajun li } 53941e568d1Shuajun li 54041e568d1Shuajun li /* Get CSW for device status */ 54141e568d1Shuajun li result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, 54241e568d1Shuajun li US_BULK_CS_WRAP_LEN, &cswlen); 54341e568d1Shuajun li 54441e568d1Shuajun li if (result == USB_STOR_XFER_SHORT && cswlen == 0) { 545191648d0SJoe Perches usb_stor_dbg(us, "Received 0-length CSW; retrying...\n"); 54641e568d1Shuajun li result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, 54741e568d1Shuajun li bcs, US_BULK_CS_WRAP_LEN, &cswlen); 54841e568d1Shuajun li } 54941e568d1Shuajun li 55041e568d1Shuajun li if (result == USB_STOR_XFER_STALLED) { 55141e568d1Shuajun li /* get the status again */ 552191648d0SJoe Perches usb_stor_dbg(us, "Attempting to get CSW (2nd try)...\n"); 55341e568d1Shuajun li result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, 55441e568d1Shuajun li bcs, US_BULK_CS_WRAP_LEN, NULL); 55541e568d1Shuajun li } 55641e568d1Shuajun li 55741e568d1Shuajun li if (result != USB_STOR_XFER_GOOD) 55841e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 55941e568d1Shuajun li 56041e568d1Shuajun li /* check bulk status */ 56141e568d1Shuajun li residue = le32_to_cpu(bcs->Residue); 56241e568d1Shuajun li 563f0183a33SFelipe Balbi /* 564f0183a33SFelipe Balbi * try to compute the actual residue, based on how much data 565f0183a33SFelipe Balbi * was really transferred and what the device tells us 566f0183a33SFelipe Balbi */ 56741e568d1Shuajun li if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) { 56841e568d1Shuajun li residue = min(residue, transfer_length); 56941e568d1Shuajun li if (us->srb != NULL) 57041e568d1Shuajun li scsi_set_resid(us->srb, max(scsi_get_resid(us->srb), 57141e568d1Shuajun li (int)residue)); 57241e568d1Shuajun li } 57341e568d1Shuajun li 57441e568d1Shuajun li if (bcs->Status != US_BULK_STAT_OK) 57541e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 57641e568d1Shuajun li 57741e568d1Shuajun li return USB_STOR_TRANSPORT_GOOD; 57841e568d1Shuajun li } 57941e568d1Shuajun li 58041e568d1Shuajun li static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb) 58141e568d1Shuajun li { 58241e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 58341e568d1Shuajun li 58441e568d1Shuajun li if (info->SD_Status.Insert && info->SD_Status.Ready) 58541e568d1Shuajun li return USB_STOR_TRANSPORT_GOOD; 58641e568d1Shuajun li else { 58741e568d1Shuajun li ene_sd_init(us); 58841e568d1Shuajun li return USB_STOR_TRANSPORT_GOOD; 58941e568d1Shuajun li } 59041e568d1Shuajun li 59141e568d1Shuajun li return USB_STOR_TRANSPORT_GOOD; 59241e568d1Shuajun li } 59341e568d1Shuajun li 59441e568d1Shuajun li static int sd_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb) 59541e568d1Shuajun li { 59641e568d1Shuajun li unsigned char data_ptr[36] = { 59741e568d1Shuajun li 0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 59841e568d1Shuajun li 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, 59941e568d1Shuajun li 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 60041e568d1Shuajun li 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30 }; 60141e568d1Shuajun li 60241e568d1Shuajun li usb_stor_set_xfer_buf(data_ptr, 36, srb); 60341e568d1Shuajun li return USB_STOR_TRANSPORT_GOOD; 60441e568d1Shuajun li } 60541e568d1Shuajun li 60641e568d1Shuajun li static int sd_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb) 60741e568d1Shuajun li { 60841e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 60941e568d1Shuajun li unsigned char mediaNoWP[12] = { 61041e568d1Shuajun li 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 61141e568d1Shuajun li 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 }; 61241e568d1Shuajun li unsigned char mediaWP[12] = { 61341e568d1Shuajun li 0x0b, 0x00, 0x80, 0x08, 0x00, 0x00, 61441e568d1Shuajun li 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 }; 61541e568d1Shuajun li 61641e568d1Shuajun li if (info->SD_Status.WtP) 61741e568d1Shuajun li usb_stor_set_xfer_buf(mediaWP, 12, srb); 61841e568d1Shuajun li else 61941e568d1Shuajun li usb_stor_set_xfer_buf(mediaNoWP, 12, srb); 62041e568d1Shuajun li 62141e568d1Shuajun li 62241e568d1Shuajun li return USB_STOR_TRANSPORT_GOOD; 62341e568d1Shuajun li } 62441e568d1Shuajun li 62541e568d1Shuajun li static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb) 62641e568d1Shuajun li { 62741e568d1Shuajun li u32 bl_num; 62836f3a14dSFelipe Balbi u32 bl_len; 62941e568d1Shuajun li unsigned int offset = 0; 63041e568d1Shuajun li unsigned char buf[8]; 63141e568d1Shuajun li struct scatterlist *sg = NULL; 63241e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 63341e568d1Shuajun li 634191648d0SJoe Perches usb_stor_dbg(us, "sd_scsi_read_capacity\n"); 63541e568d1Shuajun li if (info->SD_Status.HiCapacity) { 63641e568d1Shuajun li bl_len = 0x200; 63741e568d1Shuajun li if (info->SD_Status.IsMMC) 63841e568d1Shuajun li bl_num = info->HC_C_SIZE-1; 63941e568d1Shuajun li else 64041e568d1Shuajun li bl_num = (info->HC_C_SIZE + 1) * 1024 - 1; 64141e568d1Shuajun li } else { 64241e568d1Shuajun li bl_len = 1 << (info->SD_READ_BL_LEN); 64341e568d1Shuajun li bl_num = info->SD_Block_Mult * (info->SD_C_SIZE + 1) 64441e568d1Shuajun li * (1 << (info->SD_C_SIZE_MULT + 2)) - 1; 64541e568d1Shuajun li } 64641e568d1Shuajun li info->bl_num = bl_num; 647191648d0SJoe Perches usb_stor_dbg(us, "bl_len = %x\n", bl_len); 648191648d0SJoe Perches usb_stor_dbg(us, "bl_num = %x\n", bl_num); 64941e568d1Shuajun li 65041e568d1Shuajun li /*srb->request_bufflen = 8; */ 65141e568d1Shuajun li buf[0] = (bl_num >> 24) & 0xff; 65241e568d1Shuajun li buf[1] = (bl_num >> 16) & 0xff; 65341e568d1Shuajun li buf[2] = (bl_num >> 8) & 0xff; 65441e568d1Shuajun li buf[3] = (bl_num >> 0) & 0xff; 65541e568d1Shuajun li buf[4] = (bl_len >> 24) & 0xff; 65641e568d1Shuajun li buf[5] = (bl_len >> 16) & 0xff; 65741e568d1Shuajun li buf[6] = (bl_len >> 8) & 0xff; 65841e568d1Shuajun li buf[7] = (bl_len >> 0) & 0xff; 65941e568d1Shuajun li 66041e568d1Shuajun li usb_stor_access_xfer_buf(buf, 8, srb, &sg, &offset, TO_XFER_BUF); 66141e568d1Shuajun li 66241e568d1Shuajun li return USB_STOR_TRANSPORT_GOOD; 66341e568d1Shuajun li } 66441e568d1Shuajun li 66541e568d1Shuajun li static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb) 66641e568d1Shuajun li { 66741e568d1Shuajun li int result; 66841e568d1Shuajun li unsigned char *cdb = srb->cmnd; 66941e568d1Shuajun li struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 67041e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 67141e568d1Shuajun li 67241e568d1Shuajun li u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) | 67341e568d1Shuajun li ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff); 67441e568d1Shuajun li u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff); 67541e568d1Shuajun li u32 bnByte = bn * 0x200; 67641e568d1Shuajun li u32 blenByte = blen * 0x200; 67741e568d1Shuajun li 67841e568d1Shuajun li if (bn > info->bl_num) 67941e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 68041e568d1Shuajun li 68141e568d1Shuajun li result = ene_load_bincode(us, SD_RW_PATTERN); 68241e568d1Shuajun li if (result != USB_STOR_XFER_GOOD) { 683191648d0SJoe Perches usb_stor_dbg(us, "Load SD RW pattern Fail !!\n"); 68441e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 68541e568d1Shuajun li } 68641e568d1Shuajun li 68741e568d1Shuajun li if (info->SD_Status.HiCapacity) 68841e568d1Shuajun li bnByte = bn; 68941e568d1Shuajun li 69041e568d1Shuajun li /* set up the command wrapper */ 69141e568d1Shuajun li memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 69241e568d1Shuajun li bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 69341e568d1Shuajun li bcb->DataTransferLength = blenByte; 694b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 69541e568d1Shuajun li bcb->CDB[0] = 0xF1; 69641e568d1Shuajun li bcb->CDB[5] = (unsigned char)(bnByte); 69741e568d1Shuajun li bcb->CDB[4] = (unsigned char)(bnByte>>8); 69841e568d1Shuajun li bcb->CDB[3] = (unsigned char)(bnByte>>16); 69941e568d1Shuajun li bcb->CDB[2] = (unsigned char)(bnByte>>24); 70041e568d1Shuajun li 70141e568d1Shuajun li result = ene_send_scsi_cmd(us, FDIR_READ, scsi_sglist(srb), 1); 70241e568d1Shuajun li return result; 70341e568d1Shuajun li } 70441e568d1Shuajun li 70541e568d1Shuajun li static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb) 70641e568d1Shuajun li { 70741e568d1Shuajun li int result; 70841e568d1Shuajun li unsigned char *cdb = srb->cmnd; 70941e568d1Shuajun li struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 71041e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 71141e568d1Shuajun li 71241e568d1Shuajun li u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) | 71341e568d1Shuajun li ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff); 71441e568d1Shuajun li u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff); 71541e568d1Shuajun li u32 bnByte = bn * 0x200; 71641e568d1Shuajun li u32 blenByte = blen * 0x200; 71741e568d1Shuajun li 71841e568d1Shuajun li if (bn > info->bl_num) 71941e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 72041e568d1Shuajun li 72141e568d1Shuajun li result = ene_load_bincode(us, SD_RW_PATTERN); 72241e568d1Shuajun li if (result != USB_STOR_XFER_GOOD) { 723191648d0SJoe Perches usb_stor_dbg(us, "Load SD RW pattern Fail !!\n"); 72441e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 72541e568d1Shuajun li } 72641e568d1Shuajun li 72741e568d1Shuajun li if (info->SD_Status.HiCapacity) 72841e568d1Shuajun li bnByte = bn; 72941e568d1Shuajun li 73041e568d1Shuajun li /* set up the command wrapper */ 73141e568d1Shuajun li memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 73241e568d1Shuajun li bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 73341e568d1Shuajun li bcb->DataTransferLength = blenByte; 73441e568d1Shuajun li bcb->Flags = 0x00; 73541e568d1Shuajun li bcb->CDB[0] = 0xF0; 73641e568d1Shuajun li bcb->CDB[5] = (unsigned char)(bnByte); 73741e568d1Shuajun li bcb->CDB[4] = (unsigned char)(bnByte>>8); 73841e568d1Shuajun li bcb->CDB[3] = (unsigned char)(bnByte>>16); 73941e568d1Shuajun li bcb->CDB[2] = (unsigned char)(bnByte>>24); 74041e568d1Shuajun li 74141e568d1Shuajun li result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1); 74241e568d1Shuajun li return result; 74341e568d1Shuajun li } 74441e568d1Shuajun li 74533842cedSCho, Yu-Chen /* 74633842cedSCho, Yu-Chen * ENE MS Card 74733842cedSCho, Yu-Chen */ 74833842cedSCho, Yu-Chen 74933842cedSCho, Yu-Chen static int ms_lib_set_logicalpair(struct us_data *us, u16 logblk, u16 phyblk) 75033842cedSCho, Yu-Chen { 75133842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 75233842cedSCho, Yu-Chen 75333842cedSCho, Yu-Chen if ((logblk >= info->MS_Lib.NumberOfLogBlock) || (phyblk >= info->MS_Lib.NumberOfPhyBlock)) 75433842cedSCho, Yu-Chen return (u32)-1; 75533842cedSCho, Yu-Chen 75633842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap[phyblk] = logblk; 75733842cedSCho, Yu-Chen info->MS_Lib.Log2PhyMap[logblk] = phyblk; 75833842cedSCho, Yu-Chen 75933842cedSCho, Yu-Chen return 0; 76033842cedSCho, Yu-Chen } 76133842cedSCho, Yu-Chen 76233842cedSCho, Yu-Chen static int ms_lib_set_logicalblockmark(struct us_data *us, u16 phyblk, u16 mark) 76333842cedSCho, Yu-Chen { 76433842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 76533842cedSCho, Yu-Chen 76633842cedSCho, Yu-Chen if (phyblk >= info->MS_Lib.NumberOfPhyBlock) 76733842cedSCho, Yu-Chen return (u32)-1; 76833842cedSCho, Yu-Chen 76933842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap[phyblk] = mark; 77033842cedSCho, Yu-Chen 77133842cedSCho, Yu-Chen return 0; 77233842cedSCho, Yu-Chen } 77333842cedSCho, Yu-Chen 77433842cedSCho, Yu-Chen static int ms_lib_set_initialerrorblock(struct us_data *us, u16 phyblk) 77533842cedSCho, Yu-Chen { 77633842cedSCho, Yu-Chen return ms_lib_set_logicalblockmark(us, phyblk, MS_LB_INITIAL_ERROR); 77733842cedSCho, Yu-Chen } 77833842cedSCho, Yu-Chen 77933842cedSCho, Yu-Chen static int ms_lib_set_bootblockmark(struct us_data *us, u16 phyblk) 78033842cedSCho, Yu-Chen { 78133842cedSCho, Yu-Chen return ms_lib_set_logicalblockmark(us, phyblk, MS_LB_BOOT_BLOCK); 78233842cedSCho, Yu-Chen } 78333842cedSCho, Yu-Chen 78433842cedSCho, Yu-Chen static int ms_lib_free_logicalmap(struct us_data *us) 78533842cedSCho, Yu-Chen { 78633842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 78733842cedSCho, Yu-Chen 78833842cedSCho, Yu-Chen kfree(info->MS_Lib.Phy2LogMap); 78933842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap = NULL; 79033842cedSCho, Yu-Chen 79133842cedSCho, Yu-Chen kfree(info->MS_Lib.Log2PhyMap); 79233842cedSCho, Yu-Chen info->MS_Lib.Log2PhyMap = NULL; 79333842cedSCho, Yu-Chen 79433842cedSCho, Yu-Chen return 0; 79533842cedSCho, Yu-Chen } 79633842cedSCho, Yu-Chen 79736f3a14dSFelipe Balbi static int ms_lib_alloc_logicalmap(struct us_data *us) 79833842cedSCho, Yu-Chen { 79933842cedSCho, Yu-Chen u32 i; 80033842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 80133842cedSCho, Yu-Chen 80233842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap = kmalloc(info->MS_Lib.NumberOfPhyBlock * sizeof(u16), GFP_KERNEL); 80333842cedSCho, Yu-Chen info->MS_Lib.Log2PhyMap = kmalloc(info->MS_Lib.NumberOfLogBlock * sizeof(u16), GFP_KERNEL); 80433842cedSCho, Yu-Chen 80533842cedSCho, Yu-Chen if ((info->MS_Lib.Phy2LogMap == NULL) || (info->MS_Lib.Log2PhyMap == NULL)) { 80633842cedSCho, Yu-Chen ms_lib_free_logicalmap(us); 80733842cedSCho, Yu-Chen return (u32)-1; 80833842cedSCho, Yu-Chen } 80933842cedSCho, Yu-Chen 81033842cedSCho, Yu-Chen for (i = 0; i < info->MS_Lib.NumberOfPhyBlock; i++) 81133842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap[i] = MS_LB_NOT_USED; 81233842cedSCho, Yu-Chen 81333842cedSCho, Yu-Chen for (i = 0; i < info->MS_Lib.NumberOfLogBlock; i++) 81433842cedSCho, Yu-Chen info->MS_Lib.Log2PhyMap[i] = MS_LB_NOT_USED; 81533842cedSCho, Yu-Chen 81633842cedSCho, Yu-Chen return 0; 81733842cedSCho, Yu-Chen } 81833842cedSCho, Yu-Chen 81933842cedSCho, Yu-Chen static void ms_lib_clear_writebuf(struct us_data *us) 82033842cedSCho, Yu-Chen { 82133842cedSCho, Yu-Chen int i; 82233842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 82333842cedSCho, Yu-Chen 82433842cedSCho, Yu-Chen info->MS_Lib.wrtblk = (u16)-1; 82533842cedSCho, Yu-Chen ms_lib_clear_pagemap(info); 82633842cedSCho, Yu-Chen 82733842cedSCho, Yu-Chen if (info->MS_Lib.blkpag) 82833842cedSCho, Yu-Chen memset(info->MS_Lib.blkpag, 0xff, info->MS_Lib.PagesPerBlock * info->MS_Lib.BytesPerSector); 82933842cedSCho, Yu-Chen 83033842cedSCho, Yu-Chen if (info->MS_Lib.blkext) { 83133842cedSCho, Yu-Chen for (i = 0; i < info->MS_Lib.PagesPerBlock; i++) { 83233842cedSCho, Yu-Chen info->MS_Lib.blkext[i].status1 = MS_REG_ST1_DEFAULT; 83333842cedSCho, Yu-Chen info->MS_Lib.blkext[i].ovrflg = MS_REG_OVR_DEFAULT; 83433842cedSCho, Yu-Chen info->MS_Lib.blkext[i].mngflg = MS_REG_MNG_DEFAULT; 83533842cedSCho, Yu-Chen info->MS_Lib.blkext[i].logadr = MS_LB_NOT_USED; 83633842cedSCho, Yu-Chen } 83733842cedSCho, Yu-Chen } 83833842cedSCho, Yu-Chen } 83933842cedSCho, Yu-Chen 84033842cedSCho, Yu-Chen static int ms_count_freeblock(struct us_data *us, u16 PhyBlock) 84133842cedSCho, Yu-Chen { 84233842cedSCho, Yu-Chen u32 Ende, Count; 84333842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 84433842cedSCho, Yu-Chen 84533842cedSCho, Yu-Chen Ende = PhyBlock + MS_PHYSICAL_BLOCKS_PER_SEGMENT; 84633842cedSCho, Yu-Chen for (Count = 0; PhyBlock < Ende; PhyBlock++) { 84733842cedSCho, Yu-Chen switch (info->MS_Lib.Phy2LogMap[PhyBlock]) { 84833842cedSCho, Yu-Chen case MS_LB_NOT_USED: 84933842cedSCho, Yu-Chen case MS_LB_NOT_USED_ERASED: 85033842cedSCho, Yu-Chen Count++; 85133842cedSCho, Yu-Chen default: 85233842cedSCho, Yu-Chen break; 85333842cedSCho, Yu-Chen } 85433842cedSCho, Yu-Chen } 85533842cedSCho, Yu-Chen 85633842cedSCho, Yu-Chen return Count; 85733842cedSCho, Yu-Chen } 85833842cedSCho, Yu-Chen 85933842cedSCho, Yu-Chen static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, 86033842cedSCho, Yu-Chen u8 PageNum, u32 *PageBuf, struct ms_lib_type_extdat *ExtraDat) 86133842cedSCho, Yu-Chen { 86233842cedSCho, Yu-Chen struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 86333842cedSCho, Yu-Chen int result; 86433842cedSCho, Yu-Chen u8 ExtBuf[4]; 86533842cedSCho, Yu-Chen u32 bn = PhyBlockAddr * 0x20 + PageNum; 86633842cedSCho, Yu-Chen 86733842cedSCho, Yu-Chen result = ene_load_bincode(us, MS_RW_PATTERN); 86833842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) 86933842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 87033842cedSCho, Yu-Chen 87133842cedSCho, Yu-Chen /* Read Page Data */ 87233842cedSCho, Yu-Chen memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 87333842cedSCho, Yu-Chen bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 87433842cedSCho, Yu-Chen bcb->DataTransferLength = 0x200; 875b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 87633842cedSCho, Yu-Chen bcb->CDB[0] = 0xF1; 87733842cedSCho, Yu-Chen 87833842cedSCho, Yu-Chen bcb->CDB[1] = 0x02; /* in init.c ENE_MSInit() is 0x01 */ 87933842cedSCho, Yu-Chen 88033842cedSCho, Yu-Chen bcb->CDB[5] = (unsigned char)(bn); 88133842cedSCho, Yu-Chen bcb->CDB[4] = (unsigned char)(bn>>8); 88233842cedSCho, Yu-Chen bcb->CDB[3] = (unsigned char)(bn>>16); 88333842cedSCho, Yu-Chen bcb->CDB[2] = (unsigned char)(bn>>24); 88433842cedSCho, Yu-Chen 88533842cedSCho, Yu-Chen result = ene_send_scsi_cmd(us, FDIR_READ, PageBuf, 0); 88633842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) 88733842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 88833842cedSCho, Yu-Chen 88933842cedSCho, Yu-Chen 89033842cedSCho, Yu-Chen /* Read Extra Data */ 89133842cedSCho, Yu-Chen memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 89233842cedSCho, Yu-Chen bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 89333842cedSCho, Yu-Chen bcb->DataTransferLength = 0x4; 894b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 89533842cedSCho, Yu-Chen bcb->CDB[0] = 0xF1; 89633842cedSCho, Yu-Chen bcb->CDB[1] = 0x03; 89733842cedSCho, Yu-Chen 89833842cedSCho, Yu-Chen bcb->CDB[5] = (unsigned char)(PageNum); 89933842cedSCho, Yu-Chen bcb->CDB[4] = (unsigned char)(PhyBlockAddr); 90033842cedSCho, Yu-Chen bcb->CDB[3] = (unsigned char)(PhyBlockAddr>>8); 90133842cedSCho, Yu-Chen bcb->CDB[2] = (unsigned char)(PhyBlockAddr>>16); 90233842cedSCho, Yu-Chen bcb->CDB[6] = 0x01; 90333842cedSCho, Yu-Chen 90433842cedSCho, Yu-Chen result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0); 90533842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) 90633842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 90733842cedSCho, Yu-Chen 90833842cedSCho, Yu-Chen ExtraDat->reserved = 0; 90933842cedSCho, Yu-Chen ExtraDat->intr = 0x80; /* Not yet,fireware support */ 91033842cedSCho, Yu-Chen ExtraDat->status0 = 0x10; /* Not yet,fireware support */ 91133842cedSCho, Yu-Chen 91233842cedSCho, Yu-Chen ExtraDat->status1 = 0x00; /* Not yet,fireware support */ 91333842cedSCho, Yu-Chen ExtraDat->ovrflg = ExtBuf[0]; 91433842cedSCho, Yu-Chen ExtraDat->mngflg = ExtBuf[1]; 91533842cedSCho, Yu-Chen ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]); 91633842cedSCho, Yu-Chen 91733842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 91833842cedSCho, Yu-Chen } 91933842cedSCho, Yu-Chen 92033842cedSCho, Yu-Chen static int ms_lib_process_bootblock(struct us_data *us, u16 PhyBlock, u8 *PageData) 92133842cedSCho, Yu-Chen { 92233842cedSCho, Yu-Chen struct ms_bootblock_sysent *SysEntry; 92333842cedSCho, Yu-Chen struct ms_bootblock_sysinf *SysInfo; 92433842cedSCho, Yu-Chen u32 i, result; 92533842cedSCho, Yu-Chen u8 PageNumber; 92633842cedSCho, Yu-Chen u8 *PageBuffer; 92733842cedSCho, Yu-Chen struct ms_lib_type_extdat ExtraData; 92833842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 92933842cedSCho, Yu-Chen 93033842cedSCho, Yu-Chen PageBuffer = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL); 93133842cedSCho, Yu-Chen if (PageBuffer == NULL) 93233842cedSCho, Yu-Chen return (u32)-1; 93333842cedSCho, Yu-Chen 93433842cedSCho, Yu-Chen result = (u32)-1; 93533842cedSCho, Yu-Chen 93633842cedSCho, Yu-Chen SysInfo = &(((struct ms_bootblock_page0 *)PageData)->sysinf); 93733842cedSCho, Yu-Chen 93833842cedSCho, Yu-Chen if ((SysInfo->bMsClass != MS_SYSINF_MSCLASS_TYPE_1) || 93933842cedSCho, Yu-Chen (be16_to_cpu(SysInfo->wPageSize) != MS_SYSINF_PAGE_SIZE) || 94033842cedSCho, Yu-Chen ((SysInfo->bSecuritySupport & MS_SYSINF_SECURITY) == MS_SYSINF_SECURITY_SUPPORT) || 94133842cedSCho, Yu-Chen (SysInfo->bReserved1 != MS_SYSINF_RESERVED1) || 94233842cedSCho, Yu-Chen (SysInfo->bReserved2 != MS_SYSINF_RESERVED2) || 94333842cedSCho, Yu-Chen (SysInfo->bFormatType != MS_SYSINF_FORMAT_FAT) || 94433842cedSCho, Yu-Chen (SysInfo->bUsage != MS_SYSINF_USAGE_GENERAL)) 94533842cedSCho, Yu-Chen goto exit; 94633842cedSCho, Yu-Chen /* */ 94733842cedSCho, Yu-Chen switch (info->MS_Lib.cardType = SysInfo->bCardType) { 94833842cedSCho, Yu-Chen case MS_SYSINF_CARDTYPE_RDONLY: 94933842cedSCho, Yu-Chen ms_lib_ctrl_set(info, MS_LIB_CTRL_RDONLY); 95033842cedSCho, Yu-Chen break; 95133842cedSCho, Yu-Chen case MS_SYSINF_CARDTYPE_RDWR: 95233842cedSCho, Yu-Chen ms_lib_ctrl_reset(info, MS_LIB_CTRL_RDONLY); 95333842cedSCho, Yu-Chen break; 95433842cedSCho, Yu-Chen case MS_SYSINF_CARDTYPE_HYBRID: 95533842cedSCho, Yu-Chen default: 95633842cedSCho, Yu-Chen goto exit; 95733842cedSCho, Yu-Chen } 95833842cedSCho, Yu-Chen 95933842cedSCho, Yu-Chen info->MS_Lib.blockSize = be16_to_cpu(SysInfo->wBlockSize); 96033842cedSCho, Yu-Chen info->MS_Lib.NumberOfPhyBlock = be16_to_cpu(SysInfo->wBlockNumber); 96133842cedSCho, Yu-Chen info->MS_Lib.NumberOfLogBlock = be16_to_cpu(SysInfo->wTotalBlockNumber)-2; 96233842cedSCho, Yu-Chen info->MS_Lib.PagesPerBlock = info->MS_Lib.blockSize * SIZE_OF_KIRO / MS_BYTES_PER_PAGE; 96333842cedSCho, Yu-Chen info->MS_Lib.NumberOfSegment = info->MS_Lib.NumberOfPhyBlock / MS_PHYSICAL_BLOCKS_PER_SEGMENT; 96433842cedSCho, Yu-Chen info->MS_Model = be16_to_cpu(SysInfo->wMemorySize); 96533842cedSCho, Yu-Chen 96633842cedSCho, Yu-Chen /*Allocate to all number of logicalblock and physicalblock */ 96733842cedSCho, Yu-Chen if (ms_lib_alloc_logicalmap(us)) 96833842cedSCho, Yu-Chen goto exit; 96933842cedSCho, Yu-Chen 97033842cedSCho, Yu-Chen /* Mark the book block */ 97133842cedSCho, Yu-Chen ms_lib_set_bootblockmark(us, PhyBlock); 97233842cedSCho, Yu-Chen 97333842cedSCho, Yu-Chen SysEntry = &(((struct ms_bootblock_page0 *)PageData)->sysent); 97433842cedSCho, Yu-Chen 97533842cedSCho, Yu-Chen for (i = 0; i < MS_NUMBER_OF_SYSTEM_ENTRY; i++) { 97633842cedSCho, Yu-Chen u32 EntryOffset, EntrySize; 97733842cedSCho, Yu-Chen 97833842cedSCho, Yu-Chen EntryOffset = be32_to_cpu(SysEntry->entry[i].dwStart); 97933842cedSCho, Yu-Chen 98033842cedSCho, Yu-Chen if (EntryOffset == 0xffffff) 98133842cedSCho, Yu-Chen continue; 98233842cedSCho, Yu-Chen EntrySize = be32_to_cpu(SysEntry->entry[i].dwSize); 98333842cedSCho, Yu-Chen 98433842cedSCho, Yu-Chen if (EntrySize == 0) 98533842cedSCho, Yu-Chen continue; 98633842cedSCho, Yu-Chen 98733842cedSCho, Yu-Chen if (EntryOffset + MS_BYTES_PER_PAGE + EntrySize > info->MS_Lib.blockSize * (u32)SIZE_OF_KIRO) 98833842cedSCho, Yu-Chen continue; 98933842cedSCho, Yu-Chen 99033842cedSCho, Yu-Chen if (i == 0) { 99133842cedSCho, Yu-Chen u8 PrevPageNumber = 0; 99233842cedSCho, Yu-Chen u16 phyblk; 99333842cedSCho, Yu-Chen 99433842cedSCho, Yu-Chen if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_INVALID_BLOCK) 99533842cedSCho, Yu-Chen goto exit; 99633842cedSCho, Yu-Chen 99733842cedSCho, Yu-Chen while (EntrySize > 0) { 99833842cedSCho, Yu-Chen 99933842cedSCho, Yu-Chen PageNumber = (u8)(EntryOffset / MS_BYTES_PER_PAGE + 1); 100033842cedSCho, Yu-Chen if (PageNumber != PrevPageNumber) { 100133842cedSCho, Yu-Chen switch (ms_read_readpage(us, PhyBlock, PageNumber, (u32 *)PageBuffer, &ExtraData)) { 100233842cedSCho, Yu-Chen case MS_STATUS_SUCCESS: 100333842cedSCho, Yu-Chen break; 100433842cedSCho, Yu-Chen case MS_STATUS_WRITE_PROTECT: 100533842cedSCho, Yu-Chen case MS_ERROR_FLASH_READ: 100633842cedSCho, Yu-Chen case MS_STATUS_ERROR: 100733842cedSCho, Yu-Chen default: 100833842cedSCho, Yu-Chen goto exit; 100933842cedSCho, Yu-Chen } 101033842cedSCho, Yu-Chen 101133842cedSCho, Yu-Chen PrevPageNumber = PageNumber; 101233842cedSCho, Yu-Chen } 101333842cedSCho, Yu-Chen 101433842cedSCho, Yu-Chen phyblk = be16_to_cpu(*(u16 *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE))); 101533842cedSCho, Yu-Chen if (phyblk < 0x0fff) 101633842cedSCho, Yu-Chen ms_lib_set_initialerrorblock(us, phyblk); 101733842cedSCho, Yu-Chen 101833842cedSCho, Yu-Chen EntryOffset += 2; 101933842cedSCho, Yu-Chen EntrySize -= 2; 102033842cedSCho, Yu-Chen } 102133842cedSCho, Yu-Chen } else if (i == 1) { /* CIS/IDI */ 102233842cedSCho, Yu-Chen struct ms_bootblock_idi *idi; 102333842cedSCho, Yu-Chen 102433842cedSCho, Yu-Chen if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_CIS_IDI) 102533842cedSCho, Yu-Chen goto exit; 102633842cedSCho, Yu-Chen 102733842cedSCho, Yu-Chen switch (ms_read_readpage(us, PhyBlock, (u8)(EntryOffset / MS_BYTES_PER_PAGE + 1), (u32 *)PageBuffer, &ExtraData)) { 102833842cedSCho, Yu-Chen case MS_STATUS_SUCCESS: 102933842cedSCho, Yu-Chen break; 103033842cedSCho, Yu-Chen case MS_STATUS_WRITE_PROTECT: 103133842cedSCho, Yu-Chen case MS_ERROR_FLASH_READ: 103233842cedSCho, Yu-Chen case MS_STATUS_ERROR: 103333842cedSCho, Yu-Chen default: 103433842cedSCho, Yu-Chen goto exit; 103533842cedSCho, Yu-Chen } 103633842cedSCho, Yu-Chen 103733842cedSCho, Yu-Chen idi = &((struct ms_bootblock_cis_idi *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)))->idi.idi; 103833842cedSCho, Yu-Chen if (le16_to_cpu(idi->wIDIgeneralConfiguration) != MS_IDI_GENERAL_CONF) 103933842cedSCho, Yu-Chen goto exit; 104033842cedSCho, Yu-Chen 104133842cedSCho, Yu-Chen info->MS_Lib.BytesPerSector = le16_to_cpu(idi->wIDIbytesPerSector); 104233842cedSCho, Yu-Chen if (info->MS_Lib.BytesPerSector != MS_BYTES_PER_PAGE) 104333842cedSCho, Yu-Chen goto exit; 104433842cedSCho, Yu-Chen } 104533842cedSCho, Yu-Chen } /* End for .. */ 104633842cedSCho, Yu-Chen 104733842cedSCho, Yu-Chen result = 0; 104833842cedSCho, Yu-Chen 104933842cedSCho, Yu-Chen exit: 105033842cedSCho, Yu-Chen if (result) 105133842cedSCho, Yu-Chen ms_lib_free_logicalmap(us); 105233842cedSCho, Yu-Chen 105333842cedSCho, Yu-Chen kfree(PageBuffer); 105433842cedSCho, Yu-Chen 105533842cedSCho, Yu-Chen result = 0; 105633842cedSCho, Yu-Chen return result; 105733842cedSCho, Yu-Chen } 105833842cedSCho, Yu-Chen 105933842cedSCho, Yu-Chen static void ms_lib_free_writebuf(struct us_data *us) 106033842cedSCho, Yu-Chen { 106133842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 106233842cedSCho, Yu-Chen info->MS_Lib.wrtblk = (u16)-1; /* set to -1 */ 106333842cedSCho, Yu-Chen 106433842cedSCho, Yu-Chen /* memset((fdoExt)->MS_Lib.pagemap, 0, sizeof((fdoExt)->MS_Lib.pagemap)) */ 106533842cedSCho, Yu-Chen 106633842cedSCho, Yu-Chen ms_lib_clear_pagemap(info); /* (pdx)->MS_Lib.pagemap memset 0 in ms.h */ 106733842cedSCho, Yu-Chen 106833842cedSCho, Yu-Chen if (info->MS_Lib.blkpag) { 1069e6533e87SAmitoj Kaur Chawla kfree(info->MS_Lib.blkpag); /* Arnold test ... */ 107033842cedSCho, Yu-Chen info->MS_Lib.blkpag = NULL; 107133842cedSCho, Yu-Chen } 107233842cedSCho, Yu-Chen 107333842cedSCho, Yu-Chen if (info->MS_Lib.blkext) { 1074e6533e87SAmitoj Kaur Chawla kfree(info->MS_Lib.blkext); /* Arnold test ... */ 107533842cedSCho, Yu-Chen info->MS_Lib.blkext = NULL; 107633842cedSCho, Yu-Chen } 107733842cedSCho, Yu-Chen } 107833842cedSCho, Yu-Chen 107933842cedSCho, Yu-Chen 108033842cedSCho, Yu-Chen static void ms_lib_free_allocatedarea(struct us_data *us) 108133842cedSCho, Yu-Chen { 108233842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 108333842cedSCho, Yu-Chen 108433842cedSCho, Yu-Chen ms_lib_free_writebuf(us); /* Free MS_Lib.pagemap */ 108533842cedSCho, Yu-Chen ms_lib_free_logicalmap(us); /* kfree MS_Lib.Phy2LogMap and MS_Lib.Log2PhyMap */ 108633842cedSCho, Yu-Chen 108733842cedSCho, Yu-Chen /* set struct us point flag to 0 */ 108833842cedSCho, Yu-Chen info->MS_Lib.flags = 0; 108933842cedSCho, Yu-Chen info->MS_Lib.BytesPerSector = 0; 109033842cedSCho, Yu-Chen info->MS_Lib.SectorsPerCylinder = 0; 109133842cedSCho, Yu-Chen 109233842cedSCho, Yu-Chen info->MS_Lib.cardType = 0; 109333842cedSCho, Yu-Chen info->MS_Lib.blockSize = 0; 109433842cedSCho, Yu-Chen info->MS_Lib.PagesPerBlock = 0; 109533842cedSCho, Yu-Chen 109633842cedSCho, Yu-Chen info->MS_Lib.NumberOfPhyBlock = 0; 109733842cedSCho, Yu-Chen info->MS_Lib.NumberOfLogBlock = 0; 109833842cedSCho, Yu-Chen } 109933842cedSCho, Yu-Chen 110033842cedSCho, Yu-Chen 110133842cedSCho, Yu-Chen static int ms_lib_alloc_writebuf(struct us_data *us) 110233842cedSCho, Yu-Chen { 110333842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 110433842cedSCho, Yu-Chen 110533842cedSCho, Yu-Chen info->MS_Lib.wrtblk = (u16)-1; 110633842cedSCho, Yu-Chen 110733842cedSCho, Yu-Chen info->MS_Lib.blkpag = kmalloc(info->MS_Lib.PagesPerBlock * info->MS_Lib.BytesPerSector, GFP_KERNEL); 110833842cedSCho, Yu-Chen info->MS_Lib.blkext = kmalloc(info->MS_Lib.PagesPerBlock * sizeof(struct ms_lib_type_extdat), GFP_KERNEL); 110933842cedSCho, Yu-Chen 111033842cedSCho, Yu-Chen if ((info->MS_Lib.blkpag == NULL) || (info->MS_Lib.blkext == NULL)) { 111133842cedSCho, Yu-Chen ms_lib_free_writebuf(us); 111233842cedSCho, Yu-Chen return (u32)-1; 111333842cedSCho, Yu-Chen } 111433842cedSCho, Yu-Chen 111533842cedSCho, Yu-Chen ms_lib_clear_writebuf(us); 111633842cedSCho, Yu-Chen 111733842cedSCho, Yu-Chen return 0; 111833842cedSCho, Yu-Chen } 111933842cedSCho, Yu-Chen 112033842cedSCho, Yu-Chen static int ms_lib_force_setlogical_pair(struct us_data *us, u16 logblk, u16 phyblk) 112133842cedSCho, Yu-Chen { 112233842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 112333842cedSCho, Yu-Chen 112433842cedSCho, Yu-Chen if (logblk == MS_LB_NOT_USED) 112533842cedSCho, Yu-Chen return 0; 112633842cedSCho, Yu-Chen 112733842cedSCho, Yu-Chen if ((logblk >= info->MS_Lib.NumberOfLogBlock) || 112833842cedSCho, Yu-Chen (phyblk >= info->MS_Lib.NumberOfPhyBlock)) 112933842cedSCho, Yu-Chen return (u32)-1; 113033842cedSCho, Yu-Chen 113133842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap[phyblk] = logblk; 113233842cedSCho, Yu-Chen info->MS_Lib.Log2PhyMap[logblk] = phyblk; 113333842cedSCho, Yu-Chen 113433842cedSCho, Yu-Chen return 0; 113533842cedSCho, Yu-Chen } 113633842cedSCho, Yu-Chen 113733842cedSCho, Yu-Chen static int ms_read_copyblock(struct us_data *us, u16 oldphy, u16 newphy, 113833842cedSCho, Yu-Chen u16 PhyBlockAddr, u8 PageNum, unsigned char *buf, u16 len) 113933842cedSCho, Yu-Chen { 114033842cedSCho, Yu-Chen struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 114133842cedSCho, Yu-Chen int result; 114233842cedSCho, Yu-Chen 114333842cedSCho, Yu-Chen result = ene_load_bincode(us, MS_RW_PATTERN); 114433842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) 114533842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 114633842cedSCho, Yu-Chen 114733842cedSCho, Yu-Chen memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 114833842cedSCho, Yu-Chen bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 114933842cedSCho, Yu-Chen bcb->DataTransferLength = 0x200*len; 115033842cedSCho, Yu-Chen bcb->Flags = 0x00; 115133842cedSCho, Yu-Chen bcb->CDB[0] = 0xF0; 115233842cedSCho, Yu-Chen bcb->CDB[1] = 0x08; 115333842cedSCho, Yu-Chen bcb->CDB[4] = (unsigned char)(oldphy); 115433842cedSCho, Yu-Chen bcb->CDB[3] = (unsigned char)(oldphy>>8); 115533842cedSCho, Yu-Chen bcb->CDB[2] = 0; /* (BYTE)(oldphy>>16) */ 115633842cedSCho, Yu-Chen bcb->CDB[7] = (unsigned char)(newphy); 115733842cedSCho, Yu-Chen bcb->CDB[6] = (unsigned char)(newphy>>8); 115833842cedSCho, Yu-Chen bcb->CDB[5] = 0; /* (BYTE)(newphy>>16) */ 115933842cedSCho, Yu-Chen bcb->CDB[9] = (unsigned char)(PhyBlockAddr); 116033842cedSCho, Yu-Chen bcb->CDB[8] = (unsigned char)(PhyBlockAddr>>8); 116133842cedSCho, Yu-Chen bcb->CDB[10] = PageNum; 116233842cedSCho, Yu-Chen 116333842cedSCho, Yu-Chen result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0); 116433842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) 116533842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 116633842cedSCho, Yu-Chen 116733842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 116833842cedSCho, Yu-Chen } 116933842cedSCho, Yu-Chen 117033842cedSCho, Yu-Chen static int ms_read_eraseblock(struct us_data *us, u32 PhyBlockAddr) 117133842cedSCho, Yu-Chen { 117233842cedSCho, Yu-Chen struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 117333842cedSCho, Yu-Chen int result; 117433842cedSCho, Yu-Chen u32 bn = PhyBlockAddr; 117533842cedSCho, Yu-Chen 117633842cedSCho, Yu-Chen result = ene_load_bincode(us, MS_RW_PATTERN); 117733842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) 117833842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 117933842cedSCho, Yu-Chen 118033842cedSCho, Yu-Chen memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 118133842cedSCho, Yu-Chen bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 118233842cedSCho, Yu-Chen bcb->DataTransferLength = 0x200; 1183b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 118433842cedSCho, Yu-Chen bcb->CDB[0] = 0xF2; 118533842cedSCho, Yu-Chen bcb->CDB[1] = 0x06; 118633842cedSCho, Yu-Chen bcb->CDB[4] = (unsigned char)(bn); 118733842cedSCho, Yu-Chen bcb->CDB[3] = (unsigned char)(bn>>8); 118833842cedSCho, Yu-Chen bcb->CDB[2] = (unsigned char)(bn>>16); 118933842cedSCho, Yu-Chen 119033842cedSCho, Yu-Chen result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0); 119133842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) 119233842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 119333842cedSCho, Yu-Chen 119433842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 119533842cedSCho, Yu-Chen } 119633842cedSCho, Yu-Chen 119733842cedSCho, Yu-Chen static int ms_lib_check_disableblock(struct us_data *us, u16 PhyBlock) 119833842cedSCho, Yu-Chen { 119933842cedSCho, Yu-Chen unsigned char *PageBuf = NULL; 120033842cedSCho, Yu-Chen u16 result = MS_STATUS_SUCCESS; 120133842cedSCho, Yu-Chen u16 blk, index = 0; 120233842cedSCho, Yu-Chen struct ms_lib_type_extdat extdat; 120333842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 120433842cedSCho, Yu-Chen 120533842cedSCho, Yu-Chen PageBuf = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL); 120633842cedSCho, Yu-Chen if (PageBuf == NULL) { 120733842cedSCho, Yu-Chen result = MS_NO_MEMORY_ERROR; 120833842cedSCho, Yu-Chen goto exit; 120933842cedSCho, Yu-Chen } 121033842cedSCho, Yu-Chen 121133842cedSCho, Yu-Chen ms_read_readpage(us, PhyBlock, 1, (u32 *)PageBuf, &extdat); 121233842cedSCho, Yu-Chen do { 121333842cedSCho, Yu-Chen blk = be16_to_cpu(PageBuf[index]); 121433842cedSCho, Yu-Chen if (blk == MS_LB_NOT_USED) 121533842cedSCho, Yu-Chen break; 121633842cedSCho, Yu-Chen if (blk == info->MS_Lib.Log2PhyMap[0]) { 121733842cedSCho, Yu-Chen result = MS_ERROR_FLASH_READ; 121833842cedSCho, Yu-Chen break; 121933842cedSCho, Yu-Chen } 122033842cedSCho, Yu-Chen index++; 122133842cedSCho, Yu-Chen } while (1); 122233842cedSCho, Yu-Chen 122333842cedSCho, Yu-Chen exit: 122433842cedSCho, Yu-Chen kfree(PageBuf); 122533842cedSCho, Yu-Chen return result; 122633842cedSCho, Yu-Chen } 122733842cedSCho, Yu-Chen 122833842cedSCho, Yu-Chen static int ms_lib_setacquired_errorblock(struct us_data *us, u16 phyblk) 122933842cedSCho, Yu-Chen { 123033842cedSCho, Yu-Chen u16 log; 123133842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 123233842cedSCho, Yu-Chen 123333842cedSCho, Yu-Chen if (phyblk >= info->MS_Lib.NumberOfPhyBlock) 123433842cedSCho, Yu-Chen return (u32)-1; 123533842cedSCho, Yu-Chen 123633842cedSCho, Yu-Chen log = info->MS_Lib.Phy2LogMap[phyblk]; 123733842cedSCho, Yu-Chen 123833842cedSCho, Yu-Chen if (log < info->MS_Lib.NumberOfLogBlock) 123933842cedSCho, Yu-Chen info->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED; 124033842cedSCho, Yu-Chen 124133842cedSCho, Yu-Chen if (info->MS_Lib.Phy2LogMap[phyblk] != MS_LB_INITIAL_ERROR) 124233842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap[phyblk] = MS_LB_ACQUIRED_ERROR; 124333842cedSCho, Yu-Chen 124433842cedSCho, Yu-Chen return 0; 124533842cedSCho, Yu-Chen } 124633842cedSCho, Yu-Chen 124733842cedSCho, Yu-Chen static int ms_lib_overwrite_extra(struct us_data *us, u32 PhyBlockAddr, 124833842cedSCho, Yu-Chen u8 PageNum, u8 OverwriteFlag) 124933842cedSCho, Yu-Chen { 125033842cedSCho, Yu-Chen struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 125133842cedSCho, Yu-Chen int result; 125233842cedSCho, Yu-Chen 125333842cedSCho, Yu-Chen result = ene_load_bincode(us, MS_RW_PATTERN); 125433842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) 125533842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 125633842cedSCho, Yu-Chen 125733842cedSCho, Yu-Chen memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 125833842cedSCho, Yu-Chen bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 125933842cedSCho, Yu-Chen bcb->DataTransferLength = 0x4; 1260b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 126133842cedSCho, Yu-Chen bcb->CDB[0] = 0xF2; 126233842cedSCho, Yu-Chen bcb->CDB[1] = 0x05; 126333842cedSCho, Yu-Chen bcb->CDB[5] = (unsigned char)(PageNum); 126433842cedSCho, Yu-Chen bcb->CDB[4] = (unsigned char)(PhyBlockAddr); 126533842cedSCho, Yu-Chen bcb->CDB[3] = (unsigned char)(PhyBlockAddr>>8); 126633842cedSCho, Yu-Chen bcb->CDB[2] = (unsigned char)(PhyBlockAddr>>16); 126733842cedSCho, Yu-Chen bcb->CDB[6] = OverwriteFlag; 126833842cedSCho, Yu-Chen bcb->CDB[7] = 0xFF; 126933842cedSCho, Yu-Chen bcb->CDB[8] = 0xFF; 127033842cedSCho, Yu-Chen bcb->CDB[9] = 0xFF; 127133842cedSCho, Yu-Chen 127233842cedSCho, Yu-Chen result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0); 127333842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) 127433842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 127533842cedSCho, Yu-Chen 127633842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 127733842cedSCho, Yu-Chen } 127833842cedSCho, Yu-Chen 127933842cedSCho, Yu-Chen static int ms_lib_error_phyblock(struct us_data *us, u16 phyblk) 128033842cedSCho, Yu-Chen { 128133842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 128233842cedSCho, Yu-Chen 128333842cedSCho, Yu-Chen if (phyblk >= info->MS_Lib.NumberOfPhyBlock) 128433842cedSCho, Yu-Chen return MS_STATUS_ERROR; 128533842cedSCho, Yu-Chen 128633842cedSCho, Yu-Chen ms_lib_setacquired_errorblock(us, phyblk); 128733842cedSCho, Yu-Chen 128833842cedSCho, Yu-Chen if (ms_lib_iswritable(info)) 128933842cedSCho, Yu-Chen return ms_lib_overwrite_extra(us, phyblk, 0, (u8)(~MS_REG_OVR_BKST & BYTE_MASK)); 129033842cedSCho, Yu-Chen 129133842cedSCho, Yu-Chen return MS_STATUS_SUCCESS; 129233842cedSCho, Yu-Chen } 129333842cedSCho, Yu-Chen 129433842cedSCho, Yu-Chen static int ms_lib_erase_phyblock(struct us_data *us, u16 phyblk) 129533842cedSCho, Yu-Chen { 129633842cedSCho, Yu-Chen u16 log; 129733842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 129833842cedSCho, Yu-Chen 129933842cedSCho, Yu-Chen if (phyblk >= info->MS_Lib.NumberOfPhyBlock) 130033842cedSCho, Yu-Chen return MS_STATUS_ERROR; 130133842cedSCho, Yu-Chen 130233842cedSCho, Yu-Chen log = info->MS_Lib.Phy2LogMap[phyblk]; 130333842cedSCho, Yu-Chen 130433842cedSCho, Yu-Chen if (log < info->MS_Lib.NumberOfLogBlock) 130533842cedSCho, Yu-Chen info->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED; 130633842cedSCho, Yu-Chen 130733842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED; 130833842cedSCho, Yu-Chen 130933842cedSCho, Yu-Chen if (ms_lib_iswritable(info)) { 131033842cedSCho, Yu-Chen switch (ms_read_eraseblock(us, phyblk)) { 131133842cedSCho, Yu-Chen case MS_STATUS_SUCCESS: 131233842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED_ERASED; 131333842cedSCho, Yu-Chen return MS_STATUS_SUCCESS; 131433842cedSCho, Yu-Chen case MS_ERROR_FLASH_ERASE: 131533842cedSCho, Yu-Chen case MS_STATUS_INT_ERROR: 131633842cedSCho, Yu-Chen ms_lib_error_phyblock(us, phyblk); 131733842cedSCho, Yu-Chen return MS_ERROR_FLASH_ERASE; 131833842cedSCho, Yu-Chen case MS_STATUS_ERROR: 131933842cedSCho, Yu-Chen default: 132033842cedSCho, Yu-Chen ms_lib_ctrl_set(info, MS_LIB_CTRL_RDONLY); /* MS_LibCtrlSet will used by ENE_MSInit ,need check, and why us to info*/ 132133842cedSCho, Yu-Chen ms_lib_setacquired_errorblock(us, phyblk); 132233842cedSCho, Yu-Chen return MS_STATUS_ERROR; 132333842cedSCho, Yu-Chen } 132433842cedSCho, Yu-Chen } 132533842cedSCho, Yu-Chen 132633842cedSCho, Yu-Chen ms_lib_setacquired_errorblock(us, phyblk); 132733842cedSCho, Yu-Chen 132833842cedSCho, Yu-Chen return MS_STATUS_SUCCESS; 132933842cedSCho, Yu-Chen } 133033842cedSCho, Yu-Chen 133133842cedSCho, Yu-Chen static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, 133233842cedSCho, Yu-Chen u8 PageNum, struct ms_lib_type_extdat *ExtraDat) 133333842cedSCho, Yu-Chen { 133433842cedSCho, Yu-Chen struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 133533842cedSCho, Yu-Chen int result; 133633842cedSCho, Yu-Chen u8 ExtBuf[4]; 133733842cedSCho, Yu-Chen 133833842cedSCho, Yu-Chen memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 133933842cedSCho, Yu-Chen bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 134033842cedSCho, Yu-Chen bcb->DataTransferLength = 0x4; 1341b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 134233842cedSCho, Yu-Chen bcb->CDB[0] = 0xF1; 134333842cedSCho, Yu-Chen bcb->CDB[1] = 0x03; 134433842cedSCho, Yu-Chen bcb->CDB[5] = (unsigned char)(PageNum); 134533842cedSCho, Yu-Chen bcb->CDB[4] = (unsigned char)(PhyBlock); 134633842cedSCho, Yu-Chen bcb->CDB[3] = (unsigned char)(PhyBlock>>8); 134733842cedSCho, Yu-Chen bcb->CDB[2] = (unsigned char)(PhyBlock>>16); 134833842cedSCho, Yu-Chen bcb->CDB[6] = 0x01; 134933842cedSCho, Yu-Chen 135033842cedSCho, Yu-Chen result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0); 135133842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) 135233842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 135333842cedSCho, Yu-Chen 135433842cedSCho, Yu-Chen ExtraDat->reserved = 0; 135533842cedSCho, Yu-Chen ExtraDat->intr = 0x80; /* Not yet, waiting for fireware support */ 135633842cedSCho, Yu-Chen ExtraDat->status0 = 0x10; /* Not yet, waiting for fireware support */ 135733842cedSCho, Yu-Chen ExtraDat->status1 = 0x00; /* Not yet, waiting for fireware support */ 135833842cedSCho, Yu-Chen ExtraDat->ovrflg = ExtBuf[0]; 135933842cedSCho, Yu-Chen ExtraDat->mngflg = ExtBuf[1]; 136033842cedSCho, Yu-Chen ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]); 136133842cedSCho, Yu-Chen 136233842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 136333842cedSCho, Yu-Chen } 136433842cedSCho, Yu-Chen 136533842cedSCho, Yu-Chen static int ms_libsearch_block_from_physical(struct us_data *us, u16 phyblk) 136633842cedSCho, Yu-Chen { 136733842cedSCho, Yu-Chen u16 blk; 136833842cedSCho, Yu-Chen struct ms_lib_type_extdat extdat; /* need check */ 136933842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 137033842cedSCho, Yu-Chen 137133842cedSCho, Yu-Chen 137233842cedSCho, Yu-Chen if (phyblk >= info->MS_Lib.NumberOfPhyBlock) 137333842cedSCho, Yu-Chen return MS_LB_ERROR; 137433842cedSCho, Yu-Chen 137533842cedSCho, Yu-Chen for (blk = phyblk + 1; blk != phyblk; blk++) { 137633842cedSCho, Yu-Chen if ((blk & MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK) == 0) 137733842cedSCho, Yu-Chen blk -= MS_PHYSICAL_BLOCKS_PER_SEGMENT; 137833842cedSCho, Yu-Chen 137933842cedSCho, Yu-Chen if (info->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED_ERASED) { 138033842cedSCho, Yu-Chen return blk; 138133842cedSCho, Yu-Chen } else if (info->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED) { 138233842cedSCho, Yu-Chen switch (ms_lib_read_extra(us, blk, 0, &extdat)) { 138333842cedSCho, Yu-Chen case MS_STATUS_SUCCESS: 138433842cedSCho, Yu-Chen case MS_STATUS_SUCCESS_WITH_ECC: 138533842cedSCho, Yu-Chen break; 138633842cedSCho, Yu-Chen case MS_NOCARD_ERROR: 138733842cedSCho, Yu-Chen return MS_NOCARD_ERROR; 138833842cedSCho, Yu-Chen case MS_STATUS_INT_ERROR: 138933842cedSCho, Yu-Chen return MS_LB_ERROR; 139033842cedSCho, Yu-Chen case MS_ERROR_FLASH_READ: 139133842cedSCho, Yu-Chen default: 139233842cedSCho, Yu-Chen ms_lib_setacquired_errorblock(us, blk); 139333842cedSCho, Yu-Chen continue; 139433842cedSCho, Yu-Chen } /* End switch */ 139533842cedSCho, Yu-Chen 139633842cedSCho, Yu-Chen if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) { 139733842cedSCho, Yu-Chen ms_lib_setacquired_errorblock(us, blk); 139833842cedSCho, Yu-Chen continue; 139933842cedSCho, Yu-Chen } 140033842cedSCho, Yu-Chen 140133842cedSCho, Yu-Chen switch (ms_lib_erase_phyblock(us, blk)) { 140233842cedSCho, Yu-Chen case MS_STATUS_SUCCESS: 140333842cedSCho, Yu-Chen return blk; 140433842cedSCho, Yu-Chen case MS_STATUS_ERROR: 140533842cedSCho, Yu-Chen return MS_LB_ERROR; 140633842cedSCho, Yu-Chen case MS_ERROR_FLASH_ERASE: 140733842cedSCho, Yu-Chen default: 140833842cedSCho, Yu-Chen ms_lib_error_phyblock(us, blk); 140933842cedSCho, Yu-Chen break; 141033842cedSCho, Yu-Chen } 141133842cedSCho, Yu-Chen } 141233842cedSCho, Yu-Chen } /* End for */ 141333842cedSCho, Yu-Chen 141433842cedSCho, Yu-Chen return MS_LB_ERROR; 141533842cedSCho, Yu-Chen } 141633842cedSCho, Yu-Chen static int ms_libsearch_block_from_logical(struct us_data *us, u16 logblk) 141733842cedSCho, Yu-Chen { 141833842cedSCho, Yu-Chen u16 phyblk; 141933842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 142033842cedSCho, Yu-Chen 142133842cedSCho, Yu-Chen phyblk = ms_libconv_to_physical(info, logblk); 142233842cedSCho, Yu-Chen if (phyblk >= MS_LB_ERROR) { 142333842cedSCho, Yu-Chen if (logblk >= info->MS_Lib.NumberOfLogBlock) 142433842cedSCho, Yu-Chen return MS_LB_ERROR; 142533842cedSCho, Yu-Chen 142633842cedSCho, Yu-Chen phyblk = (logblk + MS_NUMBER_OF_BOOT_BLOCK) / MS_LOGICAL_BLOCKS_PER_SEGMENT; 142733842cedSCho, Yu-Chen phyblk *= MS_PHYSICAL_BLOCKS_PER_SEGMENT; 142833842cedSCho, Yu-Chen phyblk += MS_PHYSICAL_BLOCKS_PER_SEGMENT - 1; 142933842cedSCho, Yu-Chen } 143033842cedSCho, Yu-Chen 143133842cedSCho, Yu-Chen return ms_libsearch_block_from_physical(us, phyblk); 143233842cedSCho, Yu-Chen } 143333842cedSCho, Yu-Chen 143433842cedSCho, Yu-Chen static int ms_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb) 143533842cedSCho, Yu-Chen { 143633842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); 143733842cedSCho, Yu-Chen 143833842cedSCho, Yu-Chen /* pr_info("MS_SCSI_Test_Unit_Ready\n"); */ 143933842cedSCho, Yu-Chen if (info->MS_Status.Insert && info->MS_Status.Ready) { 144033842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 144133842cedSCho, Yu-Chen } else { 144233842cedSCho, Yu-Chen ene_ms_init(us); 144333842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 144433842cedSCho, Yu-Chen } 144533842cedSCho, Yu-Chen 144633842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 144733842cedSCho, Yu-Chen } 144833842cedSCho, Yu-Chen 144933842cedSCho, Yu-Chen static int ms_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb) 145033842cedSCho, Yu-Chen { 145133842cedSCho, Yu-Chen /* pr_info("MS_SCSI_Inquiry\n"); */ 145233842cedSCho, Yu-Chen unsigned char data_ptr[36] = { 145333842cedSCho, Yu-Chen 0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 145433842cedSCho, Yu-Chen 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, 145533842cedSCho, Yu-Chen 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 145633842cedSCho, Yu-Chen 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30}; 145733842cedSCho, Yu-Chen 145833842cedSCho, Yu-Chen usb_stor_set_xfer_buf(data_ptr, 36, srb); 145933842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 146033842cedSCho, Yu-Chen } 146133842cedSCho, Yu-Chen 146233842cedSCho, Yu-Chen static int ms_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb) 146333842cedSCho, Yu-Chen { 146433842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 146533842cedSCho, Yu-Chen unsigned char mediaNoWP[12] = { 146633842cedSCho, Yu-Chen 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 146733842cedSCho, Yu-Chen 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 }; 146833842cedSCho, Yu-Chen unsigned char mediaWP[12] = { 146933842cedSCho, Yu-Chen 0x0b, 0x00, 0x80, 0x08, 0x00, 0x00, 147033842cedSCho, Yu-Chen 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 }; 147133842cedSCho, Yu-Chen 147233842cedSCho, Yu-Chen if (info->MS_Status.WtP) 147333842cedSCho, Yu-Chen usb_stor_set_xfer_buf(mediaWP, 12, srb); 147433842cedSCho, Yu-Chen else 147533842cedSCho, Yu-Chen usb_stor_set_xfer_buf(mediaNoWP, 12, srb); 147633842cedSCho, Yu-Chen 147733842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 147833842cedSCho, Yu-Chen } 147933842cedSCho, Yu-Chen 148033842cedSCho, Yu-Chen static int ms_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb) 148133842cedSCho, Yu-Chen { 148233842cedSCho, Yu-Chen u32 bl_num; 148333842cedSCho, Yu-Chen u16 bl_len; 148433842cedSCho, Yu-Chen unsigned int offset = 0; 148533842cedSCho, Yu-Chen unsigned char buf[8]; 148633842cedSCho, Yu-Chen struct scatterlist *sg = NULL; 148733842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 148833842cedSCho, Yu-Chen 1489191648d0SJoe Perches usb_stor_dbg(us, "ms_scsi_read_capacity\n"); 149033842cedSCho, Yu-Chen bl_len = 0x200; 149133842cedSCho, Yu-Chen if (info->MS_Status.IsMSPro) 149233842cedSCho, Yu-Chen bl_num = info->MSP_TotalBlock - 1; 149333842cedSCho, Yu-Chen else 149433842cedSCho, Yu-Chen bl_num = info->MS_Lib.NumberOfLogBlock * info->MS_Lib.blockSize * 2 - 1; 149533842cedSCho, Yu-Chen 149633842cedSCho, Yu-Chen info->bl_num = bl_num; 1497191648d0SJoe Perches usb_stor_dbg(us, "bl_len = %x\n", bl_len); 1498191648d0SJoe Perches usb_stor_dbg(us, "bl_num = %x\n", bl_num); 149933842cedSCho, Yu-Chen 150033842cedSCho, Yu-Chen /*srb->request_bufflen = 8; */ 150133842cedSCho, Yu-Chen buf[0] = (bl_num >> 24) & 0xff; 150233842cedSCho, Yu-Chen buf[1] = (bl_num >> 16) & 0xff; 150333842cedSCho, Yu-Chen buf[2] = (bl_num >> 8) & 0xff; 150433842cedSCho, Yu-Chen buf[3] = (bl_num >> 0) & 0xff; 150533842cedSCho, Yu-Chen buf[4] = (bl_len >> 24) & 0xff; 150633842cedSCho, Yu-Chen buf[5] = (bl_len >> 16) & 0xff; 150733842cedSCho, Yu-Chen buf[6] = (bl_len >> 8) & 0xff; 150833842cedSCho, Yu-Chen buf[7] = (bl_len >> 0) & 0xff; 150933842cedSCho, Yu-Chen 151033842cedSCho, Yu-Chen usb_stor_access_xfer_buf(buf, 8, srb, &sg, &offset, TO_XFER_BUF); 151133842cedSCho, Yu-Chen 151233842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 151333842cedSCho, Yu-Chen } 151433842cedSCho, Yu-Chen 151533842cedSCho, Yu-Chen static void ms_lib_phy_to_log_range(u16 PhyBlock, u16 *LogStart, u16 *LogEnde) 151633842cedSCho, Yu-Chen { 151733842cedSCho, Yu-Chen PhyBlock /= MS_PHYSICAL_BLOCKS_PER_SEGMENT; 151833842cedSCho, Yu-Chen 151933842cedSCho, Yu-Chen if (PhyBlock) { 152033842cedSCho, Yu-Chen *LogStart = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT + (PhyBlock - 1) * MS_LOGICAL_BLOCKS_PER_SEGMENT;/*496*/ 152133842cedSCho, Yu-Chen *LogEnde = *LogStart + MS_LOGICAL_BLOCKS_PER_SEGMENT;/*496*/ 152233842cedSCho, Yu-Chen } else { 152333842cedSCho, Yu-Chen *LogStart = 0; 152433842cedSCho, Yu-Chen *LogEnde = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT;/*494*/ 152533842cedSCho, Yu-Chen } 152633842cedSCho, Yu-Chen } 152733842cedSCho, Yu-Chen 152833842cedSCho, Yu-Chen static int ms_lib_read_extrablock(struct us_data *us, u32 PhyBlock, 152933842cedSCho, Yu-Chen u8 PageNum, u8 blen, void *buf) 153033842cedSCho, Yu-Chen { 153133842cedSCho, Yu-Chen struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 153233842cedSCho, Yu-Chen int result; 153333842cedSCho, Yu-Chen 153433842cedSCho, Yu-Chen /* Read Extra Data */ 153533842cedSCho, Yu-Chen memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 153633842cedSCho, Yu-Chen bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 153733842cedSCho, Yu-Chen bcb->DataTransferLength = 0x4 * blen; 1538b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 153933842cedSCho, Yu-Chen bcb->CDB[0] = 0xF1; 154033842cedSCho, Yu-Chen bcb->CDB[1] = 0x03; 154133842cedSCho, Yu-Chen bcb->CDB[5] = (unsigned char)(PageNum); 154233842cedSCho, Yu-Chen bcb->CDB[4] = (unsigned char)(PhyBlock); 154333842cedSCho, Yu-Chen bcb->CDB[3] = (unsigned char)(PhyBlock>>8); 154433842cedSCho, Yu-Chen bcb->CDB[2] = (unsigned char)(PhyBlock>>16); 154533842cedSCho, Yu-Chen bcb->CDB[6] = blen; 154633842cedSCho, Yu-Chen 154733842cedSCho, Yu-Chen result = ene_send_scsi_cmd(us, FDIR_READ, buf, 0); 154833842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) 154933842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 155033842cedSCho, Yu-Chen 155133842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 155233842cedSCho, Yu-Chen } 155333842cedSCho, Yu-Chen 155433842cedSCho, Yu-Chen static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st) 155533842cedSCho, Yu-Chen { 155633842cedSCho, Yu-Chen u16 PhyBlock, newblk, i; 155733842cedSCho, Yu-Chen u16 LogStart, LogEnde; 155833842cedSCho, Yu-Chen struct ms_lib_type_extdat extdat; 155933842cedSCho, Yu-Chen u8 buf[0x200]; 156033842cedSCho, Yu-Chen u32 count = 0, index = 0; 156133842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 156233842cedSCho, Yu-Chen 156333842cedSCho, Yu-Chen for (PhyBlock = 0; PhyBlock < info->MS_Lib.NumberOfPhyBlock;) { 156433842cedSCho, Yu-Chen ms_lib_phy_to_log_range(PhyBlock, &LogStart, &LogEnde); 156533842cedSCho, Yu-Chen 156633842cedSCho, Yu-Chen for (i = 0; i < MS_PHYSICAL_BLOCKS_PER_SEGMENT; i++, PhyBlock++) { 156733842cedSCho, Yu-Chen switch (ms_libconv_to_logical(info, PhyBlock)) { 156833842cedSCho, Yu-Chen case MS_STATUS_ERROR: 156933842cedSCho, Yu-Chen continue; 157033842cedSCho, Yu-Chen default: 157133842cedSCho, Yu-Chen break; 157233842cedSCho, Yu-Chen } 157333842cedSCho, Yu-Chen 157433842cedSCho, Yu-Chen if (count == PhyBlock) { 157533842cedSCho, Yu-Chen ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, &buf); 157633842cedSCho, Yu-Chen count += 0x80; 157733842cedSCho, Yu-Chen } 157833842cedSCho, Yu-Chen index = (PhyBlock % 0x80) * 4; 157933842cedSCho, Yu-Chen 158033842cedSCho, Yu-Chen extdat.ovrflg = buf[index]; 158133842cedSCho, Yu-Chen extdat.mngflg = buf[index+1]; 158233842cedSCho, Yu-Chen extdat.logadr = memstick_logaddr(buf[index+2], buf[index+3]); 158333842cedSCho, Yu-Chen 158433842cedSCho, Yu-Chen if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) { 158533842cedSCho, Yu-Chen ms_lib_setacquired_errorblock(us, PhyBlock); 158633842cedSCho, Yu-Chen continue; 158733842cedSCho, Yu-Chen } 158833842cedSCho, Yu-Chen 158933842cedSCho, Yu-Chen if ((extdat.mngflg & MS_REG_MNG_ATFLG) == MS_REG_MNG_ATFLG_ATTBL) { 159033842cedSCho, Yu-Chen ms_lib_erase_phyblock(us, PhyBlock); 159133842cedSCho, Yu-Chen continue; 159233842cedSCho, Yu-Chen } 159333842cedSCho, Yu-Chen 159433842cedSCho, Yu-Chen if (extdat.logadr != MS_LB_NOT_USED) { 159533842cedSCho, Yu-Chen if ((extdat.logadr < LogStart) || (LogEnde <= extdat.logadr)) { 159633842cedSCho, Yu-Chen ms_lib_erase_phyblock(us, PhyBlock); 159733842cedSCho, Yu-Chen continue; 159833842cedSCho, Yu-Chen } 159933842cedSCho, Yu-Chen 160033842cedSCho, Yu-Chen newblk = ms_libconv_to_physical(info, extdat.logadr); 160133842cedSCho, Yu-Chen 160233842cedSCho, Yu-Chen if (newblk != MS_LB_NOT_USED) { 160333842cedSCho, Yu-Chen if (extdat.logadr == 0) { 160433842cedSCho, Yu-Chen ms_lib_set_logicalpair(us, extdat.logadr, PhyBlock); 160533842cedSCho, Yu-Chen if (ms_lib_check_disableblock(us, btBlk1st)) { 160633842cedSCho, Yu-Chen ms_lib_set_logicalpair(us, extdat.logadr, newblk); 160733842cedSCho, Yu-Chen continue; 160833842cedSCho, Yu-Chen } 160933842cedSCho, Yu-Chen } 161033842cedSCho, Yu-Chen 161133842cedSCho, Yu-Chen ms_lib_read_extra(us, newblk, 0, &extdat); 161233842cedSCho, Yu-Chen if ((extdat.ovrflg & MS_REG_OVR_UDST) == MS_REG_OVR_UDST_UPDATING) { 161333842cedSCho, Yu-Chen ms_lib_erase_phyblock(us, PhyBlock); 161433842cedSCho, Yu-Chen continue; 161533842cedSCho, Yu-Chen } else { 161633842cedSCho, Yu-Chen ms_lib_erase_phyblock(us, newblk); 161733842cedSCho, Yu-Chen } 161833842cedSCho, Yu-Chen } 161933842cedSCho, Yu-Chen 162033842cedSCho, Yu-Chen ms_lib_set_logicalpair(us, extdat.logadr, PhyBlock); 162133842cedSCho, Yu-Chen } 162233842cedSCho, Yu-Chen } 162333842cedSCho, Yu-Chen } /* End for ... */ 162433842cedSCho, Yu-Chen 162533842cedSCho, Yu-Chen return MS_STATUS_SUCCESS; 162633842cedSCho, Yu-Chen } 162733842cedSCho, Yu-Chen 162833842cedSCho, Yu-Chen 162933842cedSCho, Yu-Chen static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb) 163033842cedSCho, Yu-Chen { 163133842cedSCho, Yu-Chen int result; 163233842cedSCho, Yu-Chen unsigned char *cdb = srb->cmnd; 163333842cedSCho, Yu-Chen struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 163433842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 163533842cedSCho, Yu-Chen 163633842cedSCho, Yu-Chen u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) | 163733842cedSCho, Yu-Chen ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff); 163833842cedSCho, Yu-Chen u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff); 163933842cedSCho, Yu-Chen u32 blenByte = blen * 0x200; 164033842cedSCho, Yu-Chen 164133842cedSCho, Yu-Chen if (bn > info->bl_num) 164233842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 164333842cedSCho, Yu-Chen 164433842cedSCho, Yu-Chen if (info->MS_Status.IsMSPro) { 164533842cedSCho, Yu-Chen result = ene_load_bincode(us, MSP_RW_PATTERN); 164633842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) { 1647191648d0SJoe Perches usb_stor_dbg(us, "Load MPS RW pattern Fail !!\n"); 164833842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 164933842cedSCho, Yu-Chen } 165033842cedSCho, Yu-Chen 165133842cedSCho, Yu-Chen /* set up the command wrapper */ 165233842cedSCho, Yu-Chen memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 165333842cedSCho, Yu-Chen bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 165433842cedSCho, Yu-Chen bcb->DataTransferLength = blenByte; 1655b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 165633842cedSCho, Yu-Chen bcb->CDB[0] = 0xF1; 165733842cedSCho, Yu-Chen bcb->CDB[1] = 0x02; 165833842cedSCho, Yu-Chen bcb->CDB[5] = (unsigned char)(bn); 165933842cedSCho, Yu-Chen bcb->CDB[4] = (unsigned char)(bn>>8); 166033842cedSCho, Yu-Chen bcb->CDB[3] = (unsigned char)(bn>>16); 166133842cedSCho, Yu-Chen bcb->CDB[2] = (unsigned char)(bn>>24); 166233842cedSCho, Yu-Chen 166333842cedSCho, Yu-Chen result = ene_send_scsi_cmd(us, FDIR_READ, scsi_sglist(srb), 1); 166433842cedSCho, Yu-Chen } else { 166533842cedSCho, Yu-Chen void *buf; 166633842cedSCho, Yu-Chen int offset = 0; 166733842cedSCho, Yu-Chen u16 phyblk, logblk; 166833842cedSCho, Yu-Chen u8 PageNum; 166933842cedSCho, Yu-Chen u16 len; 167033842cedSCho, Yu-Chen u32 blkno; 167133842cedSCho, Yu-Chen 167233842cedSCho, Yu-Chen buf = kmalloc(blenByte, GFP_KERNEL); 167333842cedSCho, Yu-Chen if (buf == NULL) 167433842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 167533842cedSCho, Yu-Chen 167633842cedSCho, Yu-Chen result = ene_load_bincode(us, MS_RW_PATTERN); 167733842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) { 167833842cedSCho, Yu-Chen pr_info("Load MS RW pattern Fail !!\n"); 167933842cedSCho, Yu-Chen result = USB_STOR_TRANSPORT_ERROR; 168033842cedSCho, Yu-Chen goto exit; 168133842cedSCho, Yu-Chen } 168233842cedSCho, Yu-Chen 168333842cedSCho, Yu-Chen logblk = (u16)(bn / info->MS_Lib.PagesPerBlock); 168433842cedSCho, Yu-Chen PageNum = (u8)(bn % info->MS_Lib.PagesPerBlock); 168533842cedSCho, Yu-Chen 168633842cedSCho, Yu-Chen while (1) { 168733842cedSCho, Yu-Chen if (blen > (info->MS_Lib.PagesPerBlock-PageNum)) 168833842cedSCho, Yu-Chen len = info->MS_Lib.PagesPerBlock-PageNum; 168933842cedSCho, Yu-Chen else 169033842cedSCho, Yu-Chen len = blen; 169133842cedSCho, Yu-Chen 169233842cedSCho, Yu-Chen phyblk = ms_libconv_to_physical(info, logblk); 169333842cedSCho, Yu-Chen blkno = phyblk * 0x20 + PageNum; 169433842cedSCho, Yu-Chen 169533842cedSCho, Yu-Chen /* set up the command wrapper */ 169633842cedSCho, Yu-Chen memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 169733842cedSCho, Yu-Chen bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 169833842cedSCho, Yu-Chen bcb->DataTransferLength = 0x200 * len; 1699b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 170033842cedSCho, Yu-Chen bcb->CDB[0] = 0xF1; 170133842cedSCho, Yu-Chen bcb->CDB[1] = 0x02; 170233842cedSCho, Yu-Chen bcb->CDB[5] = (unsigned char)(blkno); 170333842cedSCho, Yu-Chen bcb->CDB[4] = (unsigned char)(blkno>>8); 170433842cedSCho, Yu-Chen bcb->CDB[3] = (unsigned char)(blkno>>16); 170533842cedSCho, Yu-Chen bcb->CDB[2] = (unsigned char)(blkno>>24); 170633842cedSCho, Yu-Chen 170733842cedSCho, Yu-Chen result = ene_send_scsi_cmd(us, FDIR_READ, buf+offset, 0); 170833842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) { 170933842cedSCho, Yu-Chen pr_info("MS_SCSI_Read --- result = %x\n", result); 171033842cedSCho, Yu-Chen result = USB_STOR_TRANSPORT_ERROR; 171133842cedSCho, Yu-Chen goto exit; 171233842cedSCho, Yu-Chen } 171333842cedSCho, Yu-Chen 171433842cedSCho, Yu-Chen blen -= len; 171533842cedSCho, Yu-Chen if (blen <= 0) 171633842cedSCho, Yu-Chen break; 171733842cedSCho, Yu-Chen logblk++; 171833842cedSCho, Yu-Chen PageNum = 0; 171933842cedSCho, Yu-Chen offset += MS_BYTES_PER_PAGE*len; 172033842cedSCho, Yu-Chen } 172133842cedSCho, Yu-Chen usb_stor_set_xfer_buf(buf, blenByte, srb); 172233842cedSCho, Yu-Chen exit: 172333842cedSCho, Yu-Chen kfree(buf); 172433842cedSCho, Yu-Chen } 172533842cedSCho, Yu-Chen return result; 172633842cedSCho, Yu-Chen } 172733842cedSCho, Yu-Chen 172833842cedSCho, Yu-Chen static int ms_scsi_write(struct us_data *us, struct scsi_cmnd *srb) 172933842cedSCho, Yu-Chen { 173033842cedSCho, Yu-Chen int result; 173133842cedSCho, Yu-Chen struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 173233842cedSCho, Yu-Chen unsigned char *cdb = srb->cmnd; 173333842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 173433842cedSCho, Yu-Chen 173533842cedSCho, Yu-Chen u32 bn = ((cdb[2] << 24) & 0xff000000) | 173633842cedSCho, Yu-Chen ((cdb[3] << 16) & 0x00ff0000) | 173733842cedSCho, Yu-Chen ((cdb[4] << 8) & 0x0000ff00) | 173833842cedSCho, Yu-Chen ((cdb[5] << 0) & 0x000000ff); 173933842cedSCho, Yu-Chen u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff); 174033842cedSCho, Yu-Chen u32 blenByte = blen * 0x200; 174133842cedSCho, Yu-Chen 174233842cedSCho, Yu-Chen if (bn > info->bl_num) 174333842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 174433842cedSCho, Yu-Chen 174533842cedSCho, Yu-Chen if (info->MS_Status.IsMSPro) { 174633842cedSCho, Yu-Chen result = ene_load_bincode(us, MSP_RW_PATTERN); 174733842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) { 174833842cedSCho, Yu-Chen pr_info("Load MSP RW pattern Fail !!\n"); 174933842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 175033842cedSCho, Yu-Chen } 175133842cedSCho, Yu-Chen 175233842cedSCho, Yu-Chen /* set up the command wrapper */ 175333842cedSCho, Yu-Chen memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 175433842cedSCho, Yu-Chen bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 175533842cedSCho, Yu-Chen bcb->DataTransferLength = blenByte; 175633842cedSCho, Yu-Chen bcb->Flags = 0x00; 175733842cedSCho, Yu-Chen bcb->CDB[0] = 0xF0; 175833842cedSCho, Yu-Chen bcb->CDB[1] = 0x04; 175933842cedSCho, Yu-Chen bcb->CDB[5] = (unsigned char)(bn); 176033842cedSCho, Yu-Chen bcb->CDB[4] = (unsigned char)(bn>>8); 176133842cedSCho, Yu-Chen bcb->CDB[3] = (unsigned char)(bn>>16); 176233842cedSCho, Yu-Chen bcb->CDB[2] = (unsigned char)(bn>>24); 176333842cedSCho, Yu-Chen 176433842cedSCho, Yu-Chen result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1); 176533842cedSCho, Yu-Chen } else { 176633842cedSCho, Yu-Chen void *buf; 1767bc985c10SFelipe Balbi int offset = 0; 176833842cedSCho, Yu-Chen u16 PhyBlockAddr; 176933842cedSCho, Yu-Chen u8 PageNum; 177033842cedSCho, Yu-Chen u16 len, oldphy, newphy; 177133842cedSCho, Yu-Chen 177233842cedSCho, Yu-Chen buf = kmalloc(blenByte, GFP_KERNEL); 177333842cedSCho, Yu-Chen if (buf == NULL) 177433842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 177533842cedSCho, Yu-Chen usb_stor_set_xfer_buf(buf, blenByte, srb); 177633842cedSCho, Yu-Chen 177733842cedSCho, Yu-Chen result = ene_load_bincode(us, MS_RW_PATTERN); 177833842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) { 177933842cedSCho, Yu-Chen pr_info("Load MS RW pattern Fail !!\n"); 178033842cedSCho, Yu-Chen result = USB_STOR_TRANSPORT_ERROR; 178133842cedSCho, Yu-Chen goto exit; 178233842cedSCho, Yu-Chen } 178333842cedSCho, Yu-Chen 178433842cedSCho, Yu-Chen PhyBlockAddr = (u16)(bn / info->MS_Lib.PagesPerBlock); 178533842cedSCho, Yu-Chen PageNum = (u8)(bn % info->MS_Lib.PagesPerBlock); 178633842cedSCho, Yu-Chen 178733842cedSCho, Yu-Chen while (1) { 178833842cedSCho, Yu-Chen if (blen > (info->MS_Lib.PagesPerBlock-PageNum)) 178933842cedSCho, Yu-Chen len = info->MS_Lib.PagesPerBlock-PageNum; 179033842cedSCho, Yu-Chen else 179133842cedSCho, Yu-Chen len = blen; 179233842cedSCho, Yu-Chen 179333842cedSCho, Yu-Chen oldphy = ms_libconv_to_physical(info, PhyBlockAddr); /* need check us <-> info */ 179433842cedSCho, Yu-Chen newphy = ms_libsearch_block_from_logical(us, PhyBlockAddr); 179533842cedSCho, Yu-Chen 179633842cedSCho, Yu-Chen result = ms_read_copyblock(us, oldphy, newphy, PhyBlockAddr, PageNum, buf+offset, len); 179733842cedSCho, Yu-Chen 179833842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) { 179933842cedSCho, Yu-Chen pr_info("MS_SCSI_Write --- result = %x\n", result); 180033842cedSCho, Yu-Chen result = USB_STOR_TRANSPORT_ERROR; 180133842cedSCho, Yu-Chen goto exit; 180233842cedSCho, Yu-Chen } 180333842cedSCho, Yu-Chen 180433842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap[oldphy] = MS_LB_NOT_USED_ERASED; 180533842cedSCho, Yu-Chen ms_lib_force_setlogical_pair(us, PhyBlockAddr, newphy); 180633842cedSCho, Yu-Chen 180733842cedSCho, Yu-Chen blen -= len; 180833842cedSCho, Yu-Chen if (blen <= 0) 180933842cedSCho, Yu-Chen break; 181033842cedSCho, Yu-Chen PhyBlockAddr++; 181133842cedSCho, Yu-Chen PageNum = 0; 181233842cedSCho, Yu-Chen offset += MS_BYTES_PER_PAGE*len; 181333842cedSCho, Yu-Chen } 181433842cedSCho, Yu-Chen exit: 181533842cedSCho, Yu-Chen kfree(buf); 181633842cedSCho, Yu-Chen } 181733842cedSCho, Yu-Chen return result; 181833842cedSCho, Yu-Chen } 181933842cedSCho, Yu-Chen 182033842cedSCho, Yu-Chen /* 182133842cedSCho, Yu-Chen * ENE MS Card 182233842cedSCho, Yu-Chen */ 182333842cedSCho, Yu-Chen 182441e568d1Shuajun li static int ene_get_card_type(struct us_data *us, u16 index, void *buf) 182541e568d1Shuajun li { 182641e568d1Shuajun li struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 182741e568d1Shuajun li int result; 182841e568d1Shuajun li 182941e568d1Shuajun li memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 183041e568d1Shuajun li bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 183141e568d1Shuajun li bcb->DataTransferLength = 0x01; 1832b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 183341e568d1Shuajun li bcb->CDB[0] = 0xED; 183441e568d1Shuajun li bcb->CDB[2] = (unsigned char)(index>>8); 183541e568d1Shuajun li bcb->CDB[3] = (unsigned char)index; 183641e568d1Shuajun li 183741e568d1Shuajun li result = ene_send_scsi_cmd(us, FDIR_READ, buf, 0); 183841e568d1Shuajun li return result; 183941e568d1Shuajun li } 184041e568d1Shuajun li 184141e568d1Shuajun li static int ene_get_card_status(struct us_data *us, u8 *buf) 184241e568d1Shuajun li { 184341e568d1Shuajun li u16 tmpreg; 184441e568d1Shuajun li u32 reg4b; 184541e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 184641e568d1Shuajun li 1847191648d0SJoe Perches /*usb_stor_dbg(us, "transport --- ENE_ReadSDReg\n");*/ 184841e568d1Shuajun li reg4b = *(u32 *)&buf[0x18]; 184941e568d1Shuajun li info->SD_READ_BL_LEN = (u8)((reg4b >> 8) & 0x0f); 185041e568d1Shuajun li 185141e568d1Shuajun li tmpreg = (u16) reg4b; 185241e568d1Shuajun li reg4b = *(u32 *)(&buf[0x14]); 185341e568d1Shuajun li if (info->SD_Status.HiCapacity && !info->SD_Status.IsMMC) 185441e568d1Shuajun li info->HC_C_SIZE = (reg4b >> 8) & 0x3fffff; 185541e568d1Shuajun li 185641e568d1Shuajun li info->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (u16)(reg4b >> 22); 185741e568d1Shuajun li info->SD_C_SIZE_MULT = (u8)(reg4b >> 7) & 0x07; 185841e568d1Shuajun li if (info->SD_Status.HiCapacity && info->SD_Status.IsMMC) 185941e568d1Shuajun li info->HC_C_SIZE = *(u32 *)(&buf[0x100]); 186041e568d1Shuajun li 186141e568d1Shuajun li if (info->SD_READ_BL_LEN > SD_BLOCK_LEN) { 186241e568d1Shuajun li info->SD_Block_Mult = 1 << (info->SD_READ_BL_LEN-SD_BLOCK_LEN); 186341e568d1Shuajun li info->SD_READ_BL_LEN = SD_BLOCK_LEN; 186441e568d1Shuajun li } else { 186541e568d1Shuajun li info->SD_Block_Mult = 1; 186641e568d1Shuajun li } 186741e568d1Shuajun li 186841e568d1Shuajun li return USB_STOR_TRANSPORT_GOOD; 186941e568d1Shuajun li } 187041e568d1Shuajun li 187141e568d1Shuajun li static int ene_load_bincode(struct us_data *us, unsigned char flag) 187241e568d1Shuajun li { 187341e568d1Shuajun li int err; 187441e568d1Shuajun li char *fw_name = NULL; 187541e568d1Shuajun li unsigned char *buf = NULL; 187641e568d1Shuajun li const struct firmware *sd_fw = NULL; 187741e568d1Shuajun li int result = USB_STOR_TRANSPORT_ERROR; 187841e568d1Shuajun li struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 187941e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 188041e568d1Shuajun li 188141e568d1Shuajun li if (info->BIN_FLAG == flag) 188241e568d1Shuajun li return USB_STOR_TRANSPORT_GOOD; 188341e568d1Shuajun li 188441e568d1Shuajun li switch (flag) { 188541e568d1Shuajun li /* For SD */ 188641e568d1Shuajun li case SD_INIT1_PATTERN: 1887191648d0SJoe Perches usb_stor_dbg(us, "SD_INIT1_PATTERN\n"); 1888595c8970STim Gardner fw_name = SD_INIT1_FIRMWARE; 188941e568d1Shuajun li break; 189041e568d1Shuajun li case SD_INIT2_PATTERN: 1891191648d0SJoe Perches usb_stor_dbg(us, "SD_INIT2_PATTERN\n"); 1892595c8970STim Gardner fw_name = SD_INIT2_FIRMWARE; 189341e568d1Shuajun li break; 189441e568d1Shuajun li case SD_RW_PATTERN: 1895191648d0SJoe Perches usb_stor_dbg(us, "SD_RW_PATTERN\n"); 1896595c8970STim Gardner fw_name = SD_RW_FIRMWARE; 189741e568d1Shuajun li break; 189833842cedSCho, Yu-Chen /* For MS */ 189933842cedSCho, Yu-Chen case MS_INIT_PATTERN: 1900191648d0SJoe Perches usb_stor_dbg(us, "MS_INIT_PATTERN\n"); 1901595c8970STim Gardner fw_name = MS_INIT_FIRMWARE; 190233842cedSCho, Yu-Chen break; 190333842cedSCho, Yu-Chen case MSP_RW_PATTERN: 1904191648d0SJoe Perches usb_stor_dbg(us, "MSP_RW_PATTERN\n"); 1905595c8970STim Gardner fw_name = MSP_RW_FIRMWARE; 190633842cedSCho, Yu-Chen break; 190733842cedSCho, Yu-Chen case MS_RW_PATTERN: 1908191648d0SJoe Perches usb_stor_dbg(us, "MS_RW_PATTERN\n"); 1909595c8970STim Gardner fw_name = MS_RW_FIRMWARE; 191033842cedSCho, Yu-Chen break; 191141e568d1Shuajun li default: 1912191648d0SJoe Perches usb_stor_dbg(us, "----------- Unknown PATTERN ----------\n"); 191341e568d1Shuajun li goto nofw; 191441e568d1Shuajun li } 191541e568d1Shuajun li 191641e568d1Shuajun li err = request_firmware(&sd_fw, fw_name, &us->pusb_dev->dev); 191741e568d1Shuajun li if (err) { 1918191648d0SJoe Perches usb_stor_dbg(us, "load firmware %s failed\n", fw_name); 191941e568d1Shuajun li goto nofw; 192041e568d1Shuajun li } 1921a328512dSBenoit Taine buf = kmemdup(sd_fw->data, sd_fw->size, GFP_KERNEL); 1922191648d0SJoe Perches if (buf == NULL) 192341e568d1Shuajun li goto nofw; 1924191648d0SJoe Perches 192541e568d1Shuajun li memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 192641e568d1Shuajun li bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 192741e568d1Shuajun li bcb->DataTransferLength = sd_fw->size; 192841e568d1Shuajun li bcb->Flags = 0x00; 192941e568d1Shuajun li bcb->CDB[0] = 0xEF; 193041e568d1Shuajun li 193141e568d1Shuajun li result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0); 1932aa18c4b6SAlan Stern if (us->srb != NULL) 1933aa18c4b6SAlan Stern scsi_set_resid(us->srb, 0); 193441e568d1Shuajun li info->BIN_FLAG = flag; 193541e568d1Shuajun li kfree(buf); 193641e568d1Shuajun li 193741e568d1Shuajun li nofw: 193841e568d1Shuajun li release_firmware(sd_fw); 193941e568d1Shuajun li return result; 194041e568d1Shuajun li } 194141e568d1Shuajun li 194233842cedSCho, Yu-Chen static int ms_card_init(struct us_data *us) 194333842cedSCho, Yu-Chen { 194433842cedSCho, Yu-Chen u32 result; 194533842cedSCho, Yu-Chen u16 TmpBlock; 194633842cedSCho, Yu-Chen unsigned char *PageBuffer0 = NULL, *PageBuffer1 = NULL; 194733842cedSCho, Yu-Chen struct ms_lib_type_extdat extdat; 194833842cedSCho, Yu-Chen u16 btBlk1st, btBlk2nd; 194933842cedSCho, Yu-Chen u32 btBlk1stErred; 195033842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 195133842cedSCho, Yu-Chen 195233842cedSCho, Yu-Chen printk(KERN_INFO "MS_CardInit start\n"); 195333842cedSCho, Yu-Chen 195433842cedSCho, Yu-Chen ms_lib_free_allocatedarea(us); /* Clean buffer and set struct us_data flag to 0 */ 195533842cedSCho, Yu-Chen 195633842cedSCho, Yu-Chen /* get two PageBuffer */ 195733842cedSCho, Yu-Chen PageBuffer0 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL); 195833842cedSCho, Yu-Chen PageBuffer1 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL); 195933842cedSCho, Yu-Chen if ((PageBuffer0 == NULL) || (PageBuffer1 == NULL)) { 196033842cedSCho, Yu-Chen result = MS_NO_MEMORY_ERROR; 196133842cedSCho, Yu-Chen goto exit; 196233842cedSCho, Yu-Chen } 196333842cedSCho, Yu-Chen 196433842cedSCho, Yu-Chen btBlk1st = btBlk2nd = MS_LB_NOT_USED; 196533842cedSCho, Yu-Chen btBlk1stErred = 0; 196633842cedSCho, Yu-Chen 196733842cedSCho, Yu-Chen for (TmpBlock = 0; TmpBlock < MS_MAX_INITIAL_ERROR_BLOCKS+2; TmpBlock++) { 196833842cedSCho, Yu-Chen 196933842cedSCho, Yu-Chen switch (ms_read_readpage(us, TmpBlock, 0, (u32 *)PageBuffer0, &extdat)) { 197033842cedSCho, Yu-Chen case MS_STATUS_SUCCESS: 197133842cedSCho, Yu-Chen break; 197233842cedSCho, Yu-Chen case MS_STATUS_INT_ERROR: 197333842cedSCho, Yu-Chen break; 197433842cedSCho, Yu-Chen case MS_STATUS_ERROR: 197533842cedSCho, Yu-Chen default: 197633842cedSCho, Yu-Chen continue; 197733842cedSCho, Yu-Chen } 197833842cedSCho, Yu-Chen 197933842cedSCho, Yu-Chen if ((extdat.ovrflg & MS_REG_OVR_BKST) == MS_REG_OVR_BKST_NG) 198033842cedSCho, Yu-Chen continue; 198133842cedSCho, Yu-Chen 198233842cedSCho, Yu-Chen if (((extdat.mngflg & MS_REG_MNG_SYSFLG) == MS_REG_MNG_SYSFLG_USER) || 198333842cedSCho, Yu-Chen (be16_to_cpu(((struct ms_bootblock_page0 *)PageBuffer0)->header.wBlockID) != MS_BOOT_BLOCK_ID) || 198433842cedSCho, Yu-Chen (be16_to_cpu(((struct ms_bootblock_page0 *)PageBuffer0)->header.wFormatVersion) != MS_BOOT_BLOCK_FORMAT_VERSION) || 198533842cedSCho, Yu-Chen (((struct ms_bootblock_page0 *)PageBuffer0)->header.bNumberOfDataEntry != MS_BOOT_BLOCK_DATA_ENTRIES)) 198633842cedSCho, Yu-Chen continue; 198733842cedSCho, Yu-Chen 198833842cedSCho, Yu-Chen if (btBlk1st != MS_LB_NOT_USED) { 198933842cedSCho, Yu-Chen btBlk2nd = TmpBlock; 199033842cedSCho, Yu-Chen break; 199133842cedSCho, Yu-Chen } 199233842cedSCho, Yu-Chen 199333842cedSCho, Yu-Chen btBlk1st = TmpBlock; 199433842cedSCho, Yu-Chen memcpy(PageBuffer1, PageBuffer0, MS_BYTES_PER_PAGE); 199533842cedSCho, Yu-Chen if (extdat.status1 & (MS_REG_ST1_DTER | MS_REG_ST1_EXER | MS_REG_ST1_FGER)) 199633842cedSCho, Yu-Chen btBlk1stErred = 1; 199733842cedSCho, Yu-Chen } 199833842cedSCho, Yu-Chen 199933842cedSCho, Yu-Chen if (btBlk1st == MS_LB_NOT_USED) { 200033842cedSCho, Yu-Chen result = MS_STATUS_ERROR; 200133842cedSCho, Yu-Chen goto exit; 200233842cedSCho, Yu-Chen } 200333842cedSCho, Yu-Chen 200433842cedSCho, Yu-Chen /* write protect */ 200533842cedSCho, Yu-Chen if ((extdat.status0 & MS_REG_ST0_WP) == MS_REG_ST0_WP_ON) 200633842cedSCho, Yu-Chen ms_lib_ctrl_set(info, MS_LIB_CTRL_WRPROTECT); 200733842cedSCho, Yu-Chen 200833842cedSCho, Yu-Chen result = MS_STATUS_ERROR; 200933842cedSCho, Yu-Chen /* 1st Boot Block */ 201033842cedSCho, Yu-Chen if (btBlk1stErred == 0) 201133842cedSCho, Yu-Chen result = ms_lib_process_bootblock(us, btBlk1st, PageBuffer1); 201233842cedSCho, Yu-Chen /* 1st */ 201333842cedSCho, Yu-Chen /* 2nd Boot Block */ 201433842cedSCho, Yu-Chen if (result && (btBlk2nd != MS_LB_NOT_USED)) 201533842cedSCho, Yu-Chen result = ms_lib_process_bootblock(us, btBlk2nd, PageBuffer0); 201633842cedSCho, Yu-Chen 201733842cedSCho, Yu-Chen if (result) { 201833842cedSCho, Yu-Chen result = MS_STATUS_ERROR; 201933842cedSCho, Yu-Chen goto exit; 202033842cedSCho, Yu-Chen } 202133842cedSCho, Yu-Chen 202233842cedSCho, Yu-Chen for (TmpBlock = 0; TmpBlock < btBlk1st; TmpBlock++) 202333842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR; 202433842cedSCho, Yu-Chen 202533842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap[btBlk1st] = MS_LB_BOOT_BLOCK; 202633842cedSCho, Yu-Chen 202733842cedSCho, Yu-Chen if (btBlk2nd != MS_LB_NOT_USED) { 202833842cedSCho, Yu-Chen for (TmpBlock = btBlk1st + 1; TmpBlock < btBlk2nd; TmpBlock++) 202933842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR; 203033842cedSCho, Yu-Chen 203133842cedSCho, Yu-Chen info->MS_Lib.Phy2LogMap[btBlk2nd] = MS_LB_BOOT_BLOCK; 203233842cedSCho, Yu-Chen } 203333842cedSCho, Yu-Chen 203433842cedSCho, Yu-Chen result = ms_lib_scan_logicalblocknumber(us, btBlk1st); 203533842cedSCho, Yu-Chen if (result) 203633842cedSCho, Yu-Chen goto exit; 203733842cedSCho, Yu-Chen 203833842cedSCho, Yu-Chen for (TmpBlock = MS_PHYSICAL_BLOCKS_PER_SEGMENT; 203933842cedSCho, Yu-Chen TmpBlock < info->MS_Lib.NumberOfPhyBlock; 204033842cedSCho, Yu-Chen TmpBlock += MS_PHYSICAL_BLOCKS_PER_SEGMENT) { 204133842cedSCho, Yu-Chen if (ms_count_freeblock(us, TmpBlock) == 0) { 204233842cedSCho, Yu-Chen ms_lib_ctrl_set(info, MS_LIB_CTRL_WRPROTECT); 204333842cedSCho, Yu-Chen break; 204433842cedSCho, Yu-Chen } 204533842cedSCho, Yu-Chen } 204633842cedSCho, Yu-Chen 204733842cedSCho, Yu-Chen /* write */ 204833842cedSCho, Yu-Chen if (ms_lib_alloc_writebuf(us)) { 204933842cedSCho, Yu-Chen result = MS_NO_MEMORY_ERROR; 205033842cedSCho, Yu-Chen goto exit; 205133842cedSCho, Yu-Chen } 205233842cedSCho, Yu-Chen 205333842cedSCho, Yu-Chen result = MS_STATUS_SUCCESS; 205433842cedSCho, Yu-Chen 205533842cedSCho, Yu-Chen exit: 205633842cedSCho, Yu-Chen kfree(PageBuffer1); 205733842cedSCho, Yu-Chen kfree(PageBuffer0); 205833842cedSCho, Yu-Chen 205933842cedSCho, Yu-Chen printk(KERN_INFO "MS_CardInit end\n"); 206033842cedSCho, Yu-Chen return result; 206133842cedSCho, Yu-Chen } 206233842cedSCho, Yu-Chen 206333842cedSCho, Yu-Chen static int ene_ms_init(struct us_data *us) 206433842cedSCho, Yu-Chen { 206533842cedSCho, Yu-Chen struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 206633842cedSCho, Yu-Chen int result; 206733842cedSCho, Yu-Chen u8 buf[0x200]; 206833842cedSCho, Yu-Chen u16 MSP_BlockSize, MSP_UserAreaBlocks; 206933842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 207033842cedSCho, Yu-Chen 207133842cedSCho, Yu-Chen printk(KERN_INFO "transport --- ENE_MSInit\n"); 207233842cedSCho, Yu-Chen 207333842cedSCho, Yu-Chen /* the same part to test ENE */ 207433842cedSCho, Yu-Chen 207533842cedSCho, Yu-Chen result = ene_load_bincode(us, MS_INIT_PATTERN); 207633842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) { 207733842cedSCho, Yu-Chen printk(KERN_ERR "Load MS Init Code Fail !!\n"); 207833842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 207933842cedSCho, Yu-Chen } 208033842cedSCho, Yu-Chen 208133842cedSCho, Yu-Chen memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 208233842cedSCho, Yu-Chen bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 208333842cedSCho, Yu-Chen bcb->DataTransferLength = 0x200; 2084b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 208533842cedSCho, Yu-Chen bcb->CDB[0] = 0xF1; 208633842cedSCho, Yu-Chen bcb->CDB[1] = 0x01; 208733842cedSCho, Yu-Chen 208833842cedSCho, Yu-Chen result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); 208933842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) { 209033842cedSCho, Yu-Chen printk(KERN_ERR "Execution MS Init Code Fail !!\n"); 209133842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 209233842cedSCho, Yu-Chen } 209333842cedSCho, Yu-Chen /* the same part to test ENE */ 209433842cedSCho, Yu-Chen info->MS_Status = *(struct MS_STATUS *)&buf[0]; 209533842cedSCho, Yu-Chen 209633842cedSCho, Yu-Chen if (info->MS_Status.Insert && info->MS_Status.Ready) { 209733842cedSCho, Yu-Chen printk(KERN_INFO "Insert = %x\n", info->MS_Status.Insert); 209833842cedSCho, Yu-Chen printk(KERN_INFO "Ready = %x\n", info->MS_Status.Ready); 209933842cedSCho, Yu-Chen printk(KERN_INFO "IsMSPro = %x\n", info->MS_Status.IsMSPro); 210033842cedSCho, Yu-Chen printk(KERN_INFO "IsMSPHG = %x\n", info->MS_Status.IsMSPHG); 210133842cedSCho, Yu-Chen printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP); 210233842cedSCho, Yu-Chen if (info->MS_Status.IsMSPro) { 210333842cedSCho, Yu-Chen MSP_BlockSize = (buf[6] << 8) | buf[7]; 210433842cedSCho, Yu-Chen MSP_UserAreaBlocks = (buf[10] << 8) | buf[11]; 210533842cedSCho, Yu-Chen info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks; 210633842cedSCho, Yu-Chen } else { 210733842cedSCho, Yu-Chen ms_card_init(us); /* Card is MS (to ms.c)*/ 210833842cedSCho, Yu-Chen } 2109191648d0SJoe Perches usb_stor_dbg(us, "MS Init Code OK !!\n"); 211033842cedSCho, Yu-Chen } else { 2111191648d0SJoe Perches usb_stor_dbg(us, "MS Card Not Ready --- %x\n", buf[0]); 211233842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 211333842cedSCho, Yu-Chen } 211433842cedSCho, Yu-Chen 211533842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_GOOD; 211633842cedSCho, Yu-Chen } 211733842cedSCho, Yu-Chen 211841e568d1Shuajun li static int ene_sd_init(struct us_data *us) 211941e568d1Shuajun li { 212041e568d1Shuajun li int result; 212141e568d1Shuajun li u8 buf[0x200]; 212241e568d1Shuajun li struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 212341e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 212441e568d1Shuajun li 2125191648d0SJoe Perches usb_stor_dbg(us, "transport --- ENE_SDInit\n"); 212641e568d1Shuajun li /* SD Init Part-1 */ 212741e568d1Shuajun li result = ene_load_bincode(us, SD_INIT1_PATTERN); 212841e568d1Shuajun li if (result != USB_STOR_XFER_GOOD) { 2129191648d0SJoe Perches usb_stor_dbg(us, "Load SD Init Code Part-1 Fail !!\n"); 213041e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 213141e568d1Shuajun li } 213241e568d1Shuajun li 213341e568d1Shuajun li memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 213441e568d1Shuajun li bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 2135b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 213641e568d1Shuajun li bcb->CDB[0] = 0xF2; 213741e568d1Shuajun li 213841e568d1Shuajun li result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0); 213941e568d1Shuajun li if (result != USB_STOR_XFER_GOOD) { 2140191648d0SJoe Perches usb_stor_dbg(us, "Execution SD Init Code Fail !!\n"); 214141e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 214241e568d1Shuajun li } 214341e568d1Shuajun li 214441e568d1Shuajun li /* SD Init Part-2 */ 214541e568d1Shuajun li result = ene_load_bincode(us, SD_INIT2_PATTERN); 214641e568d1Shuajun li if (result != USB_STOR_XFER_GOOD) { 2147191648d0SJoe Perches usb_stor_dbg(us, "Load SD Init Code Part-2 Fail !!\n"); 214841e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 214941e568d1Shuajun li } 215041e568d1Shuajun li 215141e568d1Shuajun li memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 215241e568d1Shuajun li bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 215341e568d1Shuajun li bcb->DataTransferLength = 0x200; 2154b8db6d64SSebastian Andrzej Siewior bcb->Flags = US_BULK_FLAG_IN; 215541e568d1Shuajun li bcb->CDB[0] = 0xF1; 215641e568d1Shuajun li 215741e568d1Shuajun li result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); 215841e568d1Shuajun li if (result != USB_STOR_XFER_GOOD) { 2159191648d0SJoe Perches usb_stor_dbg(us, "Execution SD Init Code Fail !!\n"); 216041e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 216141e568d1Shuajun li } 216241e568d1Shuajun li 216341e568d1Shuajun li info->SD_Status = *(struct SD_STATUS *)&buf[0]; 216441e568d1Shuajun li if (info->SD_Status.Insert && info->SD_Status.Ready) { 2165191648d0SJoe Perches struct SD_STATUS *s = &info->SD_Status; 2166191648d0SJoe Perches 216741e568d1Shuajun li ene_get_card_status(us, (unsigned char *)&buf); 2168191648d0SJoe Perches usb_stor_dbg(us, "Insert = %x\n", s->Insert); 2169191648d0SJoe Perches usb_stor_dbg(us, "Ready = %x\n", s->Ready); 2170191648d0SJoe Perches usb_stor_dbg(us, "IsMMC = %x\n", s->IsMMC); 2171191648d0SJoe Perches usb_stor_dbg(us, "HiCapacity = %x\n", s->HiCapacity); 2172191648d0SJoe Perches usb_stor_dbg(us, "HiSpeed = %x\n", s->HiSpeed); 2173191648d0SJoe Perches usb_stor_dbg(us, "WtP = %x\n", s->WtP); 217441e568d1Shuajun li } else { 2175191648d0SJoe Perches usb_stor_dbg(us, "SD Card Not Ready --- %x\n", buf[0]); 217641e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 217741e568d1Shuajun li } 217841e568d1Shuajun li return USB_STOR_TRANSPORT_GOOD; 217941e568d1Shuajun li } 218041e568d1Shuajun li 218141e568d1Shuajun li 218241e568d1Shuajun li static int ene_init(struct us_data *us) 218341e568d1Shuajun li { 218441e568d1Shuajun li int result; 218541e568d1Shuajun li u8 misc_reg03 = 0; 218641e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); 218741e568d1Shuajun li 218841e568d1Shuajun li result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); 218941e568d1Shuajun li if (result != USB_STOR_XFER_GOOD) 219041e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 219141e568d1Shuajun li 219241e568d1Shuajun li if (misc_reg03 & 0x01) { 219341e568d1Shuajun li if (!info->SD_Status.Ready) { 219441e568d1Shuajun li result = ene_sd_init(us); 219541e568d1Shuajun li if (result != USB_STOR_XFER_GOOD) 219641e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 219741e568d1Shuajun li } 219841e568d1Shuajun li } 219933842cedSCho, Yu-Chen if (misc_reg03 & 0x02) { 220033842cedSCho, Yu-Chen if (!info->MS_Status.Ready) { 220133842cedSCho, Yu-Chen result = ene_ms_init(us); 220233842cedSCho, Yu-Chen if (result != USB_STOR_XFER_GOOD) 220333842cedSCho, Yu-Chen return USB_STOR_TRANSPORT_ERROR; 220433842cedSCho, Yu-Chen } 220533842cedSCho, Yu-Chen } 220641e568d1Shuajun li return result; 220741e568d1Shuajun li } 220841e568d1Shuajun li 220941e568d1Shuajun li /*----- sd_scsi_irp() ---------*/ 221041e568d1Shuajun li static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb) 221141e568d1Shuajun li { 221241e568d1Shuajun li int result; 221341e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra; 221441e568d1Shuajun li 221541e568d1Shuajun li info->SrbStatus = SS_SUCCESS; 221641e568d1Shuajun li switch (srb->cmnd[0]) { 221741e568d1Shuajun li case TEST_UNIT_READY: 221841e568d1Shuajun li result = sd_scsi_test_unit_ready(us, srb); 221941e568d1Shuajun li break; /* 0x00 */ 222041e568d1Shuajun li case INQUIRY: 222141e568d1Shuajun li result = sd_scsi_inquiry(us, srb); 222241e568d1Shuajun li break; /* 0x12 */ 222341e568d1Shuajun li case MODE_SENSE: 222441e568d1Shuajun li result = sd_scsi_mode_sense(us, srb); 222541e568d1Shuajun li break; /* 0x1A */ 222641e568d1Shuajun li /* 222741e568d1Shuajun li case START_STOP: 222841e568d1Shuajun li result = SD_SCSI_Start_Stop(us, srb); 222941e568d1Shuajun li break; //0x1B 223041e568d1Shuajun li */ 223141e568d1Shuajun li case READ_CAPACITY: 223241e568d1Shuajun li result = sd_scsi_read_capacity(us, srb); 223341e568d1Shuajun li break; /* 0x25 */ 223441e568d1Shuajun li case READ_10: 223541e568d1Shuajun li result = sd_scsi_read(us, srb); 223641e568d1Shuajun li break; /* 0x28 */ 223741e568d1Shuajun li case WRITE_10: 223841e568d1Shuajun li result = sd_scsi_write(us, srb); 223941e568d1Shuajun li break; /* 0x2A */ 224041e568d1Shuajun li default: 224141e568d1Shuajun li info->SrbStatus = SS_ILLEGAL_REQUEST; 224241e568d1Shuajun li result = USB_STOR_TRANSPORT_FAILED; 224341e568d1Shuajun li break; 224441e568d1Shuajun li } 224541e568d1Shuajun li return result; 224641e568d1Shuajun li } 224741e568d1Shuajun li 224833842cedSCho, Yu-Chen /* 224933842cedSCho, Yu-Chen * ms_scsi_irp() 225033842cedSCho, Yu-Chen */ 225136f3a14dSFelipe Balbi static int ms_scsi_irp(struct us_data *us, struct scsi_cmnd *srb) 225233842cedSCho, Yu-Chen { 225333842cedSCho, Yu-Chen int result; 225433842cedSCho, Yu-Chen struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra; 225533842cedSCho, Yu-Chen info->SrbStatus = SS_SUCCESS; 225633842cedSCho, Yu-Chen switch (srb->cmnd[0]) { 225733842cedSCho, Yu-Chen case TEST_UNIT_READY: 225833842cedSCho, Yu-Chen result = ms_scsi_test_unit_ready(us, srb); 225933842cedSCho, Yu-Chen break; /* 0x00 */ 226033842cedSCho, Yu-Chen case INQUIRY: 226133842cedSCho, Yu-Chen result = ms_scsi_inquiry(us, srb); 226233842cedSCho, Yu-Chen break; /* 0x12 */ 226333842cedSCho, Yu-Chen case MODE_SENSE: 226433842cedSCho, Yu-Chen result = ms_scsi_mode_sense(us, srb); 226533842cedSCho, Yu-Chen break; /* 0x1A */ 226633842cedSCho, Yu-Chen case READ_CAPACITY: 226733842cedSCho, Yu-Chen result = ms_scsi_read_capacity(us, srb); 226833842cedSCho, Yu-Chen break; /* 0x25 */ 226933842cedSCho, Yu-Chen case READ_10: 227033842cedSCho, Yu-Chen result = ms_scsi_read(us, srb); 227133842cedSCho, Yu-Chen break; /* 0x28 */ 227233842cedSCho, Yu-Chen case WRITE_10: 227333842cedSCho, Yu-Chen result = ms_scsi_write(us, srb); 227433842cedSCho, Yu-Chen break; /* 0x2A */ 227533842cedSCho, Yu-Chen default: 227633842cedSCho, Yu-Chen info->SrbStatus = SS_ILLEGAL_REQUEST; 227733842cedSCho, Yu-Chen result = USB_STOR_TRANSPORT_FAILED; 227833842cedSCho, Yu-Chen break; 227933842cedSCho, Yu-Chen } 228033842cedSCho, Yu-Chen return result; 228133842cedSCho, Yu-Chen } 228233842cedSCho, Yu-Chen 228341e568d1Shuajun li static int ene_transport(struct scsi_cmnd *srb, struct us_data *us) 228441e568d1Shuajun li { 22854b309f1cSAlan Stern int result = USB_STOR_XFER_GOOD; 228641e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); 228741e568d1Shuajun li 2288191648d0SJoe Perches /*US_DEBUG(usb_stor_show_command(us, srb)); */ 228941e568d1Shuajun li scsi_set_resid(srb, 0); 22904b309f1cSAlan Stern if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready))) 229141e568d1Shuajun li result = ene_init(us); 22924b309f1cSAlan Stern if (result == USB_STOR_XFER_GOOD) { 22934b309f1cSAlan Stern result = USB_STOR_TRANSPORT_ERROR; 229433842cedSCho, Yu-Chen if (info->SD_Status.Ready) 229541e568d1Shuajun li result = sd_scsi_irp(us, srb); 229641e568d1Shuajun li 229733842cedSCho, Yu-Chen if (info->MS_Status.Ready) 229833842cedSCho, Yu-Chen result = ms_scsi_irp(us, srb); 229933842cedSCho, Yu-Chen } 23004b309f1cSAlan Stern return result; 230141e568d1Shuajun li } 230241e568d1Shuajun li 2303aa519be3SAkinobu Mita static struct scsi_host_template ene_ub6250_host_template; 230441e568d1Shuajun li 230541e568d1Shuajun li static int ene_ub6250_probe(struct usb_interface *intf, 230641e568d1Shuajun li const struct usb_device_id *id) 230741e568d1Shuajun li { 230841e568d1Shuajun li int result; 230941e568d1Shuajun li u8 misc_reg03 = 0; 231041e568d1Shuajun li struct us_data *us; 231141e568d1Shuajun li 231241e568d1Shuajun li result = usb_stor_probe1(&us, intf, id, 2313aa519be3SAkinobu Mita (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list, 2314aa519be3SAkinobu Mita &ene_ub6250_host_template); 231541e568d1Shuajun li if (result) 231641e568d1Shuajun li return result; 231741e568d1Shuajun li 231841e568d1Shuajun li /* FIXME: where should the code alloc extra buf ? */ 231941e568d1Shuajun li if (!us->extra) { 232041e568d1Shuajun li us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL); 232141e568d1Shuajun li if (!us->extra) 232241e568d1Shuajun li return -ENOMEM; 232341e568d1Shuajun li us->extra_destructor = ene_ub6250_info_destructor; 232441e568d1Shuajun li } 232541e568d1Shuajun li 232641e568d1Shuajun li us->transport_name = "ene_ub6250"; 232741e568d1Shuajun li us->transport = ene_transport; 232841e568d1Shuajun li us->max_lun = 0; 232941e568d1Shuajun li 233041e568d1Shuajun li result = usb_stor_probe2(us); 233141e568d1Shuajun li if (result) 233241e568d1Shuajun li return result; 233341e568d1Shuajun li 233441e568d1Shuajun li /* probe card type */ 233541e568d1Shuajun li result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); 233641e568d1Shuajun li if (result != USB_STOR_XFER_GOOD) { 233741e568d1Shuajun li usb_stor_disconnect(intf); 233841e568d1Shuajun li return USB_STOR_TRANSPORT_ERROR; 233941e568d1Shuajun li } 234041e568d1Shuajun li 234141e568d1Shuajun li if (!(misc_reg03 & 0x01)) { 234216fae052SKristina Martšenko pr_info("ums_eneub6250: This driver only supports SD/MS cards. " 234316fae052SKristina Martšenko "It does not support SM cards.\n"); 234441e568d1Shuajun li } 234541e568d1Shuajun li 234641e568d1Shuajun li return result; 234741e568d1Shuajun li } 234841e568d1Shuajun li 234941e568d1Shuajun li 235041e568d1Shuajun li #ifdef CONFIG_PM 235141e568d1Shuajun li 235241e568d1Shuajun li static int ene_ub6250_resume(struct usb_interface *iface) 235341e568d1Shuajun li { 235441e568d1Shuajun li u8 tmp = 0; 235541e568d1Shuajun li struct us_data *us = usb_get_intfdata(iface); 235641e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); 235741e568d1Shuajun li 235841e568d1Shuajun li mutex_lock(&us->dev_mutex); 235941e568d1Shuajun li 236041e568d1Shuajun li if (us->suspend_resume_hook) 236141e568d1Shuajun li (us->suspend_resume_hook)(us, US_RESUME); 236241e568d1Shuajun li 236341e568d1Shuajun li mutex_unlock(&us->dev_mutex); 236441e568d1Shuajun li 236541e568d1Shuajun li info->Power_IsResum = true; 236641e568d1Shuajun li /*info->SD_Status.Ready = 0; */ 236741e568d1Shuajun li info->SD_Status = *(struct SD_STATUS *)&tmp; 236841e568d1Shuajun li info->MS_Status = *(struct MS_STATUS *)&tmp; 236941e568d1Shuajun li info->SM_Status = *(struct SM_STATUS *)&tmp; 237041e568d1Shuajun li 237141e568d1Shuajun li return 0; 237241e568d1Shuajun li } 237341e568d1Shuajun li 237441e568d1Shuajun li static int ene_ub6250_reset_resume(struct usb_interface *iface) 237541e568d1Shuajun li { 237641e568d1Shuajun li u8 tmp = 0; 237741e568d1Shuajun li struct us_data *us = usb_get_intfdata(iface); 237841e568d1Shuajun li struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); 2379191648d0SJoe Perches 238041e568d1Shuajun li /* Report the reset to the SCSI core */ 238141e568d1Shuajun li usb_stor_reset_resume(iface); 238241e568d1Shuajun li 2383f0183a33SFelipe Balbi /* 2384f0183a33SFelipe Balbi * FIXME: Notify the subdrivers that they need to reinitialize 2385f0183a33SFelipe Balbi * the device 2386f0183a33SFelipe Balbi */ 238741e568d1Shuajun li info->Power_IsResum = true; 238841e568d1Shuajun li /*info->SD_Status.Ready = 0; */ 238941e568d1Shuajun li info->SD_Status = *(struct SD_STATUS *)&tmp; 239041e568d1Shuajun li info->MS_Status = *(struct MS_STATUS *)&tmp; 239141e568d1Shuajun li info->SM_Status = *(struct SM_STATUS *)&tmp; 239241e568d1Shuajun li 239341e568d1Shuajun li return 0; 239441e568d1Shuajun li } 239541e568d1Shuajun li 239641e568d1Shuajun li #else 239741e568d1Shuajun li 239841e568d1Shuajun li #define ene_ub6250_resume NULL 239941e568d1Shuajun li #define ene_ub6250_reset_resume NULL 240041e568d1Shuajun li 240141e568d1Shuajun li #endif 240241e568d1Shuajun li 240341e568d1Shuajun li static struct usb_driver ene_ub6250_driver = { 2404aa519be3SAkinobu Mita .name = DRV_NAME, 240541e568d1Shuajun li .probe = ene_ub6250_probe, 240641e568d1Shuajun li .disconnect = usb_stor_disconnect, 240741e568d1Shuajun li .suspend = usb_stor_suspend, 240841e568d1Shuajun li .resume = ene_ub6250_resume, 240941e568d1Shuajun li .reset_resume = ene_ub6250_reset_resume, 241041e568d1Shuajun li .pre_reset = usb_stor_pre_reset, 241141e568d1Shuajun li .post_reset = usb_stor_post_reset, 241241e568d1Shuajun li .id_table = ene_ub6250_usb_ids, 241341e568d1Shuajun li .soft_unbind = 1, 2414e73b2db6SHuajun Li .no_dynamic_id = 1, 241541e568d1Shuajun li }; 241641e568d1Shuajun li 2417aa519be3SAkinobu Mita module_usb_stor_driver(ene_ub6250_driver, ene_ub6250_host_template, DRV_NAME); 2418