18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 38c2ecf20Sopenharmony_ci#include <linux/errno.h> 48c2ecf20Sopenharmony_ci#include <linux/module.h> 58c2ecf20Sopenharmony_ci#include <linux/slab.h> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <scsi/scsi.h> 88c2ecf20Sopenharmony_ci#include <scsi/scsi_cmnd.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/firmware.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "usb.h" 138c2ecf20Sopenharmony_ci#include "transport.h" 148c2ecf20Sopenharmony_ci#include "protocol.h" 158c2ecf20Sopenharmony_ci#include "debug.h" 168c2ecf20Sopenharmony_ci#include "scsiglue.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define SD_INIT1_FIRMWARE "ene-ub6250/sd_init1.bin" 198c2ecf20Sopenharmony_ci#define SD_INIT2_FIRMWARE "ene-ub6250/sd_init2.bin" 208c2ecf20Sopenharmony_ci#define SD_RW_FIRMWARE "ene-ub6250/sd_rdwr.bin" 218c2ecf20Sopenharmony_ci#define MS_INIT_FIRMWARE "ene-ub6250/ms_init.bin" 228c2ecf20Sopenharmony_ci#define MSP_RW_FIRMWARE "ene-ub6250/msp_rdwr.bin" 238c2ecf20Sopenharmony_ci#define MS_RW_FIRMWARE "ene-ub6250/ms_rdwr.bin" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define DRV_NAME "ums_eneub6250" 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Driver for ENE UB6250 reader"); 288c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 298c2ecf20Sopenharmony_ciMODULE_IMPORT_NS(USB_STORAGE); 308c2ecf20Sopenharmony_ciMODULE_FIRMWARE(SD_INIT1_FIRMWARE); 318c2ecf20Sopenharmony_ciMODULE_FIRMWARE(SD_INIT2_FIRMWARE); 328c2ecf20Sopenharmony_ciMODULE_FIRMWARE(SD_RW_FIRMWARE); 338c2ecf20Sopenharmony_ciMODULE_FIRMWARE(MS_INIT_FIRMWARE); 348c2ecf20Sopenharmony_ciMODULE_FIRMWARE(MSP_RW_FIRMWARE); 358c2ecf20Sopenharmony_ciMODULE_FIRMWARE(MS_RW_FIRMWARE); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci/* 388c2ecf20Sopenharmony_ci * The table of devices 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_ci#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ 418c2ecf20Sopenharmony_ci vendorName, productName, useProtocol, useTransport, \ 428c2ecf20Sopenharmony_ci initFunction, flags) \ 438c2ecf20Sopenharmony_ci{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ 448c2ecf20Sopenharmony_ci .driver_info = (flags)} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic struct usb_device_id ene_ub6250_usb_ids[] = { 478c2ecf20Sopenharmony_ci# include "unusual_ene_ub6250.h" 488c2ecf20Sopenharmony_ci { } /* Terminating entry */ 498c2ecf20Sopenharmony_ci}; 508c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, ene_ub6250_usb_ids); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#undef UNUSUAL_DEV 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/* 558c2ecf20Sopenharmony_ci * The flags table 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_ci#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ 588c2ecf20Sopenharmony_ci vendor_name, product_name, use_protocol, use_transport, \ 598c2ecf20Sopenharmony_ci init_function, Flags) \ 608c2ecf20Sopenharmony_ci{ \ 618c2ecf20Sopenharmony_ci .vendorName = vendor_name, \ 628c2ecf20Sopenharmony_ci .productName = product_name, \ 638c2ecf20Sopenharmony_ci .useProtocol = use_protocol, \ 648c2ecf20Sopenharmony_ci .useTransport = use_transport, \ 658c2ecf20Sopenharmony_ci .initFunction = init_function, \ 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic struct us_unusual_dev ene_ub6250_unusual_dev_list[] = { 698c2ecf20Sopenharmony_ci# include "unusual_ene_ub6250.h" 708c2ecf20Sopenharmony_ci { } /* Terminating entry */ 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#undef UNUSUAL_DEV 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* ENE bin code len */ 788c2ecf20Sopenharmony_ci#define ENE_BIN_CODE_LEN 0x800 798c2ecf20Sopenharmony_ci/* EnE HW Register */ 808c2ecf20Sopenharmony_ci#define REG_CARD_STATUS 0xFF83 818c2ecf20Sopenharmony_ci#define REG_HW_TRAP1 0xFF89 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* SRB Status */ 848c2ecf20Sopenharmony_ci#define SS_SUCCESS 0x000000 /* No Sense */ 858c2ecf20Sopenharmony_ci#define SS_NOT_READY 0x023A00 /* Medium not present */ 868c2ecf20Sopenharmony_ci#define SS_MEDIUM_ERR 0x031100 /* Unrecovered read error */ 878c2ecf20Sopenharmony_ci#define SS_HW_ERR 0x040800 /* Communication failure */ 888c2ecf20Sopenharmony_ci#define SS_ILLEGAL_REQUEST 0x052000 /* Invalid command */ 898c2ecf20Sopenharmony_ci#define SS_UNIT_ATTENTION 0x062900 /* Reset occurred */ 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/* ENE Load FW Pattern */ 928c2ecf20Sopenharmony_ci#define SD_INIT1_PATTERN 1 938c2ecf20Sopenharmony_ci#define SD_INIT2_PATTERN 2 948c2ecf20Sopenharmony_ci#define SD_RW_PATTERN 3 958c2ecf20Sopenharmony_ci#define MS_INIT_PATTERN 4 968c2ecf20Sopenharmony_ci#define MSP_RW_PATTERN 5 978c2ecf20Sopenharmony_ci#define MS_RW_PATTERN 6 988c2ecf20Sopenharmony_ci#define SM_INIT_PATTERN 7 998c2ecf20Sopenharmony_ci#define SM_RW_PATTERN 8 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#define FDIR_WRITE 0 1028c2ecf20Sopenharmony_ci#define FDIR_READ 1 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/* For MS Card */ 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* Status Register 1 */ 1078c2ecf20Sopenharmony_ci#define MS_REG_ST1_MB 0x80 /* media busy */ 1088c2ecf20Sopenharmony_ci#define MS_REG_ST1_FB1 0x40 /* flush busy 1 */ 1098c2ecf20Sopenharmony_ci#define MS_REG_ST1_DTER 0x20 /* error on data(corrected) */ 1108c2ecf20Sopenharmony_ci#define MS_REG_ST1_UCDT 0x10 /* unable to correct data */ 1118c2ecf20Sopenharmony_ci#define MS_REG_ST1_EXER 0x08 /* error on extra(corrected) */ 1128c2ecf20Sopenharmony_ci#define MS_REG_ST1_UCEX 0x04 /* unable to correct extra */ 1138c2ecf20Sopenharmony_ci#define MS_REG_ST1_FGER 0x02 /* error on overwrite flag(corrected) */ 1148c2ecf20Sopenharmony_ci#define MS_REG_ST1_UCFG 0x01 /* unable to correct overwrite flag */ 1158c2ecf20Sopenharmony_ci#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) 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci/* Overwrite Area */ 1188c2ecf20Sopenharmony_ci#define MS_REG_OVR_BKST 0x80 /* block status */ 1198c2ecf20Sopenharmony_ci#define MS_REG_OVR_BKST_OK MS_REG_OVR_BKST /* OK */ 1208c2ecf20Sopenharmony_ci#define MS_REG_OVR_BKST_NG 0x00 /* NG */ 1218c2ecf20Sopenharmony_ci#define MS_REG_OVR_PGST0 0x40 /* page status */ 1228c2ecf20Sopenharmony_ci#define MS_REG_OVR_PGST1 0x20 1238c2ecf20Sopenharmony_ci#define MS_REG_OVR_PGST_MASK (MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1) 1248c2ecf20Sopenharmony_ci#define MS_REG_OVR_PGST_OK (MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1) /* OK */ 1258c2ecf20Sopenharmony_ci#define MS_REG_OVR_PGST_NG MS_REG_OVR_PGST1 /* NG */ 1268c2ecf20Sopenharmony_ci#define MS_REG_OVR_PGST_DATA_ERROR 0x00 /* data error */ 1278c2ecf20Sopenharmony_ci#define MS_REG_OVR_UDST 0x10 /* update status */ 1288c2ecf20Sopenharmony_ci#define MS_REG_OVR_UDST_UPDATING 0x00 /* updating */ 1298c2ecf20Sopenharmony_ci#define MS_REG_OVR_UDST_NO_UPDATE MS_REG_OVR_UDST 1308c2ecf20Sopenharmony_ci#define MS_REG_OVR_RESERVED 0x08 1318c2ecf20Sopenharmony_ci#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) 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/* Management Flag */ 1348c2ecf20Sopenharmony_ci#define MS_REG_MNG_SCMS0 0x20 /* serial copy management system */ 1358c2ecf20Sopenharmony_ci#define MS_REG_MNG_SCMS1 0x10 1368c2ecf20Sopenharmony_ci#define MS_REG_MNG_SCMS_MASK (MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1) 1378c2ecf20Sopenharmony_ci#define MS_REG_MNG_SCMS_COPY_OK (MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1) 1388c2ecf20Sopenharmony_ci#define MS_REG_MNG_SCMS_ONE_COPY MS_REG_MNG_SCMS1 1398c2ecf20Sopenharmony_ci#define MS_REG_MNG_SCMS_NO_COPY 0x00 1408c2ecf20Sopenharmony_ci#define MS_REG_MNG_ATFLG 0x08 /* address transfer table flag */ 1418c2ecf20Sopenharmony_ci#define MS_REG_MNG_ATFLG_OTHER MS_REG_MNG_ATFLG /* other */ 1428c2ecf20Sopenharmony_ci#define MS_REG_MNG_ATFLG_ATTBL 0x00 /* address transfer table */ 1438c2ecf20Sopenharmony_ci#define MS_REG_MNG_SYSFLG 0x04 /* system flag */ 1448c2ecf20Sopenharmony_ci#define MS_REG_MNG_SYSFLG_USER MS_REG_MNG_SYSFLG /* user block */ 1458c2ecf20Sopenharmony_ci#define MS_REG_MNG_SYSFLG_BOOT 0x00 /* system block */ 1468c2ecf20Sopenharmony_ci#define MS_REG_MNG_RESERVED 0xc3 1478c2ecf20Sopenharmony_ci#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) 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci#define MS_MAX_PAGES_PER_BLOCK 32 1518c2ecf20Sopenharmony_ci#define MS_MAX_INITIAL_ERROR_BLOCKS 10 1528c2ecf20Sopenharmony_ci#define MS_LIB_BITS_PER_BYTE 8 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci#define MS_SYSINF_FORMAT_FAT 1 1558c2ecf20Sopenharmony_ci#define MS_SYSINF_USAGE_GENERAL 0 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci#define MS_SYSINF_MSCLASS_TYPE_1 1 1588c2ecf20Sopenharmony_ci#define MS_SYSINF_PAGE_SIZE MS_BYTES_PER_PAGE /* fixed */ 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci#define MS_SYSINF_CARDTYPE_RDONLY 1 1618c2ecf20Sopenharmony_ci#define MS_SYSINF_CARDTYPE_RDWR 2 1628c2ecf20Sopenharmony_ci#define MS_SYSINF_CARDTYPE_HYBRID 3 1638c2ecf20Sopenharmony_ci#define MS_SYSINF_SECURITY 0x01 1648c2ecf20Sopenharmony_ci#define MS_SYSINF_SECURITY_NO_SUPPORT MS_SYSINF_SECURITY 1658c2ecf20Sopenharmony_ci#define MS_SYSINF_SECURITY_SUPPORT 0 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci#define MS_SYSINF_RESERVED1 1 1688c2ecf20Sopenharmony_ci#define MS_SYSINF_RESERVED2 1 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci#define MS_SYSENT_TYPE_INVALID_BLOCK 0x01 1718c2ecf20Sopenharmony_ci#define MS_SYSENT_TYPE_CIS_IDI 0x0a /* CIS/IDI */ 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci#define SIZE_OF_KIRO 1024 1748c2ecf20Sopenharmony_ci#define BYTE_MASK 0xff 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci/* ms error code */ 1778c2ecf20Sopenharmony_ci#define MS_STATUS_WRITE_PROTECT 0x0106 1788c2ecf20Sopenharmony_ci#define MS_STATUS_SUCCESS 0x0000 1798c2ecf20Sopenharmony_ci#define MS_ERROR_FLASH_READ 0x8003 1808c2ecf20Sopenharmony_ci#define MS_ERROR_FLASH_ERASE 0x8005 1818c2ecf20Sopenharmony_ci#define MS_LB_ERROR 0xfff0 1828c2ecf20Sopenharmony_ci#define MS_LB_BOOT_BLOCK 0xfff1 1838c2ecf20Sopenharmony_ci#define MS_LB_INITIAL_ERROR 0xfff2 1848c2ecf20Sopenharmony_ci#define MS_STATUS_SUCCESS_WITH_ECC 0xfff3 1858c2ecf20Sopenharmony_ci#define MS_LB_ACQUIRED_ERROR 0xfff4 1868c2ecf20Sopenharmony_ci#define MS_LB_NOT_USED_ERASED 0xfff5 1878c2ecf20Sopenharmony_ci#define MS_NOCARD_ERROR 0xfff8 1888c2ecf20Sopenharmony_ci#define MS_NO_MEMORY_ERROR 0xfff9 1898c2ecf20Sopenharmony_ci#define MS_STATUS_INT_ERROR 0xfffa 1908c2ecf20Sopenharmony_ci#define MS_STATUS_ERROR 0xfffe 1918c2ecf20Sopenharmony_ci#define MS_LB_NOT_USED 0xffff 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci#define MS_REG_MNG_SYSFLG 0x04 /* system flag */ 1948c2ecf20Sopenharmony_ci#define MS_REG_MNG_SYSFLG_USER MS_REG_MNG_SYSFLG /* user block */ 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci#define MS_BOOT_BLOCK_ID 0x0001 1978c2ecf20Sopenharmony_ci#define MS_BOOT_BLOCK_FORMAT_VERSION 0x0100 1988c2ecf20Sopenharmony_ci#define MS_BOOT_BLOCK_DATA_ENTRIES 2 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci#define MS_NUMBER_OF_SYSTEM_ENTRY 4 2018c2ecf20Sopenharmony_ci#define MS_NUMBER_OF_BOOT_BLOCK 2 2028c2ecf20Sopenharmony_ci#define MS_BYTES_PER_PAGE 512 2038c2ecf20Sopenharmony_ci#define MS_LOGICAL_BLOCKS_PER_SEGMENT 496 2048c2ecf20Sopenharmony_ci#define MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT 494 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci#define MS_PHYSICAL_BLOCKS_PER_SEGMENT 0x200 /* 512 */ 2078c2ecf20Sopenharmony_ci#define MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK 0x1ff 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci/* overwrite area */ 2108c2ecf20Sopenharmony_ci#define MS_REG_OVR_BKST 0x80 /* block status */ 2118c2ecf20Sopenharmony_ci#define MS_REG_OVR_BKST_OK MS_REG_OVR_BKST /* OK */ 2128c2ecf20Sopenharmony_ci#define MS_REG_OVR_BKST_NG 0x00 /* NG */ 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci/* Status Register 1 */ 2158c2ecf20Sopenharmony_ci#define MS_REG_ST1_DTER 0x20 /* error on data(corrected) */ 2168c2ecf20Sopenharmony_ci#define MS_REG_ST1_EXER 0x08 /* error on extra(corrected) */ 2178c2ecf20Sopenharmony_ci#define MS_REG_ST1_FGER 0x02 /* error on overwrite flag(corrected) */ 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci/* MemoryStick Register */ 2208c2ecf20Sopenharmony_ci/* Status Register 0 */ 2218c2ecf20Sopenharmony_ci#define MS_REG_ST0_WP 0x01 /* write protected */ 2228c2ecf20Sopenharmony_ci#define MS_REG_ST0_WP_ON MS_REG_ST0_WP 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci#define MS_LIB_CTRL_RDONLY 0 2258c2ecf20Sopenharmony_ci#define MS_LIB_CTRL_WRPROTECT 1 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci/*dphy->log table */ 2288c2ecf20Sopenharmony_ci#define ms_libconv_to_logical(pdx, PhyBlock) (((PhyBlock) >= (pdx)->MS_Lib.NumberOfPhyBlock) ? MS_STATUS_ERROR : (pdx)->MS_Lib.Phy2LogMap[PhyBlock]) 2298c2ecf20Sopenharmony_ci#define ms_libconv_to_physical(pdx, LogBlock) (((LogBlock) >= (pdx)->MS_Lib.NumberOfLogBlock) ? MS_STATUS_ERROR : (pdx)->MS_Lib.Log2PhyMap[LogBlock]) 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci#define ms_lib_ctrl_set(pdx, Flag) ((pdx)->MS_Lib.flags |= (1 << (Flag))) 2328c2ecf20Sopenharmony_ci#define ms_lib_ctrl_reset(pdx, Flag) ((pdx)->MS_Lib.flags &= ~(1 << (Flag))) 2338c2ecf20Sopenharmony_ci#define ms_lib_ctrl_check(pdx, Flag) ((pdx)->MS_Lib.flags & (1 << (Flag))) 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci#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)) 2368c2ecf20Sopenharmony_ci#define ms_lib_clear_pagemap(pdx) memset((pdx)->MS_Lib.pagemap, 0, sizeof((pdx)->MS_Lib.pagemap)) 2378c2ecf20Sopenharmony_ci#define memstick_logaddr(logadr1, logadr0) ((((u16)(logadr1)) << 8) | (logadr0)) 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci/* SD_STATUS bits */ 2418c2ecf20Sopenharmony_ci#define SD_Insert BIT(0) 2428c2ecf20Sopenharmony_ci#define SD_Ready BIT(1) 2438c2ecf20Sopenharmony_ci#define SD_MediaChange BIT(2) 2448c2ecf20Sopenharmony_ci#define SD_IsMMC BIT(3) 2458c2ecf20Sopenharmony_ci#define SD_HiCapacity BIT(4) 2468c2ecf20Sopenharmony_ci#define SD_HiSpeed BIT(5) 2478c2ecf20Sopenharmony_ci#define SD_WtP BIT(6) 2488c2ecf20Sopenharmony_ci /* Bit 7 reserved */ 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci/* MS_STATUS bits */ 2518c2ecf20Sopenharmony_ci#define MS_Insert BIT(0) 2528c2ecf20Sopenharmony_ci#define MS_Ready BIT(1) 2538c2ecf20Sopenharmony_ci#define MS_MediaChange BIT(2) 2548c2ecf20Sopenharmony_ci#define MS_IsMSPro BIT(3) 2558c2ecf20Sopenharmony_ci#define MS_IsMSPHG BIT(4) 2568c2ecf20Sopenharmony_ci /* Bit 5 reserved */ 2578c2ecf20Sopenharmony_ci#define MS_WtP BIT(6) 2588c2ecf20Sopenharmony_ci /* Bit 7 reserved */ 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci/* SM_STATUS bits */ 2618c2ecf20Sopenharmony_ci#define SM_Insert BIT(0) 2628c2ecf20Sopenharmony_ci#define SM_Ready BIT(1) 2638c2ecf20Sopenharmony_ci#define SM_MediaChange BIT(2) 2648c2ecf20Sopenharmony_ci /* Bits 3-5 reserved */ 2658c2ecf20Sopenharmony_ci#define SM_WtP BIT(6) 2668c2ecf20Sopenharmony_ci#define SM_IsMS BIT(7) 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cistruct ms_bootblock_cis { 2698c2ecf20Sopenharmony_ci u8 bCistplDEVICE[6]; /* 0 */ 2708c2ecf20Sopenharmony_ci u8 bCistplDEVICE0C[6]; /* 6 */ 2718c2ecf20Sopenharmony_ci u8 bCistplJEDECC[4]; /* 12 */ 2728c2ecf20Sopenharmony_ci u8 bCistplMANFID[6]; /* 16 */ 2738c2ecf20Sopenharmony_ci u8 bCistplVER1[32]; /* 22 */ 2748c2ecf20Sopenharmony_ci u8 bCistplFUNCID[4]; /* 54 */ 2758c2ecf20Sopenharmony_ci u8 bCistplFUNCE0[4]; /* 58 */ 2768c2ecf20Sopenharmony_ci u8 bCistplFUNCE1[5]; /* 62 */ 2778c2ecf20Sopenharmony_ci u8 bCistplCONF[7]; /* 67 */ 2788c2ecf20Sopenharmony_ci u8 bCistplCFTBLENT0[10];/* 74 */ 2798c2ecf20Sopenharmony_ci u8 bCistplCFTBLENT1[8]; /* 84 */ 2808c2ecf20Sopenharmony_ci u8 bCistplCFTBLENT2[12];/* 92 */ 2818c2ecf20Sopenharmony_ci u8 bCistplCFTBLENT3[8]; /* 104 */ 2828c2ecf20Sopenharmony_ci u8 bCistplCFTBLENT4[17];/* 112 */ 2838c2ecf20Sopenharmony_ci u8 bCistplCFTBLENT5[8]; /* 129 */ 2848c2ecf20Sopenharmony_ci u8 bCistplCFTBLENT6[17];/* 137 */ 2858c2ecf20Sopenharmony_ci u8 bCistplCFTBLENT7[8]; /* 154 */ 2868c2ecf20Sopenharmony_ci u8 bCistplNOLINK[3]; /* 162 */ 2878c2ecf20Sopenharmony_ci} ; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_cistruct ms_bootblock_idi { 2908c2ecf20Sopenharmony_ci#define MS_IDI_GENERAL_CONF 0x848A 2918c2ecf20Sopenharmony_ci u16 wIDIgeneralConfiguration; /* 0 */ 2928c2ecf20Sopenharmony_ci u16 wIDInumberOfCylinder; /* 1 */ 2938c2ecf20Sopenharmony_ci u16 wIDIreserved0; /* 2 */ 2948c2ecf20Sopenharmony_ci u16 wIDInumberOfHead; /* 3 */ 2958c2ecf20Sopenharmony_ci u16 wIDIbytesPerTrack; /* 4 */ 2968c2ecf20Sopenharmony_ci u16 wIDIbytesPerSector; /* 5 */ 2978c2ecf20Sopenharmony_ci u16 wIDIsectorsPerTrack; /* 6 */ 2988c2ecf20Sopenharmony_ci u16 wIDItotalSectors[2]; /* 7-8 high,low */ 2998c2ecf20Sopenharmony_ci u16 wIDIreserved1[11]; /* 9-19 */ 3008c2ecf20Sopenharmony_ci u16 wIDIbufferType; /* 20 */ 3018c2ecf20Sopenharmony_ci u16 wIDIbufferSize; /* 21 */ 3028c2ecf20Sopenharmony_ci u16 wIDIlongCmdECC; /* 22 */ 3038c2ecf20Sopenharmony_ci u16 wIDIfirmVersion[4]; /* 23-26 */ 3048c2ecf20Sopenharmony_ci u16 wIDImodelName[20]; /* 27-46 */ 3058c2ecf20Sopenharmony_ci u16 wIDIreserved2; /* 47 */ 3068c2ecf20Sopenharmony_ci u16 wIDIlongWordSupported; /* 48 */ 3078c2ecf20Sopenharmony_ci u16 wIDIdmaSupported; /* 49 */ 3088c2ecf20Sopenharmony_ci u16 wIDIreserved3; /* 50 */ 3098c2ecf20Sopenharmony_ci u16 wIDIpioTiming; /* 51 */ 3108c2ecf20Sopenharmony_ci u16 wIDIdmaTiming; /* 52 */ 3118c2ecf20Sopenharmony_ci u16 wIDItransferParameter; /* 53 */ 3128c2ecf20Sopenharmony_ci u16 wIDIformattedCylinder; /* 54 */ 3138c2ecf20Sopenharmony_ci u16 wIDIformattedHead; /* 55 */ 3148c2ecf20Sopenharmony_ci u16 wIDIformattedSectorsPerTrack;/* 56 */ 3158c2ecf20Sopenharmony_ci u16 wIDIformattedTotalSectors[2];/* 57-58 */ 3168c2ecf20Sopenharmony_ci u16 wIDImultiSector; /* 59 */ 3178c2ecf20Sopenharmony_ci u16 wIDIlbaSectors[2]; /* 60-61 */ 3188c2ecf20Sopenharmony_ci u16 wIDIsingleWordDMA; /* 62 */ 3198c2ecf20Sopenharmony_ci u16 wIDImultiWordDMA; /* 63 */ 3208c2ecf20Sopenharmony_ci u16 wIDIreserved4[192]; /* 64-255 */ 3218c2ecf20Sopenharmony_ci}; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistruct ms_bootblock_sysent_rec { 3248c2ecf20Sopenharmony_ci u32 dwStart; 3258c2ecf20Sopenharmony_ci u32 dwSize; 3268c2ecf20Sopenharmony_ci u8 bType; 3278c2ecf20Sopenharmony_ci u8 bReserved[3]; 3288c2ecf20Sopenharmony_ci}; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistruct ms_bootblock_sysent { 3318c2ecf20Sopenharmony_ci struct ms_bootblock_sysent_rec entry[MS_NUMBER_OF_SYSTEM_ENTRY]; 3328c2ecf20Sopenharmony_ci}; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistruct ms_bootblock_sysinf { 3358c2ecf20Sopenharmony_ci u8 bMsClass; /* must be 1 */ 3368c2ecf20Sopenharmony_ci u8 bCardType; /* see below */ 3378c2ecf20Sopenharmony_ci u16 wBlockSize; /* n KB */ 3388c2ecf20Sopenharmony_ci u16 wBlockNumber; /* number of physical block */ 3398c2ecf20Sopenharmony_ci u16 wTotalBlockNumber; /* number of logical block */ 3408c2ecf20Sopenharmony_ci u16 wPageSize; /* must be 0x200 */ 3418c2ecf20Sopenharmony_ci u8 bExtraSize; /* 0x10 */ 3428c2ecf20Sopenharmony_ci u8 bSecuritySupport; 3438c2ecf20Sopenharmony_ci u8 bAssemblyDate[8]; 3448c2ecf20Sopenharmony_ci u8 bFactoryArea[4]; 3458c2ecf20Sopenharmony_ci u8 bAssemblyMakerCode; 3468c2ecf20Sopenharmony_ci u8 bAssemblyMachineCode[3]; 3478c2ecf20Sopenharmony_ci u16 wMemoryMakerCode; 3488c2ecf20Sopenharmony_ci u16 wMemoryDeviceCode; 3498c2ecf20Sopenharmony_ci u16 wMemorySize; 3508c2ecf20Sopenharmony_ci u8 bReserved1; 3518c2ecf20Sopenharmony_ci u8 bReserved2; 3528c2ecf20Sopenharmony_ci u8 bVCC; 3538c2ecf20Sopenharmony_ci u8 bVPP; 3548c2ecf20Sopenharmony_ci u16 wControllerChipNumber; 3558c2ecf20Sopenharmony_ci u16 wControllerFunction; /* New MS */ 3568c2ecf20Sopenharmony_ci u8 bReserved3[9]; /* New MS */ 3578c2ecf20Sopenharmony_ci u8 bParallelSupport; /* New MS */ 3588c2ecf20Sopenharmony_ci u16 wFormatValue; /* New MS */ 3598c2ecf20Sopenharmony_ci u8 bFormatType; 3608c2ecf20Sopenharmony_ci u8 bUsage; 3618c2ecf20Sopenharmony_ci u8 bDeviceType; 3628c2ecf20Sopenharmony_ci u8 bReserved4[22]; 3638c2ecf20Sopenharmony_ci u8 bFUValue3; 3648c2ecf20Sopenharmony_ci u8 bFUValue4; 3658c2ecf20Sopenharmony_ci u8 bReserved5[15]; 3668c2ecf20Sopenharmony_ci}; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistruct ms_bootblock_header { 3698c2ecf20Sopenharmony_ci u16 wBlockID; 3708c2ecf20Sopenharmony_ci u16 wFormatVersion; 3718c2ecf20Sopenharmony_ci u8 bReserved1[184]; 3728c2ecf20Sopenharmony_ci u8 bNumberOfDataEntry; 3738c2ecf20Sopenharmony_ci u8 bReserved2[179]; 3748c2ecf20Sopenharmony_ci}; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistruct ms_bootblock_page0 { 3778c2ecf20Sopenharmony_ci struct ms_bootblock_header header; 3788c2ecf20Sopenharmony_ci struct ms_bootblock_sysent sysent; 3798c2ecf20Sopenharmony_ci struct ms_bootblock_sysinf sysinf; 3808c2ecf20Sopenharmony_ci}; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cistruct ms_bootblock_cis_idi { 3838c2ecf20Sopenharmony_ci union { 3848c2ecf20Sopenharmony_ci struct ms_bootblock_cis cis; 3858c2ecf20Sopenharmony_ci u8 dmy[256]; 3868c2ecf20Sopenharmony_ci } cis; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci union { 3898c2ecf20Sopenharmony_ci struct ms_bootblock_idi idi; 3908c2ecf20Sopenharmony_ci u8 dmy[256]; 3918c2ecf20Sopenharmony_ci } idi; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci}; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci/* ENE MS Lib struct */ 3968c2ecf20Sopenharmony_cistruct ms_lib_type_extdat { 3978c2ecf20Sopenharmony_ci u8 reserved; 3988c2ecf20Sopenharmony_ci u8 intr; 3998c2ecf20Sopenharmony_ci u8 status0; 4008c2ecf20Sopenharmony_ci u8 status1; 4018c2ecf20Sopenharmony_ci u8 ovrflg; 4028c2ecf20Sopenharmony_ci u8 mngflg; 4038c2ecf20Sopenharmony_ci u16 logadr; 4048c2ecf20Sopenharmony_ci}; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_cistruct ms_lib_ctrl { 4078c2ecf20Sopenharmony_ci u32 flags; 4088c2ecf20Sopenharmony_ci u32 BytesPerSector; 4098c2ecf20Sopenharmony_ci u32 NumberOfCylinder; 4108c2ecf20Sopenharmony_ci u32 SectorsPerCylinder; 4118c2ecf20Sopenharmony_ci u16 cardType; /* R/W, RO, Hybrid */ 4128c2ecf20Sopenharmony_ci u16 blockSize; 4138c2ecf20Sopenharmony_ci u16 PagesPerBlock; 4148c2ecf20Sopenharmony_ci u16 NumberOfPhyBlock; 4158c2ecf20Sopenharmony_ci u16 NumberOfLogBlock; 4168c2ecf20Sopenharmony_ci u16 NumberOfSegment; 4178c2ecf20Sopenharmony_ci u16 *Phy2LogMap; /* phy2log table */ 4188c2ecf20Sopenharmony_ci u16 *Log2PhyMap; /* log2phy table */ 4198c2ecf20Sopenharmony_ci u16 wrtblk; 4208c2ecf20Sopenharmony_ci unsigned char *pagemap[(MS_MAX_PAGES_PER_BLOCK + (MS_LIB_BITS_PER_BYTE-1)) / MS_LIB_BITS_PER_BYTE]; 4218c2ecf20Sopenharmony_ci unsigned char *blkpag; 4228c2ecf20Sopenharmony_ci struct ms_lib_type_extdat *blkext; 4238c2ecf20Sopenharmony_ci unsigned char copybuf[512]; 4248c2ecf20Sopenharmony_ci}; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci/* SD Block Length */ 4288c2ecf20Sopenharmony_ci/* 2^9 = 512 Bytes, The HW maximum read/write data length */ 4298c2ecf20Sopenharmony_ci#define SD_BLOCK_LEN 9 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_cistruct ene_ub6250_info { 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci /* I/O bounce buffer */ 4348c2ecf20Sopenharmony_ci u8 *bbuf; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci /* for 6250 code */ 4378c2ecf20Sopenharmony_ci u8 SD_Status; 4388c2ecf20Sopenharmony_ci u8 MS_Status; 4398c2ecf20Sopenharmony_ci u8 SM_Status; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci /* ----- SD Control Data ---------------- */ 4428c2ecf20Sopenharmony_ci /*SD_REGISTER SD_Regs; */ 4438c2ecf20Sopenharmony_ci u16 SD_Block_Mult; 4448c2ecf20Sopenharmony_ci u8 SD_READ_BL_LEN; 4458c2ecf20Sopenharmony_ci u16 SD_C_SIZE; 4468c2ecf20Sopenharmony_ci u8 SD_C_SIZE_MULT; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci /* SD/MMC New spec. */ 4498c2ecf20Sopenharmony_ci u8 SD_SPEC_VER; 4508c2ecf20Sopenharmony_ci u8 SD_CSD_VER; 4518c2ecf20Sopenharmony_ci u8 SD20_HIGH_CAPACITY; 4528c2ecf20Sopenharmony_ci u32 HC_C_SIZE; 4538c2ecf20Sopenharmony_ci u8 MMC_SPEC_VER; 4548c2ecf20Sopenharmony_ci u8 MMC_BusWidth; 4558c2ecf20Sopenharmony_ci u8 MMC_HIGH_CAPACITY; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci /*----- MS Control Data ---------------- */ 4588c2ecf20Sopenharmony_ci bool MS_SWWP; 4598c2ecf20Sopenharmony_ci u32 MSP_TotalBlock; 4608c2ecf20Sopenharmony_ci struct ms_lib_ctrl MS_Lib; 4618c2ecf20Sopenharmony_ci bool MS_IsRWPage; 4628c2ecf20Sopenharmony_ci u16 MS_Model; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci /*----- SM Control Data ---------------- */ 4658c2ecf20Sopenharmony_ci u8 SM_DeviceID; 4668c2ecf20Sopenharmony_ci u8 SM_CardID; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci unsigned char *testbuf; 4698c2ecf20Sopenharmony_ci u8 BIN_FLAG; 4708c2ecf20Sopenharmony_ci u32 bl_num; 4718c2ecf20Sopenharmony_ci int SrbStatus; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci /*------Power Managerment ---------------*/ 4748c2ecf20Sopenharmony_ci bool Power_IsResum; 4758c2ecf20Sopenharmony_ci}; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_cistatic int ene_sd_init(struct us_data *us); 4788c2ecf20Sopenharmony_cistatic int ene_ms_init(struct us_data *us); 4798c2ecf20Sopenharmony_cistatic int ene_load_bincode(struct us_data *us, unsigned char flag); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_cistatic void ene_ub6250_info_destructor(void *extra) 4828c2ecf20Sopenharmony_ci{ 4838c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) extra; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci if (!extra) 4868c2ecf20Sopenharmony_ci return; 4878c2ecf20Sopenharmony_ci kfree(info->bbuf); 4888c2ecf20Sopenharmony_ci} 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_cistatic int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg) 4918c2ecf20Sopenharmony_ci{ 4928c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 4938c2ecf20Sopenharmony_ci struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci int result; 4968c2ecf20Sopenharmony_ci unsigned int residue; 4978c2ecf20Sopenharmony_ci unsigned int cswlen = 0, partial = 0; 4988c2ecf20Sopenharmony_ci unsigned int transfer_length = bcb->DataTransferLength; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci /* usb_stor_dbg(us, "transport --- ene_send_scsi_cmd\n"); */ 5018c2ecf20Sopenharmony_ci /* send cmd to out endpoint */ 5028c2ecf20Sopenharmony_ci result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, 5038c2ecf20Sopenharmony_ci bcb, US_BULK_CB_WRAP_LEN, NULL); 5048c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 5058c2ecf20Sopenharmony_ci usb_stor_dbg(us, "send cmd to out endpoint fail ---\n"); 5068c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci if (buf) { 5108c2ecf20Sopenharmony_ci unsigned int pipe = fDir; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci if (fDir == FDIR_READ) 5138c2ecf20Sopenharmony_ci pipe = us->recv_bulk_pipe; 5148c2ecf20Sopenharmony_ci else 5158c2ecf20Sopenharmony_ci pipe = us->send_bulk_pipe; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci /* Bulk */ 5188c2ecf20Sopenharmony_ci if (use_sg) { 5198c2ecf20Sopenharmony_ci result = usb_stor_bulk_srb(us, pipe, us->srb); 5208c2ecf20Sopenharmony_ci } else { 5218c2ecf20Sopenharmony_ci result = usb_stor_bulk_transfer_sg(us, pipe, buf, 5228c2ecf20Sopenharmony_ci transfer_length, 0, &partial); 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 5258c2ecf20Sopenharmony_ci usb_stor_dbg(us, "data transfer fail ---\n"); 5268c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 5278c2ecf20Sopenharmony_ci } 5288c2ecf20Sopenharmony_ci } 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci /* Get CSW for device status */ 5318c2ecf20Sopenharmony_ci result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, 5328c2ecf20Sopenharmony_ci US_BULK_CS_WRAP_LEN, &cswlen); 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci if (result == USB_STOR_XFER_SHORT && cswlen == 0) { 5358c2ecf20Sopenharmony_ci usb_stor_dbg(us, "Received 0-length CSW; retrying...\n"); 5368c2ecf20Sopenharmony_ci result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, 5378c2ecf20Sopenharmony_ci bcs, US_BULK_CS_WRAP_LEN, &cswlen); 5388c2ecf20Sopenharmony_ci } 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci if (result == USB_STOR_XFER_STALLED) { 5418c2ecf20Sopenharmony_ci /* get the status again */ 5428c2ecf20Sopenharmony_ci usb_stor_dbg(us, "Attempting to get CSW (2nd try)...\n"); 5438c2ecf20Sopenharmony_ci result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, 5448c2ecf20Sopenharmony_ci bcs, US_BULK_CS_WRAP_LEN, NULL); 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 5488c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci /* check bulk status */ 5518c2ecf20Sopenharmony_ci residue = le32_to_cpu(bcs->Residue); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci /* 5548c2ecf20Sopenharmony_ci * try to compute the actual residue, based on how much data 5558c2ecf20Sopenharmony_ci * was really transferred and what the device tells us 5568c2ecf20Sopenharmony_ci */ 5578c2ecf20Sopenharmony_ci if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) { 5588c2ecf20Sopenharmony_ci residue = min(residue, transfer_length); 5598c2ecf20Sopenharmony_ci if (us->srb != NULL) 5608c2ecf20Sopenharmony_ci scsi_set_resid(us->srb, max(scsi_get_resid(us->srb), 5618c2ecf20Sopenharmony_ci residue)); 5628c2ecf20Sopenharmony_ci } 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci if (bcs->Status != US_BULK_STAT_OK) 5658c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 5688c2ecf20Sopenharmony_ci} 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_cistatic int do_scsi_request_sense(struct us_data *us, struct scsi_cmnd *srb) 5718c2ecf20Sopenharmony_ci{ 5728c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 5738c2ecf20Sopenharmony_ci unsigned char buf[18]; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci memset(buf, 0, 18); 5768c2ecf20Sopenharmony_ci buf[0] = 0x70; /* Current error */ 5778c2ecf20Sopenharmony_ci buf[2] = info->SrbStatus >> 16; /* Sense key */ 5788c2ecf20Sopenharmony_ci buf[7] = 10; /* Additional length */ 5798c2ecf20Sopenharmony_ci buf[12] = info->SrbStatus >> 8; /* ASC */ 5808c2ecf20Sopenharmony_ci buf[13] = info->SrbStatus; /* ASCQ */ 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci usb_stor_set_xfer_buf(buf, sizeof(buf), srb); 5838c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_cistatic int do_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci unsigned char data_ptr[36] = { 5898c2ecf20Sopenharmony_ci 0x00, 0x00, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 5908c2ecf20Sopenharmony_ci 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, 5918c2ecf20Sopenharmony_ci 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 5928c2ecf20Sopenharmony_ci 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30 }; 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci usb_stor_set_xfer_buf(data_ptr, 36, srb); 5958c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 5968c2ecf20Sopenharmony_ci} 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_cistatic int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb) 5998c2ecf20Sopenharmony_ci{ 6008c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci if ((info->SD_Status & SD_Insert) && (info->SD_Status & SD_Ready)) 6038c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 6048c2ecf20Sopenharmony_ci else { 6058c2ecf20Sopenharmony_ci ene_sd_init(us); 6068c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 6078c2ecf20Sopenharmony_ci } 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 6108c2ecf20Sopenharmony_ci} 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_cistatic int sd_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb) 6138c2ecf20Sopenharmony_ci{ 6148c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 6158c2ecf20Sopenharmony_ci unsigned char mediaNoWP[12] = { 6168c2ecf20Sopenharmony_ci 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 6178c2ecf20Sopenharmony_ci 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 }; 6188c2ecf20Sopenharmony_ci unsigned char mediaWP[12] = { 6198c2ecf20Sopenharmony_ci 0x0b, 0x00, 0x80, 0x08, 0x00, 0x00, 6208c2ecf20Sopenharmony_ci 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 }; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci if (info->SD_Status & SD_WtP) 6238c2ecf20Sopenharmony_ci usb_stor_set_xfer_buf(mediaWP, 12, srb); 6248c2ecf20Sopenharmony_ci else 6258c2ecf20Sopenharmony_ci usb_stor_set_xfer_buf(mediaNoWP, 12, srb); 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci u32 bl_num; 6348c2ecf20Sopenharmony_ci u32 bl_len; 6358c2ecf20Sopenharmony_ci unsigned int offset = 0; 6368c2ecf20Sopenharmony_ci unsigned char buf[8]; 6378c2ecf20Sopenharmony_ci struct scatterlist *sg = NULL; 6388c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci usb_stor_dbg(us, "sd_scsi_read_capacity\n"); 6418c2ecf20Sopenharmony_ci if (info->SD_Status & SD_HiCapacity) { 6428c2ecf20Sopenharmony_ci bl_len = 0x200; 6438c2ecf20Sopenharmony_ci if (info->SD_Status & SD_IsMMC) 6448c2ecf20Sopenharmony_ci bl_num = info->HC_C_SIZE-1; 6458c2ecf20Sopenharmony_ci else 6468c2ecf20Sopenharmony_ci bl_num = (info->HC_C_SIZE + 1) * 1024 - 1; 6478c2ecf20Sopenharmony_ci } else { 6488c2ecf20Sopenharmony_ci bl_len = 1 << (info->SD_READ_BL_LEN); 6498c2ecf20Sopenharmony_ci bl_num = info->SD_Block_Mult * (info->SD_C_SIZE + 1) 6508c2ecf20Sopenharmony_ci * (1 << (info->SD_C_SIZE_MULT + 2)) - 1; 6518c2ecf20Sopenharmony_ci } 6528c2ecf20Sopenharmony_ci info->bl_num = bl_num; 6538c2ecf20Sopenharmony_ci usb_stor_dbg(us, "bl_len = %x\n", bl_len); 6548c2ecf20Sopenharmony_ci usb_stor_dbg(us, "bl_num = %x\n", bl_num); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci /*srb->request_bufflen = 8; */ 6578c2ecf20Sopenharmony_ci buf[0] = (bl_num >> 24) & 0xff; 6588c2ecf20Sopenharmony_ci buf[1] = (bl_num >> 16) & 0xff; 6598c2ecf20Sopenharmony_ci buf[2] = (bl_num >> 8) & 0xff; 6608c2ecf20Sopenharmony_ci buf[3] = (bl_num >> 0) & 0xff; 6618c2ecf20Sopenharmony_ci buf[4] = (bl_len >> 24) & 0xff; 6628c2ecf20Sopenharmony_ci buf[5] = (bl_len >> 16) & 0xff; 6638c2ecf20Sopenharmony_ci buf[6] = (bl_len >> 8) & 0xff; 6648c2ecf20Sopenharmony_ci buf[7] = (bl_len >> 0) & 0xff; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci usb_stor_access_xfer_buf(buf, 8, srb, &sg, &offset, TO_XFER_BUF); 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 6698c2ecf20Sopenharmony_ci} 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_cistatic int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb) 6728c2ecf20Sopenharmony_ci{ 6738c2ecf20Sopenharmony_ci int result; 6748c2ecf20Sopenharmony_ci unsigned char *cdb = srb->cmnd; 6758c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 6768c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) | 6798c2ecf20Sopenharmony_ci ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff); 6808c2ecf20Sopenharmony_ci u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff); 6818c2ecf20Sopenharmony_ci u32 bnByte = bn * 0x200; 6828c2ecf20Sopenharmony_ci u32 blenByte = blen * 0x200; 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci if (bn > info->bl_num) 6858c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci result = ene_load_bincode(us, SD_RW_PATTERN); 6888c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 6898c2ecf20Sopenharmony_ci usb_stor_dbg(us, "Load SD RW pattern Fail !!\n"); 6908c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 6918c2ecf20Sopenharmony_ci } 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci if (info->SD_Status & SD_HiCapacity) 6948c2ecf20Sopenharmony_ci bnByte = bn; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci /* set up the command wrapper */ 6978c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 6988c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 6998c2ecf20Sopenharmony_ci bcb->DataTransferLength = blenByte; 7008c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 7018c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF1; 7028c2ecf20Sopenharmony_ci bcb->CDB[5] = (unsigned char)(bnByte); 7038c2ecf20Sopenharmony_ci bcb->CDB[4] = (unsigned char)(bnByte>>8); 7048c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)(bnByte>>16); 7058c2ecf20Sopenharmony_ci bcb->CDB[2] = (unsigned char)(bnByte>>24); 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, scsi_sglist(srb), 1); 7088c2ecf20Sopenharmony_ci return result; 7098c2ecf20Sopenharmony_ci} 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_cistatic int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb) 7128c2ecf20Sopenharmony_ci{ 7138c2ecf20Sopenharmony_ci int result; 7148c2ecf20Sopenharmony_ci unsigned char *cdb = srb->cmnd; 7158c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 7168c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) | 7198c2ecf20Sopenharmony_ci ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff); 7208c2ecf20Sopenharmony_ci u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff); 7218c2ecf20Sopenharmony_ci u32 bnByte = bn * 0x200; 7228c2ecf20Sopenharmony_ci u32 blenByte = blen * 0x200; 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci if (bn > info->bl_num) 7258c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci result = ene_load_bincode(us, SD_RW_PATTERN); 7288c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 7298c2ecf20Sopenharmony_ci usb_stor_dbg(us, "Load SD RW pattern Fail !!\n"); 7308c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci if (info->SD_Status & SD_HiCapacity) 7348c2ecf20Sopenharmony_ci bnByte = bn; 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci /* set up the command wrapper */ 7378c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 7388c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 7398c2ecf20Sopenharmony_ci bcb->DataTransferLength = blenByte; 7408c2ecf20Sopenharmony_ci bcb->Flags = 0x00; 7418c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF0; 7428c2ecf20Sopenharmony_ci bcb->CDB[5] = (unsigned char)(bnByte); 7438c2ecf20Sopenharmony_ci bcb->CDB[4] = (unsigned char)(bnByte>>8); 7448c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)(bnByte>>16); 7458c2ecf20Sopenharmony_ci bcb->CDB[2] = (unsigned char)(bnByte>>24); 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1); 7488c2ecf20Sopenharmony_ci return result; 7498c2ecf20Sopenharmony_ci} 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci/* 7528c2ecf20Sopenharmony_ci * ENE MS Card 7538c2ecf20Sopenharmony_ci */ 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_cistatic int ms_lib_set_logicalpair(struct us_data *us, u16 logblk, u16 phyblk) 7568c2ecf20Sopenharmony_ci{ 7578c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci if ((logblk >= info->MS_Lib.NumberOfLogBlock) || (phyblk >= info->MS_Lib.NumberOfPhyBlock)) 7608c2ecf20Sopenharmony_ci return (u32)-1; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap[phyblk] = logblk; 7638c2ecf20Sopenharmony_ci info->MS_Lib.Log2PhyMap[logblk] = phyblk; 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci return 0; 7668c2ecf20Sopenharmony_ci} 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_cistatic int ms_lib_set_logicalblockmark(struct us_data *us, u16 phyblk, u16 mark) 7698c2ecf20Sopenharmony_ci{ 7708c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci if (phyblk >= info->MS_Lib.NumberOfPhyBlock) 7738c2ecf20Sopenharmony_ci return (u32)-1; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap[phyblk] = mark; 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci return 0; 7788c2ecf20Sopenharmony_ci} 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_cistatic int ms_lib_set_initialerrorblock(struct us_data *us, u16 phyblk) 7818c2ecf20Sopenharmony_ci{ 7828c2ecf20Sopenharmony_ci return ms_lib_set_logicalblockmark(us, phyblk, MS_LB_INITIAL_ERROR); 7838c2ecf20Sopenharmony_ci} 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_cistatic int ms_lib_set_bootblockmark(struct us_data *us, u16 phyblk) 7868c2ecf20Sopenharmony_ci{ 7878c2ecf20Sopenharmony_ci return ms_lib_set_logicalblockmark(us, phyblk, MS_LB_BOOT_BLOCK); 7888c2ecf20Sopenharmony_ci} 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_cistatic int ms_lib_free_logicalmap(struct us_data *us) 7918c2ecf20Sopenharmony_ci{ 7928c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci kfree(info->MS_Lib.Phy2LogMap); 7958c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap = NULL; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci kfree(info->MS_Lib.Log2PhyMap); 7988c2ecf20Sopenharmony_ci info->MS_Lib.Log2PhyMap = NULL; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci return 0; 8018c2ecf20Sopenharmony_ci} 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_cistatic int ms_lib_alloc_logicalmap(struct us_data *us) 8048c2ecf20Sopenharmony_ci{ 8058c2ecf20Sopenharmony_ci u32 i; 8068c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap = kmalloc_array(info->MS_Lib.NumberOfPhyBlock, 8098c2ecf20Sopenharmony_ci sizeof(u16), 8108c2ecf20Sopenharmony_ci GFP_KERNEL); 8118c2ecf20Sopenharmony_ci info->MS_Lib.Log2PhyMap = kmalloc_array(info->MS_Lib.NumberOfLogBlock, 8128c2ecf20Sopenharmony_ci sizeof(u16), 8138c2ecf20Sopenharmony_ci GFP_KERNEL); 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci if ((info->MS_Lib.Phy2LogMap == NULL) || (info->MS_Lib.Log2PhyMap == NULL)) { 8168c2ecf20Sopenharmony_ci ms_lib_free_logicalmap(us); 8178c2ecf20Sopenharmony_ci return (u32)-1; 8188c2ecf20Sopenharmony_ci } 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci for (i = 0; i < info->MS_Lib.NumberOfPhyBlock; i++) 8218c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap[i] = MS_LB_NOT_USED; 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci for (i = 0; i < info->MS_Lib.NumberOfLogBlock; i++) 8248c2ecf20Sopenharmony_ci info->MS_Lib.Log2PhyMap[i] = MS_LB_NOT_USED; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci return 0; 8278c2ecf20Sopenharmony_ci} 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_cistatic void ms_lib_clear_writebuf(struct us_data *us) 8308c2ecf20Sopenharmony_ci{ 8318c2ecf20Sopenharmony_ci int i; 8328c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci info->MS_Lib.wrtblk = (u16)-1; 8358c2ecf20Sopenharmony_ci ms_lib_clear_pagemap(info); 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci if (info->MS_Lib.blkpag) 8388c2ecf20Sopenharmony_ci memset(info->MS_Lib.blkpag, 0xff, info->MS_Lib.PagesPerBlock * info->MS_Lib.BytesPerSector); 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci if (info->MS_Lib.blkext) { 8418c2ecf20Sopenharmony_ci for (i = 0; i < info->MS_Lib.PagesPerBlock; i++) { 8428c2ecf20Sopenharmony_ci info->MS_Lib.blkext[i].status1 = MS_REG_ST1_DEFAULT; 8438c2ecf20Sopenharmony_ci info->MS_Lib.blkext[i].ovrflg = MS_REG_OVR_DEFAULT; 8448c2ecf20Sopenharmony_ci info->MS_Lib.blkext[i].mngflg = MS_REG_MNG_DEFAULT; 8458c2ecf20Sopenharmony_ci info->MS_Lib.blkext[i].logadr = MS_LB_NOT_USED; 8468c2ecf20Sopenharmony_ci } 8478c2ecf20Sopenharmony_ci } 8488c2ecf20Sopenharmony_ci} 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_cistatic int ms_count_freeblock(struct us_data *us, u16 PhyBlock) 8518c2ecf20Sopenharmony_ci{ 8528c2ecf20Sopenharmony_ci u32 Ende, Count; 8538c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci Ende = PhyBlock + MS_PHYSICAL_BLOCKS_PER_SEGMENT; 8568c2ecf20Sopenharmony_ci for (Count = 0; PhyBlock < Ende; PhyBlock++) { 8578c2ecf20Sopenharmony_ci switch (info->MS_Lib.Phy2LogMap[PhyBlock]) { 8588c2ecf20Sopenharmony_ci case MS_LB_NOT_USED: 8598c2ecf20Sopenharmony_ci case MS_LB_NOT_USED_ERASED: 8608c2ecf20Sopenharmony_ci Count++; 8618c2ecf20Sopenharmony_ci default: 8628c2ecf20Sopenharmony_ci break; 8638c2ecf20Sopenharmony_ci } 8648c2ecf20Sopenharmony_ci } 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci return Count; 8678c2ecf20Sopenharmony_ci} 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_cistatic int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, 8708c2ecf20Sopenharmony_ci u8 PageNum, u32 *PageBuf, struct ms_lib_type_extdat *ExtraDat) 8718c2ecf20Sopenharmony_ci{ 8728c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 8738c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 8748c2ecf20Sopenharmony_ci u8 *bbuf = info->bbuf; 8758c2ecf20Sopenharmony_ci int result; 8768c2ecf20Sopenharmony_ci u32 bn = PhyBlockAddr * 0x20 + PageNum; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci result = ene_load_bincode(us, MS_RW_PATTERN); 8798c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 8808c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci /* Read Page Data */ 8838c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 8848c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 8858c2ecf20Sopenharmony_ci bcb->DataTransferLength = 0x200; 8868c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 8878c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF1; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci bcb->CDB[1] = 0x02; /* in init.c ENE_MSInit() is 0x01 */ 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci bcb->CDB[5] = (unsigned char)(bn); 8928c2ecf20Sopenharmony_ci bcb->CDB[4] = (unsigned char)(bn>>8); 8938c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)(bn>>16); 8948c2ecf20Sopenharmony_ci bcb->CDB[2] = (unsigned char)(bn>>24); 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, PageBuf, 0); 8978c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 8988c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci /* Read Extra Data */ 9028c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 9038c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 9048c2ecf20Sopenharmony_ci bcb->DataTransferLength = 0x4; 9058c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 9068c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF1; 9078c2ecf20Sopenharmony_ci bcb->CDB[1] = 0x03; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci bcb->CDB[5] = (unsigned char)(PageNum); 9108c2ecf20Sopenharmony_ci bcb->CDB[4] = (unsigned char)(PhyBlockAddr); 9118c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)(PhyBlockAddr>>8); 9128c2ecf20Sopenharmony_ci bcb->CDB[2] = (unsigned char)(PhyBlockAddr>>16); 9138c2ecf20Sopenharmony_ci bcb->CDB[6] = 0x01; 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); 9168c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 9178c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci ExtraDat->reserved = 0; 9208c2ecf20Sopenharmony_ci ExtraDat->intr = 0x80; /* Not yet,fireware support */ 9218c2ecf20Sopenharmony_ci ExtraDat->status0 = 0x10; /* Not yet,fireware support */ 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci ExtraDat->status1 = 0x00; /* Not yet,fireware support */ 9248c2ecf20Sopenharmony_ci ExtraDat->ovrflg = bbuf[0]; 9258c2ecf20Sopenharmony_ci ExtraDat->mngflg = bbuf[1]; 9268c2ecf20Sopenharmony_ci ExtraDat->logadr = memstick_logaddr(bbuf[2], bbuf[3]); 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 9298c2ecf20Sopenharmony_ci} 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_cistatic int ms_lib_process_bootblock(struct us_data *us, u16 PhyBlock, u8 *PageData) 9328c2ecf20Sopenharmony_ci{ 9338c2ecf20Sopenharmony_ci struct ms_bootblock_sysent *SysEntry; 9348c2ecf20Sopenharmony_ci struct ms_bootblock_sysinf *SysInfo; 9358c2ecf20Sopenharmony_ci u32 i, result; 9368c2ecf20Sopenharmony_ci u8 PageNumber; 9378c2ecf20Sopenharmony_ci u8 *PageBuffer; 9388c2ecf20Sopenharmony_ci struct ms_lib_type_extdat ExtraData; 9398c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci PageBuffer = kzalloc(MS_BYTES_PER_PAGE * 2, GFP_KERNEL); 9428c2ecf20Sopenharmony_ci if (PageBuffer == NULL) 9438c2ecf20Sopenharmony_ci return (u32)-1; 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci result = (u32)-1; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci SysInfo = &(((struct ms_bootblock_page0 *)PageData)->sysinf); 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci if ((SysInfo->bMsClass != MS_SYSINF_MSCLASS_TYPE_1) || 9508c2ecf20Sopenharmony_ci (be16_to_cpu(SysInfo->wPageSize) != MS_SYSINF_PAGE_SIZE) || 9518c2ecf20Sopenharmony_ci ((SysInfo->bSecuritySupport & MS_SYSINF_SECURITY) == MS_SYSINF_SECURITY_SUPPORT) || 9528c2ecf20Sopenharmony_ci (SysInfo->bReserved1 != MS_SYSINF_RESERVED1) || 9538c2ecf20Sopenharmony_ci (SysInfo->bReserved2 != MS_SYSINF_RESERVED2) || 9548c2ecf20Sopenharmony_ci (SysInfo->bFormatType != MS_SYSINF_FORMAT_FAT) || 9558c2ecf20Sopenharmony_ci (SysInfo->bUsage != MS_SYSINF_USAGE_GENERAL)) 9568c2ecf20Sopenharmony_ci goto exit; 9578c2ecf20Sopenharmony_ci /* */ 9588c2ecf20Sopenharmony_ci switch (info->MS_Lib.cardType = SysInfo->bCardType) { 9598c2ecf20Sopenharmony_ci case MS_SYSINF_CARDTYPE_RDONLY: 9608c2ecf20Sopenharmony_ci ms_lib_ctrl_set(info, MS_LIB_CTRL_RDONLY); 9618c2ecf20Sopenharmony_ci break; 9628c2ecf20Sopenharmony_ci case MS_SYSINF_CARDTYPE_RDWR: 9638c2ecf20Sopenharmony_ci ms_lib_ctrl_reset(info, MS_LIB_CTRL_RDONLY); 9648c2ecf20Sopenharmony_ci break; 9658c2ecf20Sopenharmony_ci case MS_SYSINF_CARDTYPE_HYBRID: 9668c2ecf20Sopenharmony_ci default: 9678c2ecf20Sopenharmony_ci goto exit; 9688c2ecf20Sopenharmony_ci } 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci info->MS_Lib.blockSize = be16_to_cpu(SysInfo->wBlockSize); 9718c2ecf20Sopenharmony_ci info->MS_Lib.NumberOfPhyBlock = be16_to_cpu(SysInfo->wBlockNumber); 9728c2ecf20Sopenharmony_ci info->MS_Lib.NumberOfLogBlock = be16_to_cpu(SysInfo->wTotalBlockNumber)-2; 9738c2ecf20Sopenharmony_ci info->MS_Lib.PagesPerBlock = info->MS_Lib.blockSize * SIZE_OF_KIRO / MS_BYTES_PER_PAGE; 9748c2ecf20Sopenharmony_ci info->MS_Lib.NumberOfSegment = info->MS_Lib.NumberOfPhyBlock / MS_PHYSICAL_BLOCKS_PER_SEGMENT; 9758c2ecf20Sopenharmony_ci info->MS_Model = be16_to_cpu(SysInfo->wMemorySize); 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci /*Allocate to all number of logicalblock and physicalblock */ 9788c2ecf20Sopenharmony_ci if (ms_lib_alloc_logicalmap(us)) 9798c2ecf20Sopenharmony_ci goto exit; 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci /* Mark the book block */ 9828c2ecf20Sopenharmony_ci ms_lib_set_bootblockmark(us, PhyBlock); 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci SysEntry = &(((struct ms_bootblock_page0 *)PageData)->sysent); 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci for (i = 0; i < MS_NUMBER_OF_SYSTEM_ENTRY; i++) { 9878c2ecf20Sopenharmony_ci u32 EntryOffset, EntrySize; 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci EntryOffset = be32_to_cpu(SysEntry->entry[i].dwStart); 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci if (EntryOffset == 0xffffff) 9928c2ecf20Sopenharmony_ci continue; 9938c2ecf20Sopenharmony_ci EntrySize = be32_to_cpu(SysEntry->entry[i].dwSize); 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci if (EntrySize == 0) 9968c2ecf20Sopenharmony_ci continue; 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci if (EntryOffset + MS_BYTES_PER_PAGE + EntrySize > info->MS_Lib.blockSize * (u32)SIZE_OF_KIRO) 9998c2ecf20Sopenharmony_ci continue; 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci if (i == 0) { 10028c2ecf20Sopenharmony_ci u8 PrevPageNumber = 0; 10038c2ecf20Sopenharmony_ci u16 phyblk; 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_INVALID_BLOCK) 10068c2ecf20Sopenharmony_ci goto exit; 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci while (EntrySize > 0) { 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci PageNumber = (u8)(EntryOffset / MS_BYTES_PER_PAGE + 1); 10118c2ecf20Sopenharmony_ci if (PageNumber != PrevPageNumber) { 10128c2ecf20Sopenharmony_ci switch (ms_read_readpage(us, PhyBlock, PageNumber, (u32 *)PageBuffer, &ExtraData)) { 10138c2ecf20Sopenharmony_ci case MS_STATUS_SUCCESS: 10148c2ecf20Sopenharmony_ci break; 10158c2ecf20Sopenharmony_ci case MS_STATUS_WRITE_PROTECT: 10168c2ecf20Sopenharmony_ci case MS_ERROR_FLASH_READ: 10178c2ecf20Sopenharmony_ci case MS_STATUS_ERROR: 10188c2ecf20Sopenharmony_ci default: 10198c2ecf20Sopenharmony_ci goto exit; 10208c2ecf20Sopenharmony_ci } 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci PrevPageNumber = PageNumber; 10238c2ecf20Sopenharmony_ci } 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci phyblk = be16_to_cpu(*(u16 *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE))); 10268c2ecf20Sopenharmony_ci if (phyblk < 0x0fff) 10278c2ecf20Sopenharmony_ci ms_lib_set_initialerrorblock(us, phyblk); 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci EntryOffset += 2; 10308c2ecf20Sopenharmony_ci EntrySize -= 2; 10318c2ecf20Sopenharmony_ci } 10328c2ecf20Sopenharmony_ci } else if (i == 1) { /* CIS/IDI */ 10338c2ecf20Sopenharmony_ci struct ms_bootblock_idi *idi; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_CIS_IDI) 10368c2ecf20Sopenharmony_ci goto exit; 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci switch (ms_read_readpage(us, PhyBlock, (u8)(EntryOffset / MS_BYTES_PER_PAGE + 1), (u32 *)PageBuffer, &ExtraData)) { 10398c2ecf20Sopenharmony_ci case MS_STATUS_SUCCESS: 10408c2ecf20Sopenharmony_ci break; 10418c2ecf20Sopenharmony_ci case MS_STATUS_WRITE_PROTECT: 10428c2ecf20Sopenharmony_ci case MS_ERROR_FLASH_READ: 10438c2ecf20Sopenharmony_ci case MS_STATUS_ERROR: 10448c2ecf20Sopenharmony_ci default: 10458c2ecf20Sopenharmony_ci goto exit; 10468c2ecf20Sopenharmony_ci } 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci idi = &((struct ms_bootblock_cis_idi *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)))->idi.idi; 10498c2ecf20Sopenharmony_ci if (le16_to_cpu(idi->wIDIgeneralConfiguration) != MS_IDI_GENERAL_CONF) 10508c2ecf20Sopenharmony_ci goto exit; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci info->MS_Lib.BytesPerSector = le16_to_cpu(idi->wIDIbytesPerSector); 10538c2ecf20Sopenharmony_ci if (info->MS_Lib.BytesPerSector != MS_BYTES_PER_PAGE) 10548c2ecf20Sopenharmony_ci goto exit; 10558c2ecf20Sopenharmony_ci } 10568c2ecf20Sopenharmony_ci } /* End for .. */ 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci result = 0; 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ciexit: 10618c2ecf20Sopenharmony_ci if (result) 10628c2ecf20Sopenharmony_ci ms_lib_free_logicalmap(us); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci kfree(PageBuffer); 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci result = 0; 10678c2ecf20Sopenharmony_ci return result; 10688c2ecf20Sopenharmony_ci} 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_cistatic void ms_lib_free_writebuf(struct us_data *us) 10718c2ecf20Sopenharmony_ci{ 10728c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 10738c2ecf20Sopenharmony_ci info->MS_Lib.wrtblk = (u16)-1; /* set to -1 */ 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci /* memset((fdoExt)->MS_Lib.pagemap, 0, sizeof((fdoExt)->MS_Lib.pagemap)) */ 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci ms_lib_clear_pagemap(info); /* (pdx)->MS_Lib.pagemap memset 0 in ms.h */ 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci if (info->MS_Lib.blkpag) { 10808c2ecf20Sopenharmony_ci kfree(info->MS_Lib.blkpag); /* Arnold test ... */ 10818c2ecf20Sopenharmony_ci info->MS_Lib.blkpag = NULL; 10828c2ecf20Sopenharmony_ci } 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci if (info->MS_Lib.blkext) { 10858c2ecf20Sopenharmony_ci kfree(info->MS_Lib.blkext); /* Arnold test ... */ 10868c2ecf20Sopenharmony_ci info->MS_Lib.blkext = NULL; 10878c2ecf20Sopenharmony_ci } 10888c2ecf20Sopenharmony_ci} 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_cistatic void ms_lib_free_allocatedarea(struct us_data *us) 10928c2ecf20Sopenharmony_ci{ 10938c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci ms_lib_free_writebuf(us); /* Free MS_Lib.pagemap */ 10968c2ecf20Sopenharmony_ci ms_lib_free_logicalmap(us); /* kfree MS_Lib.Phy2LogMap and MS_Lib.Log2PhyMap */ 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci /* set struct us point flag to 0 */ 10998c2ecf20Sopenharmony_ci info->MS_Lib.flags = 0; 11008c2ecf20Sopenharmony_ci info->MS_Lib.BytesPerSector = 0; 11018c2ecf20Sopenharmony_ci info->MS_Lib.SectorsPerCylinder = 0; 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci info->MS_Lib.cardType = 0; 11048c2ecf20Sopenharmony_ci info->MS_Lib.blockSize = 0; 11058c2ecf20Sopenharmony_ci info->MS_Lib.PagesPerBlock = 0; 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci info->MS_Lib.NumberOfPhyBlock = 0; 11088c2ecf20Sopenharmony_ci info->MS_Lib.NumberOfLogBlock = 0; 11098c2ecf20Sopenharmony_ci} 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_cistatic int ms_lib_alloc_writebuf(struct us_data *us) 11138c2ecf20Sopenharmony_ci{ 11148c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci info->MS_Lib.wrtblk = (u16)-1; 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci info->MS_Lib.blkpag = kmalloc_array(info->MS_Lib.PagesPerBlock, 11198c2ecf20Sopenharmony_ci info->MS_Lib.BytesPerSector, 11208c2ecf20Sopenharmony_ci GFP_KERNEL); 11218c2ecf20Sopenharmony_ci info->MS_Lib.blkext = kmalloc_array(info->MS_Lib.PagesPerBlock, 11228c2ecf20Sopenharmony_ci sizeof(struct ms_lib_type_extdat), 11238c2ecf20Sopenharmony_ci GFP_KERNEL); 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci if ((info->MS_Lib.blkpag == NULL) || (info->MS_Lib.blkext == NULL)) { 11268c2ecf20Sopenharmony_ci ms_lib_free_writebuf(us); 11278c2ecf20Sopenharmony_ci return (u32)-1; 11288c2ecf20Sopenharmony_ci } 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci ms_lib_clear_writebuf(us); 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci return 0; 11338c2ecf20Sopenharmony_ci} 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_cistatic int ms_lib_force_setlogical_pair(struct us_data *us, u16 logblk, u16 phyblk) 11368c2ecf20Sopenharmony_ci{ 11378c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci if (logblk == MS_LB_NOT_USED) 11408c2ecf20Sopenharmony_ci return 0; 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci if ((logblk >= info->MS_Lib.NumberOfLogBlock) || 11438c2ecf20Sopenharmony_ci (phyblk >= info->MS_Lib.NumberOfPhyBlock)) 11448c2ecf20Sopenharmony_ci return (u32)-1; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap[phyblk] = logblk; 11478c2ecf20Sopenharmony_ci info->MS_Lib.Log2PhyMap[logblk] = phyblk; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci return 0; 11508c2ecf20Sopenharmony_ci} 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_cistatic int ms_read_copyblock(struct us_data *us, u16 oldphy, u16 newphy, 11538c2ecf20Sopenharmony_ci u16 PhyBlockAddr, u8 PageNum, unsigned char *buf, u16 len) 11548c2ecf20Sopenharmony_ci{ 11558c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 11568c2ecf20Sopenharmony_ci int result; 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci result = ene_load_bincode(us, MS_RW_PATTERN); 11598c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 11608c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 11638c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 11648c2ecf20Sopenharmony_ci bcb->DataTransferLength = 0x200*len; 11658c2ecf20Sopenharmony_ci bcb->Flags = 0x00; 11668c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF0; 11678c2ecf20Sopenharmony_ci bcb->CDB[1] = 0x08; 11688c2ecf20Sopenharmony_ci bcb->CDB[4] = (unsigned char)(oldphy); 11698c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)(oldphy>>8); 11708c2ecf20Sopenharmony_ci bcb->CDB[2] = 0; /* (BYTE)(oldphy>>16) */ 11718c2ecf20Sopenharmony_ci bcb->CDB[7] = (unsigned char)(newphy); 11728c2ecf20Sopenharmony_ci bcb->CDB[6] = (unsigned char)(newphy>>8); 11738c2ecf20Sopenharmony_ci bcb->CDB[5] = 0; /* (BYTE)(newphy>>16) */ 11748c2ecf20Sopenharmony_ci bcb->CDB[9] = (unsigned char)(PhyBlockAddr); 11758c2ecf20Sopenharmony_ci bcb->CDB[8] = (unsigned char)(PhyBlockAddr>>8); 11768c2ecf20Sopenharmony_ci bcb->CDB[10] = PageNum; 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0); 11798c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 11808c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 11838c2ecf20Sopenharmony_ci} 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_cistatic int ms_read_eraseblock(struct us_data *us, u32 PhyBlockAddr) 11868c2ecf20Sopenharmony_ci{ 11878c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 11888c2ecf20Sopenharmony_ci int result; 11898c2ecf20Sopenharmony_ci u32 bn = PhyBlockAddr; 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci result = ene_load_bincode(us, MS_RW_PATTERN); 11928c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 11938c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 11968c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 11978c2ecf20Sopenharmony_ci bcb->DataTransferLength = 0x200; 11988c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 11998c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF2; 12008c2ecf20Sopenharmony_ci bcb->CDB[1] = 0x06; 12018c2ecf20Sopenharmony_ci bcb->CDB[4] = (unsigned char)(bn); 12028c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)(bn>>8); 12038c2ecf20Sopenharmony_ci bcb->CDB[2] = (unsigned char)(bn>>16); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0); 12068c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 12078c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 12108c2ecf20Sopenharmony_ci} 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_cistatic int ms_lib_check_disableblock(struct us_data *us, u16 PhyBlock) 12138c2ecf20Sopenharmony_ci{ 12148c2ecf20Sopenharmony_ci unsigned char *PageBuf = NULL; 12158c2ecf20Sopenharmony_ci u16 result = MS_STATUS_SUCCESS; 12168c2ecf20Sopenharmony_ci u16 blk, index = 0; 12178c2ecf20Sopenharmony_ci struct ms_lib_type_extdat extdat; 12188c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci PageBuf = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL); 12218c2ecf20Sopenharmony_ci if (PageBuf == NULL) { 12228c2ecf20Sopenharmony_ci result = MS_NO_MEMORY_ERROR; 12238c2ecf20Sopenharmony_ci goto exit; 12248c2ecf20Sopenharmony_ci } 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci ms_read_readpage(us, PhyBlock, 1, (u32 *)PageBuf, &extdat); 12278c2ecf20Sopenharmony_ci do { 12288c2ecf20Sopenharmony_ci blk = be16_to_cpu(PageBuf[index]); 12298c2ecf20Sopenharmony_ci if (blk == MS_LB_NOT_USED) 12308c2ecf20Sopenharmony_ci break; 12318c2ecf20Sopenharmony_ci if (blk == info->MS_Lib.Log2PhyMap[0]) { 12328c2ecf20Sopenharmony_ci result = MS_ERROR_FLASH_READ; 12338c2ecf20Sopenharmony_ci break; 12348c2ecf20Sopenharmony_ci } 12358c2ecf20Sopenharmony_ci index++; 12368c2ecf20Sopenharmony_ci } while (1); 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ciexit: 12398c2ecf20Sopenharmony_ci kfree(PageBuf); 12408c2ecf20Sopenharmony_ci return result; 12418c2ecf20Sopenharmony_ci} 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_cistatic int ms_lib_setacquired_errorblock(struct us_data *us, u16 phyblk) 12448c2ecf20Sopenharmony_ci{ 12458c2ecf20Sopenharmony_ci u16 log; 12468c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci if (phyblk >= info->MS_Lib.NumberOfPhyBlock) 12498c2ecf20Sopenharmony_ci return (u32)-1; 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci log = info->MS_Lib.Phy2LogMap[phyblk]; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci if (log < info->MS_Lib.NumberOfLogBlock) 12548c2ecf20Sopenharmony_ci info->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED; 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci if (info->MS_Lib.Phy2LogMap[phyblk] != MS_LB_INITIAL_ERROR) 12578c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap[phyblk] = MS_LB_ACQUIRED_ERROR; 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci return 0; 12608c2ecf20Sopenharmony_ci} 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_cistatic int ms_lib_overwrite_extra(struct us_data *us, u32 PhyBlockAddr, 12638c2ecf20Sopenharmony_ci u8 PageNum, u8 OverwriteFlag) 12648c2ecf20Sopenharmony_ci{ 12658c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 12668c2ecf20Sopenharmony_ci int result; 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci result = ene_load_bincode(us, MS_RW_PATTERN); 12698c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 12708c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 12738c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 12748c2ecf20Sopenharmony_ci bcb->DataTransferLength = 0x4; 12758c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 12768c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF2; 12778c2ecf20Sopenharmony_ci bcb->CDB[1] = 0x05; 12788c2ecf20Sopenharmony_ci bcb->CDB[5] = (unsigned char)(PageNum); 12798c2ecf20Sopenharmony_ci bcb->CDB[4] = (unsigned char)(PhyBlockAddr); 12808c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)(PhyBlockAddr>>8); 12818c2ecf20Sopenharmony_ci bcb->CDB[2] = (unsigned char)(PhyBlockAddr>>16); 12828c2ecf20Sopenharmony_ci bcb->CDB[6] = OverwriteFlag; 12838c2ecf20Sopenharmony_ci bcb->CDB[7] = 0xFF; 12848c2ecf20Sopenharmony_ci bcb->CDB[8] = 0xFF; 12858c2ecf20Sopenharmony_ci bcb->CDB[9] = 0xFF; 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0); 12888c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 12898c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 12928c2ecf20Sopenharmony_ci} 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_cistatic int ms_lib_error_phyblock(struct us_data *us, u16 phyblk) 12958c2ecf20Sopenharmony_ci{ 12968c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci if (phyblk >= info->MS_Lib.NumberOfPhyBlock) 12998c2ecf20Sopenharmony_ci return MS_STATUS_ERROR; 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci ms_lib_setacquired_errorblock(us, phyblk); 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci if (ms_lib_iswritable(info)) 13048c2ecf20Sopenharmony_ci return ms_lib_overwrite_extra(us, phyblk, 0, (u8)(~MS_REG_OVR_BKST & BYTE_MASK)); 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci return MS_STATUS_SUCCESS; 13078c2ecf20Sopenharmony_ci} 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_cistatic int ms_lib_erase_phyblock(struct us_data *us, u16 phyblk) 13108c2ecf20Sopenharmony_ci{ 13118c2ecf20Sopenharmony_ci u16 log; 13128c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci if (phyblk >= info->MS_Lib.NumberOfPhyBlock) 13158c2ecf20Sopenharmony_ci return MS_STATUS_ERROR; 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci log = info->MS_Lib.Phy2LogMap[phyblk]; 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci if (log < info->MS_Lib.NumberOfLogBlock) 13208c2ecf20Sopenharmony_ci info->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED; 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED; 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci if (ms_lib_iswritable(info)) { 13258c2ecf20Sopenharmony_ci switch (ms_read_eraseblock(us, phyblk)) { 13268c2ecf20Sopenharmony_ci case MS_STATUS_SUCCESS: 13278c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED_ERASED; 13288c2ecf20Sopenharmony_ci return MS_STATUS_SUCCESS; 13298c2ecf20Sopenharmony_ci case MS_ERROR_FLASH_ERASE: 13308c2ecf20Sopenharmony_ci case MS_STATUS_INT_ERROR: 13318c2ecf20Sopenharmony_ci ms_lib_error_phyblock(us, phyblk); 13328c2ecf20Sopenharmony_ci return MS_ERROR_FLASH_ERASE; 13338c2ecf20Sopenharmony_ci case MS_STATUS_ERROR: 13348c2ecf20Sopenharmony_ci default: 13358c2ecf20Sopenharmony_ci ms_lib_ctrl_set(info, MS_LIB_CTRL_RDONLY); /* MS_LibCtrlSet will used by ENE_MSInit ,need check, and why us to info*/ 13368c2ecf20Sopenharmony_ci ms_lib_setacquired_errorblock(us, phyblk); 13378c2ecf20Sopenharmony_ci return MS_STATUS_ERROR; 13388c2ecf20Sopenharmony_ci } 13398c2ecf20Sopenharmony_ci } 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci ms_lib_setacquired_errorblock(us, phyblk); 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci return MS_STATUS_SUCCESS; 13448c2ecf20Sopenharmony_ci} 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_cistatic int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, 13478c2ecf20Sopenharmony_ci u8 PageNum, struct ms_lib_type_extdat *ExtraDat) 13488c2ecf20Sopenharmony_ci{ 13498c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 13508c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 13518c2ecf20Sopenharmony_ci u8 *bbuf = info->bbuf; 13528c2ecf20Sopenharmony_ci int result; 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 13558c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 13568c2ecf20Sopenharmony_ci bcb->DataTransferLength = 0x4; 13578c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 13588c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF1; 13598c2ecf20Sopenharmony_ci bcb->CDB[1] = 0x03; 13608c2ecf20Sopenharmony_ci bcb->CDB[5] = (unsigned char)(PageNum); 13618c2ecf20Sopenharmony_ci bcb->CDB[4] = (unsigned char)(PhyBlock); 13628c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)(PhyBlock>>8); 13638c2ecf20Sopenharmony_ci bcb->CDB[2] = (unsigned char)(PhyBlock>>16); 13648c2ecf20Sopenharmony_ci bcb->CDB[6] = 0x01; 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); 13678c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 13688c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci ExtraDat->reserved = 0; 13718c2ecf20Sopenharmony_ci ExtraDat->intr = 0x80; /* Not yet, waiting for fireware support */ 13728c2ecf20Sopenharmony_ci ExtraDat->status0 = 0x10; /* Not yet, waiting for fireware support */ 13738c2ecf20Sopenharmony_ci ExtraDat->status1 = 0x00; /* Not yet, waiting for fireware support */ 13748c2ecf20Sopenharmony_ci ExtraDat->ovrflg = bbuf[0]; 13758c2ecf20Sopenharmony_ci ExtraDat->mngflg = bbuf[1]; 13768c2ecf20Sopenharmony_ci ExtraDat->logadr = memstick_logaddr(bbuf[2], bbuf[3]); 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 13798c2ecf20Sopenharmony_ci} 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_cistatic int ms_libsearch_block_from_physical(struct us_data *us, u16 phyblk) 13828c2ecf20Sopenharmony_ci{ 13838c2ecf20Sopenharmony_ci u16 blk; 13848c2ecf20Sopenharmony_ci struct ms_lib_type_extdat extdat; /* need check */ 13858c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci if (phyblk >= info->MS_Lib.NumberOfPhyBlock) 13898c2ecf20Sopenharmony_ci return MS_LB_ERROR; 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci for (blk = phyblk + 1; blk != phyblk; blk++) { 13928c2ecf20Sopenharmony_ci if ((blk & MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK) == 0) 13938c2ecf20Sopenharmony_ci blk -= MS_PHYSICAL_BLOCKS_PER_SEGMENT; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci if (info->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED_ERASED) { 13968c2ecf20Sopenharmony_ci return blk; 13978c2ecf20Sopenharmony_ci } else if (info->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED) { 13988c2ecf20Sopenharmony_ci switch (ms_lib_read_extra(us, blk, 0, &extdat)) { 13998c2ecf20Sopenharmony_ci case MS_STATUS_SUCCESS: 14008c2ecf20Sopenharmony_ci case MS_STATUS_SUCCESS_WITH_ECC: 14018c2ecf20Sopenharmony_ci break; 14028c2ecf20Sopenharmony_ci case MS_NOCARD_ERROR: 14038c2ecf20Sopenharmony_ci return MS_NOCARD_ERROR; 14048c2ecf20Sopenharmony_ci case MS_STATUS_INT_ERROR: 14058c2ecf20Sopenharmony_ci return MS_LB_ERROR; 14068c2ecf20Sopenharmony_ci case MS_ERROR_FLASH_READ: 14078c2ecf20Sopenharmony_ci default: 14088c2ecf20Sopenharmony_ci ms_lib_setacquired_errorblock(us, blk); 14098c2ecf20Sopenharmony_ci continue; 14108c2ecf20Sopenharmony_ci } /* End switch */ 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) { 14138c2ecf20Sopenharmony_ci ms_lib_setacquired_errorblock(us, blk); 14148c2ecf20Sopenharmony_ci continue; 14158c2ecf20Sopenharmony_ci } 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci switch (ms_lib_erase_phyblock(us, blk)) { 14188c2ecf20Sopenharmony_ci case MS_STATUS_SUCCESS: 14198c2ecf20Sopenharmony_ci return blk; 14208c2ecf20Sopenharmony_ci case MS_STATUS_ERROR: 14218c2ecf20Sopenharmony_ci return MS_LB_ERROR; 14228c2ecf20Sopenharmony_ci case MS_ERROR_FLASH_ERASE: 14238c2ecf20Sopenharmony_ci default: 14248c2ecf20Sopenharmony_ci ms_lib_error_phyblock(us, blk); 14258c2ecf20Sopenharmony_ci break; 14268c2ecf20Sopenharmony_ci } 14278c2ecf20Sopenharmony_ci } 14288c2ecf20Sopenharmony_ci } /* End for */ 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci return MS_LB_ERROR; 14318c2ecf20Sopenharmony_ci} 14328c2ecf20Sopenharmony_cistatic int ms_libsearch_block_from_logical(struct us_data *us, u16 logblk) 14338c2ecf20Sopenharmony_ci{ 14348c2ecf20Sopenharmony_ci u16 phyblk; 14358c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci phyblk = ms_libconv_to_physical(info, logblk); 14388c2ecf20Sopenharmony_ci if (phyblk >= MS_LB_ERROR) { 14398c2ecf20Sopenharmony_ci if (logblk >= info->MS_Lib.NumberOfLogBlock) 14408c2ecf20Sopenharmony_ci return MS_LB_ERROR; 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ci phyblk = (logblk + MS_NUMBER_OF_BOOT_BLOCK) / MS_LOGICAL_BLOCKS_PER_SEGMENT; 14438c2ecf20Sopenharmony_ci phyblk *= MS_PHYSICAL_BLOCKS_PER_SEGMENT; 14448c2ecf20Sopenharmony_ci phyblk += MS_PHYSICAL_BLOCKS_PER_SEGMENT - 1; 14458c2ecf20Sopenharmony_ci } 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci return ms_libsearch_block_from_physical(us, phyblk); 14488c2ecf20Sopenharmony_ci} 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_cistatic int ms_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb) 14518c2ecf20Sopenharmony_ci{ 14528c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci /* pr_info("MS_SCSI_Test_Unit_Ready\n"); */ 14558c2ecf20Sopenharmony_ci if ((info->MS_Status & MS_Insert) && (info->MS_Status & MS_Ready)) { 14568c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 14578c2ecf20Sopenharmony_ci } else { 14588c2ecf20Sopenharmony_ci ene_ms_init(us); 14598c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 14608c2ecf20Sopenharmony_ci } 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 14638c2ecf20Sopenharmony_ci} 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_cistatic int ms_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb) 14668c2ecf20Sopenharmony_ci{ 14678c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 14688c2ecf20Sopenharmony_ci unsigned char mediaNoWP[12] = { 14698c2ecf20Sopenharmony_ci 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 14708c2ecf20Sopenharmony_ci 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 }; 14718c2ecf20Sopenharmony_ci unsigned char mediaWP[12] = { 14728c2ecf20Sopenharmony_ci 0x0b, 0x00, 0x80, 0x08, 0x00, 0x00, 14738c2ecf20Sopenharmony_ci 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 }; 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci if (info->MS_Status & MS_WtP) 14768c2ecf20Sopenharmony_ci usb_stor_set_xfer_buf(mediaWP, 12, srb); 14778c2ecf20Sopenharmony_ci else 14788c2ecf20Sopenharmony_ci usb_stor_set_xfer_buf(mediaNoWP, 12, srb); 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 14818c2ecf20Sopenharmony_ci} 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_cistatic int ms_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb) 14848c2ecf20Sopenharmony_ci{ 14858c2ecf20Sopenharmony_ci u32 bl_num; 14868c2ecf20Sopenharmony_ci u16 bl_len; 14878c2ecf20Sopenharmony_ci unsigned int offset = 0; 14888c2ecf20Sopenharmony_ci unsigned char buf[8]; 14898c2ecf20Sopenharmony_ci struct scatterlist *sg = NULL; 14908c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci usb_stor_dbg(us, "ms_scsi_read_capacity\n"); 14938c2ecf20Sopenharmony_ci bl_len = 0x200; 14948c2ecf20Sopenharmony_ci if (info->MS_Status & MS_IsMSPro) 14958c2ecf20Sopenharmony_ci bl_num = info->MSP_TotalBlock - 1; 14968c2ecf20Sopenharmony_ci else 14978c2ecf20Sopenharmony_ci bl_num = info->MS_Lib.NumberOfLogBlock * info->MS_Lib.blockSize * 2 - 1; 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_ci info->bl_num = bl_num; 15008c2ecf20Sopenharmony_ci usb_stor_dbg(us, "bl_len = %x\n", bl_len); 15018c2ecf20Sopenharmony_ci usb_stor_dbg(us, "bl_num = %x\n", bl_num); 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci /*srb->request_bufflen = 8; */ 15048c2ecf20Sopenharmony_ci buf[0] = (bl_num >> 24) & 0xff; 15058c2ecf20Sopenharmony_ci buf[1] = (bl_num >> 16) & 0xff; 15068c2ecf20Sopenharmony_ci buf[2] = (bl_num >> 8) & 0xff; 15078c2ecf20Sopenharmony_ci buf[3] = (bl_num >> 0) & 0xff; 15088c2ecf20Sopenharmony_ci buf[4] = (bl_len >> 24) & 0xff; 15098c2ecf20Sopenharmony_ci buf[5] = (bl_len >> 16) & 0xff; 15108c2ecf20Sopenharmony_ci buf[6] = (bl_len >> 8) & 0xff; 15118c2ecf20Sopenharmony_ci buf[7] = (bl_len >> 0) & 0xff; 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_ci usb_stor_access_xfer_buf(buf, 8, srb, &sg, &offset, TO_XFER_BUF); 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 15168c2ecf20Sopenharmony_ci} 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_cistatic void ms_lib_phy_to_log_range(u16 PhyBlock, u16 *LogStart, u16 *LogEnde) 15198c2ecf20Sopenharmony_ci{ 15208c2ecf20Sopenharmony_ci PhyBlock /= MS_PHYSICAL_BLOCKS_PER_SEGMENT; 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci if (PhyBlock) { 15238c2ecf20Sopenharmony_ci *LogStart = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT + (PhyBlock - 1) * MS_LOGICAL_BLOCKS_PER_SEGMENT;/*496*/ 15248c2ecf20Sopenharmony_ci *LogEnde = *LogStart + MS_LOGICAL_BLOCKS_PER_SEGMENT;/*496*/ 15258c2ecf20Sopenharmony_ci } else { 15268c2ecf20Sopenharmony_ci *LogStart = 0; 15278c2ecf20Sopenharmony_ci *LogEnde = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT;/*494*/ 15288c2ecf20Sopenharmony_ci } 15298c2ecf20Sopenharmony_ci} 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_cistatic int ms_lib_read_extrablock(struct us_data *us, u32 PhyBlock, 15328c2ecf20Sopenharmony_ci u8 PageNum, u8 blen, void *buf) 15338c2ecf20Sopenharmony_ci{ 15348c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 15358c2ecf20Sopenharmony_ci int result; 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci /* Read Extra Data */ 15388c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 15398c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 15408c2ecf20Sopenharmony_ci bcb->DataTransferLength = 0x4 * blen; 15418c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 15428c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF1; 15438c2ecf20Sopenharmony_ci bcb->CDB[1] = 0x03; 15448c2ecf20Sopenharmony_ci bcb->CDB[5] = (unsigned char)(PageNum); 15458c2ecf20Sopenharmony_ci bcb->CDB[4] = (unsigned char)(PhyBlock); 15468c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)(PhyBlock>>8); 15478c2ecf20Sopenharmony_ci bcb->CDB[2] = (unsigned char)(PhyBlock>>16); 15488c2ecf20Sopenharmony_ci bcb->CDB[6] = blen; 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, buf, 0); 15518c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 15528c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 15558c2ecf20Sopenharmony_ci} 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_cistatic int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st) 15588c2ecf20Sopenharmony_ci{ 15598c2ecf20Sopenharmony_ci u16 PhyBlock, newblk, i; 15608c2ecf20Sopenharmony_ci u16 LogStart, LogEnde; 15618c2ecf20Sopenharmony_ci struct ms_lib_type_extdat extdat; 15628c2ecf20Sopenharmony_ci u32 count = 0, index = 0; 15638c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 15648c2ecf20Sopenharmony_ci u8 *bbuf = info->bbuf; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci for (PhyBlock = 0; PhyBlock < info->MS_Lib.NumberOfPhyBlock;) { 15678c2ecf20Sopenharmony_ci ms_lib_phy_to_log_range(PhyBlock, &LogStart, &LogEnde); 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci for (i = 0; i < MS_PHYSICAL_BLOCKS_PER_SEGMENT; i++, PhyBlock++) { 15708c2ecf20Sopenharmony_ci switch (ms_libconv_to_logical(info, PhyBlock)) { 15718c2ecf20Sopenharmony_ci case MS_STATUS_ERROR: 15728c2ecf20Sopenharmony_ci continue; 15738c2ecf20Sopenharmony_ci default: 15748c2ecf20Sopenharmony_ci break; 15758c2ecf20Sopenharmony_ci } 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci if (count == PhyBlock) { 15788c2ecf20Sopenharmony_ci ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, 15798c2ecf20Sopenharmony_ci bbuf); 15808c2ecf20Sopenharmony_ci count += 0x80; 15818c2ecf20Sopenharmony_ci } 15828c2ecf20Sopenharmony_ci index = (PhyBlock % 0x80) * 4; 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci extdat.ovrflg = bbuf[index]; 15858c2ecf20Sopenharmony_ci extdat.mngflg = bbuf[index+1]; 15868c2ecf20Sopenharmony_ci extdat.logadr = memstick_logaddr(bbuf[index+2], 15878c2ecf20Sopenharmony_ci bbuf[index+3]); 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) { 15908c2ecf20Sopenharmony_ci ms_lib_setacquired_errorblock(us, PhyBlock); 15918c2ecf20Sopenharmony_ci continue; 15928c2ecf20Sopenharmony_ci } 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci if ((extdat.mngflg & MS_REG_MNG_ATFLG) == MS_REG_MNG_ATFLG_ATTBL) { 15958c2ecf20Sopenharmony_ci ms_lib_erase_phyblock(us, PhyBlock); 15968c2ecf20Sopenharmony_ci continue; 15978c2ecf20Sopenharmony_ci } 15988c2ecf20Sopenharmony_ci 15998c2ecf20Sopenharmony_ci if (extdat.logadr != MS_LB_NOT_USED) { 16008c2ecf20Sopenharmony_ci if ((extdat.logadr < LogStart) || (LogEnde <= extdat.logadr)) { 16018c2ecf20Sopenharmony_ci ms_lib_erase_phyblock(us, PhyBlock); 16028c2ecf20Sopenharmony_ci continue; 16038c2ecf20Sopenharmony_ci } 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci newblk = ms_libconv_to_physical(info, extdat.logadr); 16068c2ecf20Sopenharmony_ci 16078c2ecf20Sopenharmony_ci if (newblk != MS_LB_NOT_USED) { 16088c2ecf20Sopenharmony_ci if (extdat.logadr == 0) { 16098c2ecf20Sopenharmony_ci ms_lib_set_logicalpair(us, extdat.logadr, PhyBlock); 16108c2ecf20Sopenharmony_ci if (ms_lib_check_disableblock(us, btBlk1st)) { 16118c2ecf20Sopenharmony_ci ms_lib_set_logicalpair(us, extdat.logadr, newblk); 16128c2ecf20Sopenharmony_ci continue; 16138c2ecf20Sopenharmony_ci } 16148c2ecf20Sopenharmony_ci } 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci ms_lib_read_extra(us, newblk, 0, &extdat); 16178c2ecf20Sopenharmony_ci if ((extdat.ovrflg & MS_REG_OVR_UDST) == MS_REG_OVR_UDST_UPDATING) { 16188c2ecf20Sopenharmony_ci ms_lib_erase_phyblock(us, PhyBlock); 16198c2ecf20Sopenharmony_ci continue; 16208c2ecf20Sopenharmony_ci } else { 16218c2ecf20Sopenharmony_ci ms_lib_erase_phyblock(us, newblk); 16228c2ecf20Sopenharmony_ci } 16238c2ecf20Sopenharmony_ci } 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_ci ms_lib_set_logicalpair(us, extdat.logadr, PhyBlock); 16268c2ecf20Sopenharmony_ci } 16278c2ecf20Sopenharmony_ci } 16288c2ecf20Sopenharmony_ci } /* End for ... */ 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ci return MS_STATUS_SUCCESS; 16318c2ecf20Sopenharmony_ci} 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_cistatic int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb) 16358c2ecf20Sopenharmony_ci{ 16368c2ecf20Sopenharmony_ci int result; 16378c2ecf20Sopenharmony_ci unsigned char *cdb = srb->cmnd; 16388c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 16398c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) | 16428c2ecf20Sopenharmony_ci ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff); 16438c2ecf20Sopenharmony_ci u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff); 16448c2ecf20Sopenharmony_ci u32 blenByte = blen * 0x200; 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci if (bn > info->bl_num) 16478c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci if (info->MS_Status & MS_IsMSPro) { 16508c2ecf20Sopenharmony_ci result = ene_load_bincode(us, MSP_RW_PATTERN); 16518c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 16528c2ecf20Sopenharmony_ci usb_stor_dbg(us, "Load MPS RW pattern Fail !!\n"); 16538c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 16548c2ecf20Sopenharmony_ci } 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_ci /* set up the command wrapper */ 16578c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 16588c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 16598c2ecf20Sopenharmony_ci bcb->DataTransferLength = blenByte; 16608c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 16618c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF1; 16628c2ecf20Sopenharmony_ci bcb->CDB[1] = 0x02; 16638c2ecf20Sopenharmony_ci bcb->CDB[5] = (unsigned char)(bn); 16648c2ecf20Sopenharmony_ci bcb->CDB[4] = (unsigned char)(bn>>8); 16658c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)(bn>>16); 16668c2ecf20Sopenharmony_ci bcb->CDB[2] = (unsigned char)(bn>>24); 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, scsi_sglist(srb), 1); 16698c2ecf20Sopenharmony_ci } else { 16708c2ecf20Sopenharmony_ci void *buf; 16718c2ecf20Sopenharmony_ci int offset = 0; 16728c2ecf20Sopenharmony_ci u16 phyblk, logblk; 16738c2ecf20Sopenharmony_ci u8 PageNum; 16748c2ecf20Sopenharmony_ci u16 len; 16758c2ecf20Sopenharmony_ci u32 blkno; 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci buf = kmalloc(blenByte, GFP_KERNEL); 16788c2ecf20Sopenharmony_ci if (buf == NULL) 16798c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci result = ene_load_bincode(us, MS_RW_PATTERN); 16828c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 16838c2ecf20Sopenharmony_ci pr_info("Load MS RW pattern Fail !!\n"); 16848c2ecf20Sopenharmony_ci result = USB_STOR_TRANSPORT_ERROR; 16858c2ecf20Sopenharmony_ci goto exit; 16868c2ecf20Sopenharmony_ci } 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci logblk = (u16)(bn / info->MS_Lib.PagesPerBlock); 16898c2ecf20Sopenharmony_ci PageNum = (u8)(bn % info->MS_Lib.PagesPerBlock); 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci while (1) { 16928c2ecf20Sopenharmony_ci if (blen > (info->MS_Lib.PagesPerBlock-PageNum)) 16938c2ecf20Sopenharmony_ci len = info->MS_Lib.PagesPerBlock-PageNum; 16948c2ecf20Sopenharmony_ci else 16958c2ecf20Sopenharmony_ci len = blen; 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci phyblk = ms_libconv_to_physical(info, logblk); 16988c2ecf20Sopenharmony_ci blkno = phyblk * 0x20 + PageNum; 16998c2ecf20Sopenharmony_ci 17008c2ecf20Sopenharmony_ci /* set up the command wrapper */ 17018c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 17028c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 17038c2ecf20Sopenharmony_ci bcb->DataTransferLength = 0x200 * len; 17048c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 17058c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF1; 17068c2ecf20Sopenharmony_ci bcb->CDB[1] = 0x02; 17078c2ecf20Sopenharmony_ci bcb->CDB[5] = (unsigned char)(blkno); 17088c2ecf20Sopenharmony_ci bcb->CDB[4] = (unsigned char)(blkno>>8); 17098c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)(blkno>>16); 17108c2ecf20Sopenharmony_ci bcb->CDB[2] = (unsigned char)(blkno>>24); 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, buf+offset, 0); 17138c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 17148c2ecf20Sopenharmony_ci pr_info("MS_SCSI_Read --- result = %x\n", result); 17158c2ecf20Sopenharmony_ci result = USB_STOR_TRANSPORT_ERROR; 17168c2ecf20Sopenharmony_ci goto exit; 17178c2ecf20Sopenharmony_ci } 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci blen -= len; 17208c2ecf20Sopenharmony_ci if (blen <= 0) 17218c2ecf20Sopenharmony_ci break; 17228c2ecf20Sopenharmony_ci logblk++; 17238c2ecf20Sopenharmony_ci PageNum = 0; 17248c2ecf20Sopenharmony_ci offset += MS_BYTES_PER_PAGE*len; 17258c2ecf20Sopenharmony_ci } 17268c2ecf20Sopenharmony_ci usb_stor_set_xfer_buf(buf, blenByte, srb); 17278c2ecf20Sopenharmony_ciexit: 17288c2ecf20Sopenharmony_ci kfree(buf); 17298c2ecf20Sopenharmony_ci } 17308c2ecf20Sopenharmony_ci return result; 17318c2ecf20Sopenharmony_ci} 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_cistatic int ms_scsi_write(struct us_data *us, struct scsi_cmnd *srb) 17348c2ecf20Sopenharmony_ci{ 17358c2ecf20Sopenharmony_ci int result; 17368c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 17378c2ecf20Sopenharmony_ci unsigned char *cdb = srb->cmnd; 17388c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci u32 bn = ((cdb[2] << 24) & 0xff000000) | 17418c2ecf20Sopenharmony_ci ((cdb[3] << 16) & 0x00ff0000) | 17428c2ecf20Sopenharmony_ci ((cdb[4] << 8) & 0x0000ff00) | 17438c2ecf20Sopenharmony_ci ((cdb[5] << 0) & 0x000000ff); 17448c2ecf20Sopenharmony_ci u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff); 17458c2ecf20Sopenharmony_ci u32 blenByte = blen * 0x200; 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci if (bn > info->bl_num) 17488c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 17498c2ecf20Sopenharmony_ci 17508c2ecf20Sopenharmony_ci if (info->MS_Status & MS_IsMSPro) { 17518c2ecf20Sopenharmony_ci result = ene_load_bincode(us, MSP_RW_PATTERN); 17528c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 17538c2ecf20Sopenharmony_ci pr_info("Load MSP RW pattern Fail !!\n"); 17548c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 17558c2ecf20Sopenharmony_ci } 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci /* set up the command wrapper */ 17588c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 17598c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 17608c2ecf20Sopenharmony_ci bcb->DataTransferLength = blenByte; 17618c2ecf20Sopenharmony_ci bcb->Flags = 0x00; 17628c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF0; 17638c2ecf20Sopenharmony_ci bcb->CDB[1] = 0x04; 17648c2ecf20Sopenharmony_ci bcb->CDB[5] = (unsigned char)(bn); 17658c2ecf20Sopenharmony_ci bcb->CDB[4] = (unsigned char)(bn>>8); 17668c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)(bn>>16); 17678c2ecf20Sopenharmony_ci bcb->CDB[2] = (unsigned char)(bn>>24); 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1); 17708c2ecf20Sopenharmony_ci } else { 17718c2ecf20Sopenharmony_ci void *buf; 17728c2ecf20Sopenharmony_ci int offset = 0; 17738c2ecf20Sopenharmony_ci u16 PhyBlockAddr; 17748c2ecf20Sopenharmony_ci u8 PageNum; 17758c2ecf20Sopenharmony_ci u16 len, oldphy, newphy; 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci buf = kmalloc(blenByte, GFP_KERNEL); 17788c2ecf20Sopenharmony_ci if (buf == NULL) 17798c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 17808c2ecf20Sopenharmony_ci usb_stor_set_xfer_buf(buf, blenByte, srb); 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci result = ene_load_bincode(us, MS_RW_PATTERN); 17838c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 17848c2ecf20Sopenharmony_ci pr_info("Load MS RW pattern Fail !!\n"); 17858c2ecf20Sopenharmony_ci result = USB_STOR_TRANSPORT_ERROR; 17868c2ecf20Sopenharmony_ci goto exit; 17878c2ecf20Sopenharmony_ci } 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_ci PhyBlockAddr = (u16)(bn / info->MS_Lib.PagesPerBlock); 17908c2ecf20Sopenharmony_ci PageNum = (u8)(bn % info->MS_Lib.PagesPerBlock); 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci while (1) { 17938c2ecf20Sopenharmony_ci if (blen > (info->MS_Lib.PagesPerBlock-PageNum)) 17948c2ecf20Sopenharmony_ci len = info->MS_Lib.PagesPerBlock-PageNum; 17958c2ecf20Sopenharmony_ci else 17968c2ecf20Sopenharmony_ci len = blen; 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci oldphy = ms_libconv_to_physical(info, PhyBlockAddr); /* need check us <-> info */ 17998c2ecf20Sopenharmony_ci newphy = ms_libsearch_block_from_logical(us, PhyBlockAddr); 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci result = ms_read_copyblock(us, oldphy, newphy, PhyBlockAddr, PageNum, buf+offset, len); 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 18048c2ecf20Sopenharmony_ci pr_info("MS_SCSI_Write --- result = %x\n", result); 18058c2ecf20Sopenharmony_ci result = USB_STOR_TRANSPORT_ERROR; 18068c2ecf20Sopenharmony_ci goto exit; 18078c2ecf20Sopenharmony_ci } 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap[oldphy] = MS_LB_NOT_USED_ERASED; 18108c2ecf20Sopenharmony_ci ms_lib_force_setlogical_pair(us, PhyBlockAddr, newphy); 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci blen -= len; 18138c2ecf20Sopenharmony_ci if (blen <= 0) 18148c2ecf20Sopenharmony_ci break; 18158c2ecf20Sopenharmony_ci PhyBlockAddr++; 18168c2ecf20Sopenharmony_ci PageNum = 0; 18178c2ecf20Sopenharmony_ci offset += MS_BYTES_PER_PAGE*len; 18188c2ecf20Sopenharmony_ci } 18198c2ecf20Sopenharmony_ciexit: 18208c2ecf20Sopenharmony_ci kfree(buf); 18218c2ecf20Sopenharmony_ci } 18228c2ecf20Sopenharmony_ci return result; 18238c2ecf20Sopenharmony_ci} 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_ci/* 18268c2ecf20Sopenharmony_ci * ENE MS Card 18278c2ecf20Sopenharmony_ci */ 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_cistatic int ene_get_card_type(struct us_data *us, u16 index, void *buf) 18308c2ecf20Sopenharmony_ci{ 18318c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 18328c2ecf20Sopenharmony_ci int result; 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 18358c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 18368c2ecf20Sopenharmony_ci bcb->DataTransferLength = 0x01; 18378c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 18388c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xED; 18398c2ecf20Sopenharmony_ci bcb->CDB[2] = (unsigned char)(index>>8); 18408c2ecf20Sopenharmony_ci bcb->CDB[3] = (unsigned char)index; 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, buf, 0); 18438c2ecf20Sopenharmony_ci return result; 18448c2ecf20Sopenharmony_ci} 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_cistatic int ene_get_card_status(struct us_data *us, u8 *buf) 18478c2ecf20Sopenharmony_ci{ 18488c2ecf20Sopenharmony_ci u16 tmpreg; 18498c2ecf20Sopenharmony_ci u32 reg4b; 18508c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci /*usb_stor_dbg(us, "transport --- ENE_ReadSDReg\n");*/ 18538c2ecf20Sopenharmony_ci reg4b = *(u32 *)&buf[0x18]; 18548c2ecf20Sopenharmony_ci info->SD_READ_BL_LEN = (u8)((reg4b >> 8) & 0x0f); 18558c2ecf20Sopenharmony_ci 18568c2ecf20Sopenharmony_ci tmpreg = (u16) reg4b; 18578c2ecf20Sopenharmony_ci reg4b = *(u32 *)(&buf[0x14]); 18588c2ecf20Sopenharmony_ci if ((info->SD_Status & SD_HiCapacity) && !(info->SD_Status & SD_IsMMC)) 18598c2ecf20Sopenharmony_ci info->HC_C_SIZE = (reg4b >> 8) & 0x3fffff; 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci info->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (u16)(reg4b >> 22); 18628c2ecf20Sopenharmony_ci info->SD_C_SIZE_MULT = (u8)(reg4b >> 7) & 0x07; 18638c2ecf20Sopenharmony_ci if ((info->SD_Status & SD_HiCapacity) && (info->SD_Status & SD_IsMMC)) 18648c2ecf20Sopenharmony_ci info->HC_C_SIZE = *(u32 *)(&buf[0x100]); 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci if (info->SD_READ_BL_LEN > SD_BLOCK_LEN) { 18678c2ecf20Sopenharmony_ci info->SD_Block_Mult = 1 << (info->SD_READ_BL_LEN-SD_BLOCK_LEN); 18688c2ecf20Sopenharmony_ci info->SD_READ_BL_LEN = SD_BLOCK_LEN; 18698c2ecf20Sopenharmony_ci } else { 18708c2ecf20Sopenharmony_ci info->SD_Block_Mult = 1; 18718c2ecf20Sopenharmony_ci } 18728c2ecf20Sopenharmony_ci 18738c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 18748c2ecf20Sopenharmony_ci} 18758c2ecf20Sopenharmony_ci 18768c2ecf20Sopenharmony_cistatic int ene_load_bincode(struct us_data *us, unsigned char flag) 18778c2ecf20Sopenharmony_ci{ 18788c2ecf20Sopenharmony_ci int err; 18798c2ecf20Sopenharmony_ci char *fw_name = NULL; 18808c2ecf20Sopenharmony_ci unsigned char *buf = NULL; 18818c2ecf20Sopenharmony_ci const struct firmware *sd_fw = NULL; 18828c2ecf20Sopenharmony_ci int result = USB_STOR_TRANSPORT_ERROR; 18838c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 18848c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci if (info->BIN_FLAG == flag) 18878c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_ci switch (flag) { 18908c2ecf20Sopenharmony_ci /* For SD */ 18918c2ecf20Sopenharmony_ci case SD_INIT1_PATTERN: 18928c2ecf20Sopenharmony_ci usb_stor_dbg(us, "SD_INIT1_PATTERN\n"); 18938c2ecf20Sopenharmony_ci fw_name = SD_INIT1_FIRMWARE; 18948c2ecf20Sopenharmony_ci break; 18958c2ecf20Sopenharmony_ci case SD_INIT2_PATTERN: 18968c2ecf20Sopenharmony_ci usb_stor_dbg(us, "SD_INIT2_PATTERN\n"); 18978c2ecf20Sopenharmony_ci fw_name = SD_INIT2_FIRMWARE; 18988c2ecf20Sopenharmony_ci break; 18998c2ecf20Sopenharmony_ci case SD_RW_PATTERN: 19008c2ecf20Sopenharmony_ci usb_stor_dbg(us, "SD_RW_PATTERN\n"); 19018c2ecf20Sopenharmony_ci fw_name = SD_RW_FIRMWARE; 19028c2ecf20Sopenharmony_ci break; 19038c2ecf20Sopenharmony_ci /* For MS */ 19048c2ecf20Sopenharmony_ci case MS_INIT_PATTERN: 19058c2ecf20Sopenharmony_ci usb_stor_dbg(us, "MS_INIT_PATTERN\n"); 19068c2ecf20Sopenharmony_ci fw_name = MS_INIT_FIRMWARE; 19078c2ecf20Sopenharmony_ci break; 19088c2ecf20Sopenharmony_ci case MSP_RW_PATTERN: 19098c2ecf20Sopenharmony_ci usb_stor_dbg(us, "MSP_RW_PATTERN\n"); 19108c2ecf20Sopenharmony_ci fw_name = MSP_RW_FIRMWARE; 19118c2ecf20Sopenharmony_ci break; 19128c2ecf20Sopenharmony_ci case MS_RW_PATTERN: 19138c2ecf20Sopenharmony_ci usb_stor_dbg(us, "MS_RW_PATTERN\n"); 19148c2ecf20Sopenharmony_ci fw_name = MS_RW_FIRMWARE; 19158c2ecf20Sopenharmony_ci break; 19168c2ecf20Sopenharmony_ci default: 19178c2ecf20Sopenharmony_ci usb_stor_dbg(us, "----------- Unknown PATTERN ----------\n"); 19188c2ecf20Sopenharmony_ci goto nofw; 19198c2ecf20Sopenharmony_ci } 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_ci err = request_firmware(&sd_fw, fw_name, &us->pusb_dev->dev); 19228c2ecf20Sopenharmony_ci if (err) { 19238c2ecf20Sopenharmony_ci usb_stor_dbg(us, "load firmware %s failed\n", fw_name); 19248c2ecf20Sopenharmony_ci goto nofw; 19258c2ecf20Sopenharmony_ci } 19268c2ecf20Sopenharmony_ci buf = kmemdup(sd_fw->data, sd_fw->size, GFP_KERNEL); 19278c2ecf20Sopenharmony_ci if (buf == NULL) 19288c2ecf20Sopenharmony_ci goto nofw; 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 19318c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 19328c2ecf20Sopenharmony_ci bcb->DataTransferLength = sd_fw->size; 19338c2ecf20Sopenharmony_ci bcb->Flags = 0x00; 19348c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xEF; 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0); 19378c2ecf20Sopenharmony_ci if (us->srb != NULL) 19388c2ecf20Sopenharmony_ci scsi_set_resid(us->srb, 0); 19398c2ecf20Sopenharmony_ci info->BIN_FLAG = flag; 19408c2ecf20Sopenharmony_ci kfree(buf); 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_cinofw: 19438c2ecf20Sopenharmony_ci release_firmware(sd_fw); 19448c2ecf20Sopenharmony_ci return result; 19458c2ecf20Sopenharmony_ci} 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_cistatic int ms_card_init(struct us_data *us) 19488c2ecf20Sopenharmony_ci{ 19498c2ecf20Sopenharmony_ci u32 result; 19508c2ecf20Sopenharmony_ci u16 TmpBlock; 19518c2ecf20Sopenharmony_ci unsigned char *PageBuffer0 = NULL, *PageBuffer1 = NULL; 19528c2ecf20Sopenharmony_ci struct ms_lib_type_extdat extdat; 19538c2ecf20Sopenharmony_ci u16 btBlk1st, btBlk2nd; 19548c2ecf20Sopenharmony_ci u32 btBlk1stErred; 19558c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_ci printk(KERN_INFO "MS_CardInit start\n"); 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_ci ms_lib_free_allocatedarea(us); /* Clean buffer and set struct us_data flag to 0 */ 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci /* get two PageBuffer */ 19628c2ecf20Sopenharmony_ci PageBuffer0 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL); 19638c2ecf20Sopenharmony_ci PageBuffer1 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL); 19648c2ecf20Sopenharmony_ci if ((PageBuffer0 == NULL) || (PageBuffer1 == NULL)) { 19658c2ecf20Sopenharmony_ci result = MS_NO_MEMORY_ERROR; 19668c2ecf20Sopenharmony_ci goto exit; 19678c2ecf20Sopenharmony_ci } 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_ci btBlk1st = btBlk2nd = MS_LB_NOT_USED; 19708c2ecf20Sopenharmony_ci btBlk1stErred = 0; 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_ci for (TmpBlock = 0; TmpBlock < MS_MAX_INITIAL_ERROR_BLOCKS+2; TmpBlock++) { 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci switch (ms_read_readpage(us, TmpBlock, 0, (u32 *)PageBuffer0, &extdat)) { 19758c2ecf20Sopenharmony_ci case MS_STATUS_SUCCESS: 19768c2ecf20Sopenharmony_ci break; 19778c2ecf20Sopenharmony_ci case MS_STATUS_INT_ERROR: 19788c2ecf20Sopenharmony_ci break; 19798c2ecf20Sopenharmony_ci case MS_STATUS_ERROR: 19808c2ecf20Sopenharmony_ci default: 19818c2ecf20Sopenharmony_ci continue; 19828c2ecf20Sopenharmony_ci } 19838c2ecf20Sopenharmony_ci 19848c2ecf20Sopenharmony_ci if ((extdat.ovrflg & MS_REG_OVR_BKST) == MS_REG_OVR_BKST_NG) 19858c2ecf20Sopenharmony_ci continue; 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci if (((extdat.mngflg & MS_REG_MNG_SYSFLG) == MS_REG_MNG_SYSFLG_USER) || 19888c2ecf20Sopenharmony_ci (be16_to_cpu(((struct ms_bootblock_page0 *)PageBuffer0)->header.wBlockID) != MS_BOOT_BLOCK_ID) || 19898c2ecf20Sopenharmony_ci (be16_to_cpu(((struct ms_bootblock_page0 *)PageBuffer0)->header.wFormatVersion) != MS_BOOT_BLOCK_FORMAT_VERSION) || 19908c2ecf20Sopenharmony_ci (((struct ms_bootblock_page0 *)PageBuffer0)->header.bNumberOfDataEntry != MS_BOOT_BLOCK_DATA_ENTRIES)) 19918c2ecf20Sopenharmony_ci continue; 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci if (btBlk1st != MS_LB_NOT_USED) { 19948c2ecf20Sopenharmony_ci btBlk2nd = TmpBlock; 19958c2ecf20Sopenharmony_ci break; 19968c2ecf20Sopenharmony_ci } 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci btBlk1st = TmpBlock; 19998c2ecf20Sopenharmony_ci memcpy(PageBuffer1, PageBuffer0, MS_BYTES_PER_PAGE); 20008c2ecf20Sopenharmony_ci if (extdat.status1 & (MS_REG_ST1_DTER | MS_REG_ST1_EXER | MS_REG_ST1_FGER)) 20018c2ecf20Sopenharmony_ci btBlk1stErred = 1; 20028c2ecf20Sopenharmony_ci } 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci if (btBlk1st == MS_LB_NOT_USED) { 20058c2ecf20Sopenharmony_ci result = MS_STATUS_ERROR; 20068c2ecf20Sopenharmony_ci goto exit; 20078c2ecf20Sopenharmony_ci } 20088c2ecf20Sopenharmony_ci 20098c2ecf20Sopenharmony_ci /* write protect */ 20108c2ecf20Sopenharmony_ci if ((extdat.status0 & MS_REG_ST0_WP) == MS_REG_ST0_WP_ON) 20118c2ecf20Sopenharmony_ci ms_lib_ctrl_set(info, MS_LIB_CTRL_WRPROTECT); 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci result = MS_STATUS_ERROR; 20148c2ecf20Sopenharmony_ci /* 1st Boot Block */ 20158c2ecf20Sopenharmony_ci if (btBlk1stErred == 0) 20168c2ecf20Sopenharmony_ci result = ms_lib_process_bootblock(us, btBlk1st, PageBuffer1); 20178c2ecf20Sopenharmony_ci /* 1st */ 20188c2ecf20Sopenharmony_ci /* 2nd Boot Block */ 20198c2ecf20Sopenharmony_ci if (result && (btBlk2nd != MS_LB_NOT_USED)) 20208c2ecf20Sopenharmony_ci result = ms_lib_process_bootblock(us, btBlk2nd, PageBuffer0); 20218c2ecf20Sopenharmony_ci 20228c2ecf20Sopenharmony_ci if (result) { 20238c2ecf20Sopenharmony_ci result = MS_STATUS_ERROR; 20248c2ecf20Sopenharmony_ci goto exit; 20258c2ecf20Sopenharmony_ci } 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_ci for (TmpBlock = 0; TmpBlock < btBlk1st; TmpBlock++) 20288c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR; 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap[btBlk1st] = MS_LB_BOOT_BLOCK; 20318c2ecf20Sopenharmony_ci 20328c2ecf20Sopenharmony_ci if (btBlk2nd != MS_LB_NOT_USED) { 20338c2ecf20Sopenharmony_ci for (TmpBlock = btBlk1st + 1; TmpBlock < btBlk2nd; TmpBlock++) 20348c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR; 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci info->MS_Lib.Phy2LogMap[btBlk2nd] = MS_LB_BOOT_BLOCK; 20378c2ecf20Sopenharmony_ci } 20388c2ecf20Sopenharmony_ci 20398c2ecf20Sopenharmony_ci result = ms_lib_scan_logicalblocknumber(us, btBlk1st); 20408c2ecf20Sopenharmony_ci if (result) 20418c2ecf20Sopenharmony_ci goto exit; 20428c2ecf20Sopenharmony_ci 20438c2ecf20Sopenharmony_ci for (TmpBlock = MS_PHYSICAL_BLOCKS_PER_SEGMENT; 20448c2ecf20Sopenharmony_ci TmpBlock < info->MS_Lib.NumberOfPhyBlock; 20458c2ecf20Sopenharmony_ci TmpBlock += MS_PHYSICAL_BLOCKS_PER_SEGMENT) { 20468c2ecf20Sopenharmony_ci if (ms_count_freeblock(us, TmpBlock) == 0) { 20478c2ecf20Sopenharmony_ci ms_lib_ctrl_set(info, MS_LIB_CTRL_WRPROTECT); 20488c2ecf20Sopenharmony_ci break; 20498c2ecf20Sopenharmony_ci } 20508c2ecf20Sopenharmony_ci } 20518c2ecf20Sopenharmony_ci 20528c2ecf20Sopenharmony_ci /* write */ 20538c2ecf20Sopenharmony_ci if (ms_lib_alloc_writebuf(us)) { 20548c2ecf20Sopenharmony_ci result = MS_NO_MEMORY_ERROR; 20558c2ecf20Sopenharmony_ci goto exit; 20568c2ecf20Sopenharmony_ci } 20578c2ecf20Sopenharmony_ci 20588c2ecf20Sopenharmony_ci result = MS_STATUS_SUCCESS; 20598c2ecf20Sopenharmony_ci 20608c2ecf20Sopenharmony_ciexit: 20618c2ecf20Sopenharmony_ci kfree(PageBuffer1); 20628c2ecf20Sopenharmony_ci kfree(PageBuffer0); 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_ci printk(KERN_INFO "MS_CardInit end\n"); 20658c2ecf20Sopenharmony_ci return result; 20668c2ecf20Sopenharmony_ci} 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_cistatic int ene_ms_init(struct us_data *us) 20698c2ecf20Sopenharmony_ci{ 20708c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 20718c2ecf20Sopenharmony_ci int result; 20728c2ecf20Sopenharmony_ci u16 MSP_BlockSize, MSP_UserAreaBlocks; 20738c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 20748c2ecf20Sopenharmony_ci u8 *bbuf = info->bbuf; 20758c2ecf20Sopenharmony_ci unsigned int s; 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_ci printk(KERN_INFO "transport --- ENE_MSInit\n"); 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci /* the same part to test ENE */ 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_ci result = ene_load_bincode(us, MS_INIT_PATTERN); 20828c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 20838c2ecf20Sopenharmony_ci printk(KERN_ERR "Load MS Init Code Fail !!\n"); 20848c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 20858c2ecf20Sopenharmony_ci } 20868c2ecf20Sopenharmony_ci 20878c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 20888c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 20898c2ecf20Sopenharmony_ci bcb->DataTransferLength = 0x200; 20908c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 20918c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF1; 20928c2ecf20Sopenharmony_ci bcb->CDB[1] = 0x01; 20938c2ecf20Sopenharmony_ci 20948c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); 20958c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 20968c2ecf20Sopenharmony_ci printk(KERN_ERR "Execution MS Init Code Fail !!\n"); 20978c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 20988c2ecf20Sopenharmony_ci } 20998c2ecf20Sopenharmony_ci /* the same part to test ENE */ 21008c2ecf20Sopenharmony_ci info->MS_Status = bbuf[0]; 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_ci s = info->MS_Status; 21038c2ecf20Sopenharmony_ci if ((s & MS_Insert) && (s & MS_Ready)) { 21048c2ecf20Sopenharmony_ci printk(KERN_INFO "Insert = %x\n", !!(s & MS_Insert)); 21058c2ecf20Sopenharmony_ci printk(KERN_INFO "Ready = %x\n", !!(s & MS_Ready)); 21068c2ecf20Sopenharmony_ci printk(KERN_INFO "IsMSPro = %x\n", !!(s & MS_IsMSPro)); 21078c2ecf20Sopenharmony_ci printk(KERN_INFO "IsMSPHG = %x\n", !!(s & MS_IsMSPHG)); 21088c2ecf20Sopenharmony_ci printk(KERN_INFO "WtP= %x\n", !!(s & MS_WtP)); 21098c2ecf20Sopenharmony_ci if (s & MS_IsMSPro) { 21108c2ecf20Sopenharmony_ci MSP_BlockSize = (bbuf[6] << 8) | bbuf[7]; 21118c2ecf20Sopenharmony_ci MSP_UserAreaBlocks = (bbuf[10] << 8) | bbuf[11]; 21128c2ecf20Sopenharmony_ci info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks; 21138c2ecf20Sopenharmony_ci } else { 21148c2ecf20Sopenharmony_ci ms_card_init(us); /* Card is MS (to ms.c)*/ 21158c2ecf20Sopenharmony_ci } 21168c2ecf20Sopenharmony_ci usb_stor_dbg(us, "MS Init Code OK !!\n"); 21178c2ecf20Sopenharmony_ci } else { 21188c2ecf20Sopenharmony_ci usb_stor_dbg(us, "MS Card Not Ready --- %x\n", bbuf[0]); 21198c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 21208c2ecf20Sopenharmony_ci } 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 21238c2ecf20Sopenharmony_ci} 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_cistatic int ene_sd_init(struct us_data *us) 21268c2ecf20Sopenharmony_ci{ 21278c2ecf20Sopenharmony_ci int result; 21288c2ecf20Sopenharmony_ci struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 21298c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; 21308c2ecf20Sopenharmony_ci u8 *bbuf = info->bbuf; 21318c2ecf20Sopenharmony_ci 21328c2ecf20Sopenharmony_ci usb_stor_dbg(us, "transport --- ENE_SDInit\n"); 21338c2ecf20Sopenharmony_ci /* SD Init Part-1 */ 21348c2ecf20Sopenharmony_ci result = ene_load_bincode(us, SD_INIT1_PATTERN); 21358c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 21368c2ecf20Sopenharmony_ci usb_stor_dbg(us, "Load SD Init Code Part-1 Fail !!\n"); 21378c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 21388c2ecf20Sopenharmony_ci } 21398c2ecf20Sopenharmony_ci 21408c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 21418c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 21428c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 21438c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF2; 21448c2ecf20Sopenharmony_ci 21458c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0); 21468c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 21478c2ecf20Sopenharmony_ci usb_stor_dbg(us, "Execution SD Init Code Fail !!\n"); 21488c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 21498c2ecf20Sopenharmony_ci } 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_ci /* SD Init Part-2 */ 21528c2ecf20Sopenharmony_ci result = ene_load_bincode(us, SD_INIT2_PATTERN); 21538c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 21548c2ecf20Sopenharmony_ci usb_stor_dbg(us, "Load SD Init Code Part-2 Fail !!\n"); 21558c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 21568c2ecf20Sopenharmony_ci } 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 21598c2ecf20Sopenharmony_ci bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 21608c2ecf20Sopenharmony_ci bcb->DataTransferLength = 0x200; 21618c2ecf20Sopenharmony_ci bcb->Flags = US_BULK_FLAG_IN; 21628c2ecf20Sopenharmony_ci bcb->CDB[0] = 0xF1; 21638c2ecf20Sopenharmony_ci 21648c2ecf20Sopenharmony_ci result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); 21658c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 21668c2ecf20Sopenharmony_ci usb_stor_dbg(us, "Execution SD Init Code Fail !!\n"); 21678c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 21688c2ecf20Sopenharmony_ci } 21698c2ecf20Sopenharmony_ci 21708c2ecf20Sopenharmony_ci info->SD_Status = bbuf[0]; 21718c2ecf20Sopenharmony_ci if ((info->SD_Status & SD_Insert) && (info->SD_Status & SD_Ready)) { 21728c2ecf20Sopenharmony_ci unsigned int s = info->SD_Status; 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_ci ene_get_card_status(us, bbuf); 21758c2ecf20Sopenharmony_ci usb_stor_dbg(us, "Insert = %x\n", !!(s & SD_Insert)); 21768c2ecf20Sopenharmony_ci usb_stor_dbg(us, "Ready = %x\n", !!(s & SD_Ready)); 21778c2ecf20Sopenharmony_ci usb_stor_dbg(us, "IsMMC = %x\n", !!(s & SD_IsMMC)); 21788c2ecf20Sopenharmony_ci usb_stor_dbg(us, "HiCapacity = %x\n", !!(s & SD_HiCapacity)); 21798c2ecf20Sopenharmony_ci usb_stor_dbg(us, "HiSpeed = %x\n", !!(s & SD_HiSpeed)); 21808c2ecf20Sopenharmony_ci usb_stor_dbg(us, "WtP = %x\n", !!(s & SD_WtP)); 21818c2ecf20Sopenharmony_ci } else { 21828c2ecf20Sopenharmony_ci usb_stor_dbg(us, "SD Card Not Ready --- %x\n", bbuf[0]); 21838c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_GOOD; 21868c2ecf20Sopenharmony_ci} 21878c2ecf20Sopenharmony_ci 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_cistatic int ene_init(struct us_data *us) 21908c2ecf20Sopenharmony_ci{ 21918c2ecf20Sopenharmony_ci int result; 21928c2ecf20Sopenharmony_ci u8 misc_reg03; 21938c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); 21948c2ecf20Sopenharmony_ci u8 *bbuf = info->bbuf; 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci result = ene_get_card_type(us, REG_CARD_STATUS, bbuf); 21978c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 21988c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 21998c2ecf20Sopenharmony_ci 22008c2ecf20Sopenharmony_ci misc_reg03 = bbuf[0]; 22018c2ecf20Sopenharmony_ci if (misc_reg03 & 0x01) { 22028c2ecf20Sopenharmony_ci if (!(info->SD_Status & SD_Ready)) { 22038c2ecf20Sopenharmony_ci result = ene_sd_init(us); 22048c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 22058c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 22068c2ecf20Sopenharmony_ci } 22078c2ecf20Sopenharmony_ci } 22088c2ecf20Sopenharmony_ci if (misc_reg03 & 0x02) { 22098c2ecf20Sopenharmony_ci if (!(info->MS_Status & MS_Ready)) { 22108c2ecf20Sopenharmony_ci result = ene_ms_init(us); 22118c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) 22128c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 22138c2ecf20Sopenharmony_ci } 22148c2ecf20Sopenharmony_ci } 22158c2ecf20Sopenharmony_ci return result; 22168c2ecf20Sopenharmony_ci} 22178c2ecf20Sopenharmony_ci 22188c2ecf20Sopenharmony_ci/*----- sd_scsi_irp() ---------*/ 22198c2ecf20Sopenharmony_cistatic int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb) 22208c2ecf20Sopenharmony_ci{ 22218c2ecf20Sopenharmony_ci int result; 22228c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra; 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci switch (srb->cmnd[0]) { 22258c2ecf20Sopenharmony_ci case TEST_UNIT_READY: 22268c2ecf20Sopenharmony_ci result = sd_scsi_test_unit_ready(us, srb); 22278c2ecf20Sopenharmony_ci break; /* 0x00 */ 22288c2ecf20Sopenharmony_ci case REQUEST_SENSE: 22298c2ecf20Sopenharmony_ci result = do_scsi_request_sense(us, srb); 22308c2ecf20Sopenharmony_ci break; /* 0x03 */ 22318c2ecf20Sopenharmony_ci case INQUIRY: 22328c2ecf20Sopenharmony_ci result = do_scsi_inquiry(us, srb); 22338c2ecf20Sopenharmony_ci break; /* 0x12 */ 22348c2ecf20Sopenharmony_ci case MODE_SENSE: 22358c2ecf20Sopenharmony_ci result = sd_scsi_mode_sense(us, srb); 22368c2ecf20Sopenharmony_ci break; /* 0x1A */ 22378c2ecf20Sopenharmony_ci /* 22388c2ecf20Sopenharmony_ci case START_STOP: 22398c2ecf20Sopenharmony_ci result = SD_SCSI_Start_Stop(us, srb); 22408c2ecf20Sopenharmony_ci break; //0x1B 22418c2ecf20Sopenharmony_ci */ 22428c2ecf20Sopenharmony_ci case READ_CAPACITY: 22438c2ecf20Sopenharmony_ci result = sd_scsi_read_capacity(us, srb); 22448c2ecf20Sopenharmony_ci break; /* 0x25 */ 22458c2ecf20Sopenharmony_ci case READ_10: 22468c2ecf20Sopenharmony_ci result = sd_scsi_read(us, srb); 22478c2ecf20Sopenharmony_ci break; /* 0x28 */ 22488c2ecf20Sopenharmony_ci case WRITE_10: 22498c2ecf20Sopenharmony_ci result = sd_scsi_write(us, srb); 22508c2ecf20Sopenharmony_ci break; /* 0x2A */ 22518c2ecf20Sopenharmony_ci default: 22528c2ecf20Sopenharmony_ci info->SrbStatus = SS_ILLEGAL_REQUEST; 22538c2ecf20Sopenharmony_ci result = USB_STOR_TRANSPORT_FAILED; 22548c2ecf20Sopenharmony_ci break; 22558c2ecf20Sopenharmony_ci } 22568c2ecf20Sopenharmony_ci if (result == USB_STOR_TRANSPORT_GOOD) 22578c2ecf20Sopenharmony_ci info->SrbStatus = SS_SUCCESS; 22588c2ecf20Sopenharmony_ci return result; 22598c2ecf20Sopenharmony_ci} 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci/* 22628c2ecf20Sopenharmony_ci * ms_scsi_irp() 22638c2ecf20Sopenharmony_ci */ 22648c2ecf20Sopenharmony_cistatic int ms_scsi_irp(struct us_data *us, struct scsi_cmnd *srb) 22658c2ecf20Sopenharmony_ci{ 22668c2ecf20Sopenharmony_ci int result; 22678c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra; 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ci switch (srb->cmnd[0]) { 22708c2ecf20Sopenharmony_ci case TEST_UNIT_READY: 22718c2ecf20Sopenharmony_ci result = ms_scsi_test_unit_ready(us, srb); 22728c2ecf20Sopenharmony_ci break; /* 0x00 */ 22738c2ecf20Sopenharmony_ci case REQUEST_SENSE: 22748c2ecf20Sopenharmony_ci result = do_scsi_request_sense(us, srb); 22758c2ecf20Sopenharmony_ci break; /* 0x03 */ 22768c2ecf20Sopenharmony_ci case INQUIRY: 22778c2ecf20Sopenharmony_ci result = do_scsi_inquiry(us, srb); 22788c2ecf20Sopenharmony_ci break; /* 0x12 */ 22798c2ecf20Sopenharmony_ci case MODE_SENSE: 22808c2ecf20Sopenharmony_ci result = ms_scsi_mode_sense(us, srb); 22818c2ecf20Sopenharmony_ci break; /* 0x1A */ 22828c2ecf20Sopenharmony_ci case READ_CAPACITY: 22838c2ecf20Sopenharmony_ci result = ms_scsi_read_capacity(us, srb); 22848c2ecf20Sopenharmony_ci break; /* 0x25 */ 22858c2ecf20Sopenharmony_ci case READ_10: 22868c2ecf20Sopenharmony_ci result = ms_scsi_read(us, srb); 22878c2ecf20Sopenharmony_ci break; /* 0x28 */ 22888c2ecf20Sopenharmony_ci case WRITE_10: 22898c2ecf20Sopenharmony_ci result = ms_scsi_write(us, srb); 22908c2ecf20Sopenharmony_ci break; /* 0x2A */ 22918c2ecf20Sopenharmony_ci default: 22928c2ecf20Sopenharmony_ci info->SrbStatus = SS_ILLEGAL_REQUEST; 22938c2ecf20Sopenharmony_ci result = USB_STOR_TRANSPORT_FAILED; 22948c2ecf20Sopenharmony_ci break; 22958c2ecf20Sopenharmony_ci } 22968c2ecf20Sopenharmony_ci if (result == USB_STOR_TRANSPORT_GOOD) 22978c2ecf20Sopenharmony_ci info->SrbStatus = SS_SUCCESS; 22988c2ecf20Sopenharmony_ci return result; 22998c2ecf20Sopenharmony_ci} 23008c2ecf20Sopenharmony_ci 23018c2ecf20Sopenharmony_cistatic int ene_transport(struct scsi_cmnd *srb, struct us_data *us) 23028c2ecf20Sopenharmony_ci{ 23038c2ecf20Sopenharmony_ci int result = USB_STOR_XFER_GOOD; 23048c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); 23058c2ecf20Sopenharmony_ci 23068c2ecf20Sopenharmony_ci /*US_DEBUG(usb_stor_show_command(us, srb)); */ 23078c2ecf20Sopenharmony_ci scsi_set_resid(srb, 0); 23088c2ecf20Sopenharmony_ci if (unlikely(!(info->SD_Status & SD_Ready) || (info->MS_Status & MS_Ready))) 23098c2ecf20Sopenharmony_ci result = ene_init(us); 23108c2ecf20Sopenharmony_ci if (result == USB_STOR_XFER_GOOD) { 23118c2ecf20Sopenharmony_ci result = USB_STOR_TRANSPORT_ERROR; 23128c2ecf20Sopenharmony_ci if (info->SD_Status & SD_Ready) 23138c2ecf20Sopenharmony_ci result = sd_scsi_irp(us, srb); 23148c2ecf20Sopenharmony_ci 23158c2ecf20Sopenharmony_ci if (info->MS_Status & MS_Ready) 23168c2ecf20Sopenharmony_ci result = ms_scsi_irp(us, srb); 23178c2ecf20Sopenharmony_ci } 23188c2ecf20Sopenharmony_ci return result; 23198c2ecf20Sopenharmony_ci} 23208c2ecf20Sopenharmony_ci 23218c2ecf20Sopenharmony_cistatic struct scsi_host_template ene_ub6250_host_template; 23228c2ecf20Sopenharmony_ci 23238c2ecf20Sopenharmony_cistatic int ene_ub6250_probe(struct usb_interface *intf, 23248c2ecf20Sopenharmony_ci const struct usb_device_id *id) 23258c2ecf20Sopenharmony_ci{ 23268c2ecf20Sopenharmony_ci int result; 23278c2ecf20Sopenharmony_ci u8 misc_reg03; 23288c2ecf20Sopenharmony_ci struct us_data *us; 23298c2ecf20Sopenharmony_ci struct ene_ub6250_info *info; 23308c2ecf20Sopenharmony_ci 23318c2ecf20Sopenharmony_ci result = usb_stor_probe1(&us, intf, id, 23328c2ecf20Sopenharmony_ci (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list, 23338c2ecf20Sopenharmony_ci &ene_ub6250_host_template); 23348c2ecf20Sopenharmony_ci if (result) 23358c2ecf20Sopenharmony_ci return result; 23368c2ecf20Sopenharmony_ci 23378c2ecf20Sopenharmony_ci /* FIXME: where should the code alloc extra buf ? */ 23388c2ecf20Sopenharmony_ci us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL); 23398c2ecf20Sopenharmony_ci if (!us->extra) 23408c2ecf20Sopenharmony_ci return -ENOMEM; 23418c2ecf20Sopenharmony_ci us->extra_destructor = ene_ub6250_info_destructor; 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ci info = (struct ene_ub6250_info *)(us->extra); 23448c2ecf20Sopenharmony_ci info->bbuf = kmalloc(512, GFP_KERNEL); 23458c2ecf20Sopenharmony_ci if (!info->bbuf) { 23468c2ecf20Sopenharmony_ci kfree(us->extra); 23478c2ecf20Sopenharmony_ci return -ENOMEM; 23488c2ecf20Sopenharmony_ci } 23498c2ecf20Sopenharmony_ci 23508c2ecf20Sopenharmony_ci us->transport_name = "ene_ub6250"; 23518c2ecf20Sopenharmony_ci us->transport = ene_transport; 23528c2ecf20Sopenharmony_ci us->max_lun = 0; 23538c2ecf20Sopenharmony_ci 23548c2ecf20Sopenharmony_ci result = usb_stor_probe2(us); 23558c2ecf20Sopenharmony_ci if (result) 23568c2ecf20Sopenharmony_ci return result; 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci /* probe card type */ 23598c2ecf20Sopenharmony_ci result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf); 23608c2ecf20Sopenharmony_ci if (result != USB_STOR_XFER_GOOD) { 23618c2ecf20Sopenharmony_ci usb_stor_disconnect(intf); 23628c2ecf20Sopenharmony_ci return USB_STOR_TRANSPORT_ERROR; 23638c2ecf20Sopenharmony_ci } 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ci misc_reg03 = info->bbuf[0]; 23668c2ecf20Sopenharmony_ci if (!(misc_reg03 & 0x01)) { 23678c2ecf20Sopenharmony_ci pr_info("ums_eneub6250: This driver only supports SD/MS cards. " 23688c2ecf20Sopenharmony_ci "It does not support SM cards.\n"); 23698c2ecf20Sopenharmony_ci } 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci return result; 23728c2ecf20Sopenharmony_ci} 23738c2ecf20Sopenharmony_ci 23748c2ecf20Sopenharmony_ci 23758c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 23768c2ecf20Sopenharmony_ci 23778c2ecf20Sopenharmony_cistatic int ene_ub6250_resume(struct usb_interface *iface) 23788c2ecf20Sopenharmony_ci{ 23798c2ecf20Sopenharmony_ci struct us_data *us = usb_get_intfdata(iface); 23808c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); 23818c2ecf20Sopenharmony_ci 23828c2ecf20Sopenharmony_ci mutex_lock(&us->dev_mutex); 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ci if (us->suspend_resume_hook) 23858c2ecf20Sopenharmony_ci (us->suspend_resume_hook)(us, US_RESUME); 23868c2ecf20Sopenharmony_ci 23878c2ecf20Sopenharmony_ci mutex_unlock(&us->dev_mutex); 23888c2ecf20Sopenharmony_ci 23898c2ecf20Sopenharmony_ci info->Power_IsResum = true; 23908c2ecf20Sopenharmony_ci /* info->SD_Status &= ~SD_Ready; */ 23918c2ecf20Sopenharmony_ci info->SD_Status = 0; 23928c2ecf20Sopenharmony_ci info->MS_Status = 0; 23938c2ecf20Sopenharmony_ci info->SM_Status = 0; 23948c2ecf20Sopenharmony_ci 23958c2ecf20Sopenharmony_ci return 0; 23968c2ecf20Sopenharmony_ci} 23978c2ecf20Sopenharmony_ci 23988c2ecf20Sopenharmony_cistatic int ene_ub6250_reset_resume(struct usb_interface *iface) 23998c2ecf20Sopenharmony_ci{ 24008c2ecf20Sopenharmony_ci struct us_data *us = usb_get_intfdata(iface); 24018c2ecf20Sopenharmony_ci struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); 24028c2ecf20Sopenharmony_ci 24038c2ecf20Sopenharmony_ci /* Report the reset to the SCSI core */ 24048c2ecf20Sopenharmony_ci usb_stor_reset_resume(iface); 24058c2ecf20Sopenharmony_ci 24068c2ecf20Sopenharmony_ci /* 24078c2ecf20Sopenharmony_ci * FIXME: Notify the subdrivers that they need to reinitialize 24088c2ecf20Sopenharmony_ci * the device 24098c2ecf20Sopenharmony_ci */ 24108c2ecf20Sopenharmony_ci info->Power_IsResum = true; 24118c2ecf20Sopenharmony_ci /* info->SD_Status &= ~SD_Ready; */ 24128c2ecf20Sopenharmony_ci info->SD_Status = 0; 24138c2ecf20Sopenharmony_ci info->MS_Status = 0; 24148c2ecf20Sopenharmony_ci info->SM_Status = 0; 24158c2ecf20Sopenharmony_ci 24168c2ecf20Sopenharmony_ci return 0; 24178c2ecf20Sopenharmony_ci} 24188c2ecf20Sopenharmony_ci 24198c2ecf20Sopenharmony_ci#else 24208c2ecf20Sopenharmony_ci 24218c2ecf20Sopenharmony_ci#define ene_ub6250_resume NULL 24228c2ecf20Sopenharmony_ci#define ene_ub6250_reset_resume NULL 24238c2ecf20Sopenharmony_ci 24248c2ecf20Sopenharmony_ci#endif 24258c2ecf20Sopenharmony_ci 24268c2ecf20Sopenharmony_cistatic struct usb_driver ene_ub6250_driver = { 24278c2ecf20Sopenharmony_ci .name = DRV_NAME, 24288c2ecf20Sopenharmony_ci .probe = ene_ub6250_probe, 24298c2ecf20Sopenharmony_ci .disconnect = usb_stor_disconnect, 24308c2ecf20Sopenharmony_ci .suspend = usb_stor_suspend, 24318c2ecf20Sopenharmony_ci .resume = ene_ub6250_resume, 24328c2ecf20Sopenharmony_ci .reset_resume = ene_ub6250_reset_resume, 24338c2ecf20Sopenharmony_ci .pre_reset = usb_stor_pre_reset, 24348c2ecf20Sopenharmony_ci .post_reset = usb_stor_post_reset, 24358c2ecf20Sopenharmony_ci .id_table = ene_ub6250_usb_ids, 24368c2ecf20Sopenharmony_ci .soft_unbind = 1, 24378c2ecf20Sopenharmony_ci .no_dynamic_id = 1, 24388c2ecf20Sopenharmony_ci}; 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_cimodule_usb_stor_driver(ene_ub6250_driver, ene_ub6250_host_template, DRV_NAME); 2441