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