177d89b08766c878a2594b15d203e513acf952340wwang/* Driver for Realtek PCI-Express card reader
277d89b08766c878a2594b15d203e513acf952340wwang *
377d89b08766c878a2594b15d203e513acf952340wwang * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
477d89b08766c878a2594b15d203e513acf952340wwang *
577d89b08766c878a2594b15d203e513acf952340wwang * This program is free software; you can redistribute it and/or modify it
677d89b08766c878a2594b15d203e513acf952340wwang * under the terms of the GNU General Public License as published by the
777d89b08766c878a2594b15d203e513acf952340wwang * Free Software Foundation; either version 2, or (at your option) any
877d89b08766c878a2594b15d203e513acf952340wwang * later version.
977d89b08766c878a2594b15d203e513acf952340wwang *
1077d89b08766c878a2594b15d203e513acf952340wwang * This program is distributed in the hope that it will be useful, but
1177d89b08766c878a2594b15d203e513acf952340wwang * WITHOUT ANY WARRANTY; without even the implied warranty of
1277d89b08766c878a2594b15d203e513acf952340wwang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1377d89b08766c878a2594b15d203e513acf952340wwang * General Public License for more details.
1477d89b08766c878a2594b15d203e513acf952340wwang *
1577d89b08766c878a2594b15d203e513acf952340wwang * You should have received a copy of the GNU General Public License along
1677d89b08766c878a2594b15d203e513acf952340wwang * with this program; if not, see <http://www.gnu.org/licenses/>.
1777d89b08766c878a2594b15d203e513acf952340wwang *
1877d89b08766c878a2594b15d203e513acf952340wwang * Author:
1977d89b08766c878a2594b15d203e513acf952340wwang *   wwang (wei_wang@realsil.com.cn)
2077d89b08766c878a2594b15d203e513acf952340wwang *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
2177d89b08766c878a2594b15d203e513acf952340wwang */
2277d89b08766c878a2594b15d203e513acf952340wwang
2377d89b08766c878a2594b15d203e513acf952340wwang#include <linux/blkdev.h>
2477d89b08766c878a2594b15d203e513acf952340wwang#include <linux/kthread.h>
2577d89b08766c878a2594b15d203e513acf952340wwang#include <linux/sched.h>
26c6cdaded146875e2e47e946f6592c1775eaee849Jeff Mahoney#include <linux/vmalloc.h>
2777d89b08766c878a2594b15d203e513acf952340wwang
2877d89b08766c878a2594b15d203e513acf952340wwang#include "rtsx.h"
2977d89b08766c878a2594b15d203e513acf952340wwang#include "rtsx_transport.h"
3077d89b08766c878a2594b15d203e513acf952340wwang#include "rtsx_sys.h"
3177d89b08766c878a2594b15d203e513acf952340wwang#include "rtsx_card.h"
3277d89b08766c878a2594b15d203e513acf952340wwang#include "rtsx_chip.h"
3377d89b08766c878a2594b15d203e513acf952340wwang#include "rtsx_scsi.h"
3477d89b08766c878a2594b15d203e513acf952340wwang#include "sd.h"
3577d89b08766c878a2594b15d203e513acf952340wwang#include "ms.h"
3677d89b08766c878a2594b15d203e513acf952340wwang#include "spi.h"
3777d89b08766c878a2594b15d203e513acf952340wwang
3877d89b08766c878a2594b15d203e513acf952340wwangvoid scsi_show_command(struct scsi_cmnd *srb)
3977d89b08766c878a2594b15d203e513acf952340wwang{
4077d89b08766c878a2594b15d203e513acf952340wwang	char *what = NULL;
4177d89b08766c878a2594b15d203e513acf952340wwang	int i, unknown_cmd = 0;
4277d89b08766c878a2594b15d203e513acf952340wwang
4377d89b08766c878a2594b15d203e513acf952340wwang	switch (srb->cmnd[0]) {
4477d89b08766c878a2594b15d203e513acf952340wwang	case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break;
4577d89b08766c878a2594b15d203e513acf952340wwang	case REZERO_UNIT: what = "REZERO_UNIT"; break;
4677d89b08766c878a2594b15d203e513acf952340wwang	case REQUEST_SENSE: what = "REQUEST_SENSE"; break;
4777d89b08766c878a2594b15d203e513acf952340wwang	case FORMAT_UNIT: what = "FORMAT_UNIT"; break;
4877d89b08766c878a2594b15d203e513acf952340wwang	case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break;
4977d89b08766c878a2594b15d203e513acf952340wwang	case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break;
5077d89b08766c878a2594b15d203e513acf952340wwang	case READ_6: what = "READ_6"; break;
5177d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_6: what = "WRITE_6"; break;
5277d89b08766c878a2594b15d203e513acf952340wwang	case SEEK_6: what = "SEEK_6"; break;
5377d89b08766c878a2594b15d203e513acf952340wwang	case READ_REVERSE: what = "READ_REVERSE"; break;
5477d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break;
5577d89b08766c878a2594b15d203e513acf952340wwang	case SPACE: what = "SPACE"; break;
5677d89b08766c878a2594b15d203e513acf952340wwang	case INQUIRY: what = "INQUIRY"; break;
5777d89b08766c878a2594b15d203e513acf952340wwang	case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break;
5877d89b08766c878a2594b15d203e513acf952340wwang	case MODE_SELECT: what = "MODE_SELECT"; break;
5977d89b08766c878a2594b15d203e513acf952340wwang	case RESERVE: what = "RESERVE"; break;
6077d89b08766c878a2594b15d203e513acf952340wwang	case RELEASE: what = "RELEASE"; break;
6177d89b08766c878a2594b15d203e513acf952340wwang	case COPY: what = "COPY"; break;
6277d89b08766c878a2594b15d203e513acf952340wwang	case ERASE: what = "ERASE"; break;
6377d89b08766c878a2594b15d203e513acf952340wwang	case MODE_SENSE: what = "MODE_SENSE"; break;
6477d89b08766c878a2594b15d203e513acf952340wwang	case START_STOP: what = "START_STOP"; break;
6577d89b08766c878a2594b15d203e513acf952340wwang	case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break;
6677d89b08766c878a2594b15d203e513acf952340wwang	case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break;
6777d89b08766c878a2594b15d203e513acf952340wwang	case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break;
6877d89b08766c878a2594b15d203e513acf952340wwang	case SET_WINDOW: what = "SET_WINDOW"; break;
6977d89b08766c878a2594b15d203e513acf952340wwang	case READ_CAPACITY: what = "READ_CAPACITY"; break;
7077d89b08766c878a2594b15d203e513acf952340wwang	case READ_10: what = "READ_10"; break;
7177d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_10: what = "WRITE_10"; break;
7277d89b08766c878a2594b15d203e513acf952340wwang	case SEEK_10: what = "SEEK_10"; break;
7377d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_VERIFY: what = "WRITE_VERIFY"; break;
7477d89b08766c878a2594b15d203e513acf952340wwang	case VERIFY: what = "VERIFY"; break;
7577d89b08766c878a2594b15d203e513acf952340wwang	case SEARCH_HIGH: what = "SEARCH_HIGH"; break;
7677d89b08766c878a2594b15d203e513acf952340wwang	case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break;
7777d89b08766c878a2594b15d203e513acf952340wwang	case SEARCH_LOW: what = "SEARCH_LOW"; break;
7877d89b08766c878a2594b15d203e513acf952340wwang	case SET_LIMITS: what = "SET_LIMITS"; break;
7977d89b08766c878a2594b15d203e513acf952340wwang	case READ_POSITION: what = "READ_POSITION"; break;
8077d89b08766c878a2594b15d203e513acf952340wwang	case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break;
8177d89b08766c878a2594b15d203e513acf952340wwang	case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break;
8277d89b08766c878a2594b15d203e513acf952340wwang	case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break;
8377d89b08766c878a2594b15d203e513acf952340wwang	case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break;
8477d89b08766c878a2594b15d203e513acf952340wwang	case COMPARE: what = "COMPARE"; break;
8577d89b08766c878a2594b15d203e513acf952340wwang	case COPY_VERIFY: what = "COPY_VERIFY"; break;
8677d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_BUFFER: what = "WRITE_BUFFER"; break;
8777d89b08766c878a2594b15d203e513acf952340wwang	case READ_BUFFER: what = "READ_BUFFER"; break;
8877d89b08766c878a2594b15d203e513acf952340wwang	case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break;
8977d89b08766c878a2594b15d203e513acf952340wwang	case READ_LONG: what = "READ_LONG"; break;
9077d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_LONG: what = "WRITE_LONG"; break;
9177d89b08766c878a2594b15d203e513acf952340wwang	case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break;
9277d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_SAME: what = "WRITE_SAME"; break;
9377d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_READ_SUBCHANNEL: what = "READ SUBCHANNEL"; break;
9477d89b08766c878a2594b15d203e513acf952340wwang	case READ_TOC: what = "READ_TOC"; break;
9577d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_READ_HEADER: what = "READ HEADER"; break;
9677d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_PLAY_AUDIO_10: what = "PLAY AUDIO (10)"; break;
9777d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_PLAY_AUDIO_MSF: what = "PLAY AUDIO MSF"; break;
9877d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
9977d89b08766c878a2594b15d203e513acf952340wwang		what = "GET EVENT/STATUS NOTIFICATION"; break;
10077d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_PAUSE_RESUME: what = "PAUSE/RESUME"; break;
10177d89b08766c878a2594b15d203e513acf952340wwang	case LOG_SELECT: what = "LOG_SELECT"; break;
10277d89b08766c878a2594b15d203e513acf952340wwang	case LOG_SENSE: what = "LOG_SENSE"; break;
10377d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_STOP_PLAY_SCAN: what = "STOP PLAY/SCAN"; break;
10477d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_READ_DISC_INFO: what = "READ DISC INFORMATION"; break;
10577d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_READ_TRACK_RZONE_INFO:
10677d89b08766c878a2594b15d203e513acf952340wwang		what = "READ TRACK INFORMATION"; break;
10777d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_RESERVE_RZONE_TRACK: what = "RESERVE TRACK"; break;
10877d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_SEND_OPC: what = "SEND OPC"; break;
10977d89b08766c878a2594b15d203e513acf952340wwang	case MODE_SELECT_10: what = "MODE_SELECT_10"; break;
11077d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_REPAIR_RZONE_TRACK: what = "REPAIR TRACK"; break;
11177d89b08766c878a2594b15d203e513acf952340wwang	case 0x59: what = "READ MASTER CUE"; break;
11277d89b08766c878a2594b15d203e513acf952340wwang	case MODE_SENSE_10: what = "MODE_SENSE_10"; break;
11377d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_CLOSE_TRACK: what = "CLOSE TRACK/SESSION"; break;
11477d89b08766c878a2594b15d203e513acf952340wwang	case 0x5C: what = "READ BUFFER CAPACITY"; break;
11577d89b08766c878a2594b15d203e513acf952340wwang	case 0x5D: what = "SEND CUE SHEET"; break;
11677d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_BLANK: what = "BLANK"; break;
11777d89b08766c878a2594b15d203e513acf952340wwang	case REPORT_LUNS: what = "REPORT LUNS"; break;
11877d89b08766c878a2594b15d203e513acf952340wwang	case MOVE_MEDIUM: what = "MOVE_MEDIUM or PLAY AUDIO (12)"; break;
11977d89b08766c878a2594b15d203e513acf952340wwang	case READ_12: what = "READ_12"; break;
12077d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_12: what = "WRITE_12"; break;
12177d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break;
12277d89b08766c878a2594b15d203e513acf952340wwang	case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break;
12377d89b08766c878a2594b15d203e513acf952340wwang	case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break;
12477d89b08766c878a2594b15d203e513acf952340wwang	case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break;
12577d89b08766c878a2594b15d203e513acf952340wwang	case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break;
12677d89b08766c878a2594b15d203e513acf952340wwang	case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break;
12777d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_READ_CD_MSF: what = "READ CD MSF"; break;
12877d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_SCAN: what = "SCAN"; break;
12977d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_SET_SPEED: what = "SET CD SPEED"; break;
13077d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_MECHANISM_STATUS: what = "MECHANISM STATUS"; break;
13177d89b08766c878a2594b15d203e513acf952340wwang	case GPCMD_READ_CD: what = "READ CD"; break;
13277d89b08766c878a2594b15d203e513acf952340wwang	case 0xE1: what = "WRITE CONTINUE"; break;
13377d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
13477d89b08766c878a2594b15d203e513acf952340wwang	case VENDOR_CMND: what = "Realtek's vendor command"; break;
13577d89b08766c878a2594b15d203e513acf952340wwang	default: what = "(unknown command)"; unknown_cmd = 1; break;
13677d89b08766c878a2594b15d203e513acf952340wwang	}
13777d89b08766c878a2594b15d203e513acf952340wwang
13877d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[0] != TEST_UNIT_READY) {
13977d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len);
14077d89b08766c878a2594b15d203e513acf952340wwang	}
14177d89b08766c878a2594b15d203e513acf952340wwang	if (unknown_cmd) {
14277d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("");
14377d89b08766c878a2594b15d203e513acf952340wwang		for (i = 0; i < srb->cmd_len && i < 16; i++)
14477d89b08766c878a2594b15d203e513acf952340wwang			RTSX_DEBUGPN(" %02x", srb->cmnd[i]);
14577d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGPN("\n");
14677d89b08766c878a2594b15d203e513acf952340wwang	}
14777d89b08766c878a2594b15d203e513acf952340wwang}
14877d89b08766c878a2594b15d203e513acf952340wwang
14977d89b08766c878a2594b15d203e513acf952340wwangvoid set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type)
15077d89b08766c878a2594b15d203e513acf952340wwang{
15177d89b08766c878a2594b15d203e513acf952340wwang	switch (sense_type) {
15277d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MEDIA_CHANGE:
15377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0);
15477d89b08766c878a2594b15d203e513acf952340wwang		break;
15577d89b08766c878a2594b15d203e513acf952340wwang
15677d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MEDIA_NOT_PRESENT:
15777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0);
15877d89b08766c878a2594b15d203e513acf952340wwang		break;
15977d89b08766c878a2594b15d203e513acf952340wwang
16077d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MEDIA_LBA_OVER_RANGE:
16177d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0);
16277d89b08766c878a2594b15d203e513acf952340wwang		break;
16377d89b08766c878a2594b15d203e513acf952340wwang
16477d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT:
16577d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0);
16677d89b08766c878a2594b15d203e513acf952340wwang		break;
16777d89b08766c878a2594b15d203e513acf952340wwang
16877d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MEDIA_WRITE_PROTECT:
16977d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0);
17077d89b08766c878a2594b15d203e513acf952340wwang		break;
17177d89b08766c878a2594b15d203e513acf952340wwang
17277d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR:
17377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0);
17477d89b08766c878a2594b15d203e513acf952340wwang		break;
17577d89b08766c878a2594b15d203e513acf952340wwang
17677d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MEDIA_WRITE_ERR:
17777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0);
17877d89b08766c878a2594b15d203e513acf952340wwang		break;
17977d89b08766c878a2594b15d203e513acf952340wwang
18077d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD:
18177d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0,
18277d89b08766c878a2594b15d203e513acf952340wwang				ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1);
18377d89b08766c878a2594b15d203e513acf952340wwang		break;
18477d89b08766c878a2594b15d203e513acf952340wwang
18577d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_FORMAT_IN_PROGRESS:
18677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, 0, 0);
18777d89b08766c878a2594b15d203e513acf952340wwang		break;
18877d89b08766c878a2594b15d203e513acf952340wwang
18977d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_FORMAT_CMD_FAILED:
19077d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0);
19177d89b08766c878a2594b15d203e513acf952340wwang		break;
19277d89b08766c878a2594b15d203e513acf952340wwang
19377d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_MAGIC_GATE
19477d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB:
19577d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0);
19677d89b08766c878a2594b15d203e513acf952340wwang		break;
19777d89b08766c878a2594b15d203e513acf952340wwang
19877d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN:
19977d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0);
20077d89b08766c878a2594b15d203e513acf952340wwang		break;
20177d89b08766c878a2594b15d203e513acf952340wwang
20277d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM:
20377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0);
20477d89b08766c878a2594b15d203e513acf952340wwang		break;
20577d89b08766c878a2594b15d203e513acf952340wwang
20677d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MG_WRITE_ERR:
20777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0);
20877d89b08766c878a2594b15d203e513acf952340wwang		break;
20977d89b08766c878a2594b15d203e513acf952340wwang#endif
21077d89b08766c878a2594b15d203e513acf952340wwang
21177d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
21277d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_MEDIA_READ_FORBIDDEN:
21377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x11, 0x13, 0, 0);
21477d89b08766c878a2594b15d203e513acf952340wwang		break;
21577d89b08766c878a2594b15d203e513acf952340wwang#endif
21677d89b08766c878a2594b15d203e513acf952340wwang
21777d89b08766c878a2594b15d203e513acf952340wwang	case SENSE_TYPE_NO_SENSE:
21877d89b08766c878a2594b15d203e513acf952340wwang	default:
21977d89b08766c878a2594b15d203e513acf952340wwang		set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0);
22077d89b08766c878a2594b15d203e513acf952340wwang		break;
22177d89b08766c878a2594b15d203e513acf952340wwang	}
22277d89b08766c878a2594b15d203e513acf952340wwang}
22377d89b08766c878a2594b15d203e513acf952340wwang
22477d89b08766c878a2594b15d203e513acf952340wwangvoid set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, u8 sense_key,
22577d89b08766c878a2594b15d203e513acf952340wwang		u32 info, u8 asc, u8 ascq, u8 sns_key_info0, u16 sns_key_info1)
22677d89b08766c878a2594b15d203e513acf952340wwang{
22777d89b08766c878a2594b15d203e513acf952340wwang	struct sense_data_t *sense = &(chip->sense_buffer[lun]);
22877d89b08766c878a2594b15d203e513acf952340wwang
22977d89b08766c878a2594b15d203e513acf952340wwang	sense->err_code = err_code;
23077d89b08766c878a2594b15d203e513acf952340wwang	sense->sense_key = sense_key;
23177d89b08766c878a2594b15d203e513acf952340wwang	sense->info[0] = (u8)(info >> 24);
23277d89b08766c878a2594b15d203e513acf952340wwang	sense->info[1] = (u8)(info >> 16);
23377d89b08766c878a2594b15d203e513acf952340wwang	sense->info[2] = (u8)(info >> 8);
23477d89b08766c878a2594b15d203e513acf952340wwang	sense->info[3] = (u8)info;
23577d89b08766c878a2594b15d203e513acf952340wwang
23677d89b08766c878a2594b15d203e513acf952340wwang	sense->ad_sense_len = sizeof(struct sense_data_t) - 8;
23777d89b08766c878a2594b15d203e513acf952340wwang	sense->asc = asc;
23877d89b08766c878a2594b15d203e513acf952340wwang	sense->ascq = ascq;
23977d89b08766c878a2594b15d203e513acf952340wwang	if (sns_key_info0 != 0) {
24077d89b08766c878a2594b15d203e513acf952340wwang		sense->sns_key_info[0] = SKSV | sns_key_info0;
24177d89b08766c878a2594b15d203e513acf952340wwang		sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 8;
24277d89b08766c878a2594b15d203e513acf952340wwang		sense->sns_key_info[2] = sns_key_info1 & 0x0f;
24377d89b08766c878a2594b15d203e513acf952340wwang	}
24477d89b08766c878a2594b15d203e513acf952340wwang}
24577d89b08766c878a2594b15d203e513acf952340wwang
24677d89b08766c878a2594b15d203e513acf952340wwangstatic int test_unit_ready(struct scsi_cmnd *srb, struct rtsx_chip *chip)
24777d89b08766c878a2594b15d203e513acf952340wwang{
24877d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
24977d89b08766c878a2594b15d203e513acf952340wwang
25077d89b08766c878a2594b15d203e513acf952340wwang	if (!check_card_ready(chip, lun)) {
25177d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
25277d89b08766c878a2594b15d203e513acf952340wwang		return TRANSPORT_FAILED;
25377d89b08766c878a2594b15d203e513acf952340wwang	}
25477d89b08766c878a2594b15d203e513acf952340wwang
25577d89b08766c878a2594b15d203e513acf952340wwang	if (!(CHK_BIT(chip->lun_mc, lun))) {
25677d89b08766c878a2594b15d203e513acf952340wwang		SET_BIT(chip->lun_mc, lun);
25777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
25877d89b08766c878a2594b15d203e513acf952340wwang		return TRANSPORT_FAILED;
25977d89b08766c878a2594b15d203e513acf952340wwang	}
26077d89b08766c878a2594b15d203e513acf952340wwang
26177d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
26277d89b08766c878a2594b15d203e513acf952340wwang	if (get_lun_card(chip, SCSI_LUN(srb)) == SD_CARD) {
26377d89b08766c878a2594b15d203e513acf952340wwang		struct sd_info *sd_card = &(chip->sd_card);
26477d89b08766c878a2594b15d203e513acf952340wwang		if (sd_card->sd_lock_notify) {
26577d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_lock_notify = 0;
26677d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
26777d89b08766c878a2594b15d203e513acf952340wwang			return TRANSPORT_FAILED;
26877d89b08766c878a2594b15d203e513acf952340wwang		} else if (sd_card->sd_lock_status & SD_LOCKED) {
26977d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
27077d89b08766c878a2594b15d203e513acf952340wwang			return TRANSPORT_FAILED;
27177d89b08766c878a2594b15d203e513acf952340wwang		}
27277d89b08766c878a2594b15d203e513acf952340wwang	}
27377d89b08766c878a2594b15d203e513acf952340wwang#endif
27477d89b08766c878a2594b15d203e513acf952340wwang
27577d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
27677d89b08766c878a2594b15d203e513acf952340wwang}
27777d89b08766c878a2594b15d203e513acf952340wwang
2786680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic unsigned char formatter_inquiry_str[20] = {
27977d89b08766c878a2594b15d203e513acf952340wwang	'M', 'E', 'M', 'O', 'R', 'Y', 'S', 'T', 'I', 'C', 'K',
28077d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_MAGIC_GATE
28177d89b08766c878a2594b15d203e513acf952340wwang	'-', 'M', 'G', /* Byte[47:49] */
28277d89b08766c878a2594b15d203e513acf952340wwang#else
28377d89b08766c878a2594b15d203e513acf952340wwang	0x20, 0x20, 0x20,  /* Byte[47:49] */
28477d89b08766c878a2594b15d203e513acf952340wwang#endif
28577d89b08766c878a2594b15d203e513acf952340wwang
28677d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_MAGIC_GATE
28777d89b08766c878a2594b15d203e513acf952340wwang	0x0B,  /* Byte[50]: MG, MS, MSPro, MSXC */
28877d89b08766c878a2594b15d203e513acf952340wwang#else
28977d89b08766c878a2594b15d203e513acf952340wwang	0x09,  /* Byte[50]: MS, MSPro, MSXC */
29077d89b08766c878a2594b15d203e513acf952340wwang#endif
29177d89b08766c878a2594b15d203e513acf952340wwang	0x00,  /* Byte[51]: Category Specific Commands */
29277d89b08766c878a2594b15d203e513acf952340wwang	0x00,  /* Byte[52]: Access Control and feature */
29377d89b08766c878a2594b15d203e513acf952340wwang	0x20, 0x20, 0x20, /* Byte[53:55] */
29477d89b08766c878a2594b15d203e513acf952340wwang};
29577d89b08766c878a2594b15d203e513acf952340wwang
29677d89b08766c878a2594b15d203e513acf952340wwangstatic int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip)
29777d89b08766c878a2594b15d203e513acf952340wwang{
29877d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
29977d89b08766c878a2594b15d203e513acf952340wwang	char *inquiry_default = (char *)"Generic-xD/SD/M.S.      1.00 ";
30077d89b08766c878a2594b15d203e513acf952340wwang	char *inquiry_sdms =    (char *)"Generic-SD/MemoryStick  1.00 ";
30177d89b08766c878a2594b15d203e513acf952340wwang	char *inquiry_sd =      (char *)"Generic-SD/MMC          1.00 ";
30277d89b08766c878a2594b15d203e513acf952340wwang	char *inquiry_ms =      (char *)"Generic-MemoryStick     1.00 ";
30377d89b08766c878a2594b15d203e513acf952340wwang	char *inquiry_string;
30477d89b08766c878a2594b15d203e513acf952340wwang	unsigned char sendbytes;
30577d89b08766c878a2594b15d203e513acf952340wwang	unsigned char *buf;
30677d89b08766c878a2594b15d203e513acf952340wwang	u8 card = get_lun_card(chip, lun);
30777d89b08766c878a2594b15d203e513acf952340wwang	int pro_formatter_flag = 0;
30877d89b08766c878a2594b15d203e513acf952340wwang	unsigned char inquiry_buf[] = {
30977d89b08766c878a2594b15d203e513acf952340wwang		QULIFIRE|DRCT_ACCESS_DEV,
31077d89b08766c878a2594b15d203e513acf952340wwang		RMB_DISC|0x0D,
31177d89b08766c878a2594b15d203e513acf952340wwang		0x00,
31277d89b08766c878a2594b15d203e513acf952340wwang		0x01,
31377d89b08766c878a2594b15d203e513acf952340wwang		0x1f,
31477d89b08766c878a2594b15d203e513acf952340wwang		0x02,
31577d89b08766c878a2594b15d203e513acf952340wwang		0,
31677d89b08766c878a2594b15d203e513acf952340wwang		REL_ADR|WBUS_32|WBUS_16|SYNC|LINKED|CMD_QUE|SFT_RE,
31777d89b08766c878a2594b15d203e513acf952340wwang	};
31877d89b08766c878a2594b15d203e513acf952340wwang
31977d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
32077d89b08766c878a2594b15d203e513acf952340wwang		if (chip->lun2card[lun] == SD_CARD) {
32177d89b08766c878a2594b15d203e513acf952340wwang			inquiry_string = inquiry_sd;
32277d89b08766c878a2594b15d203e513acf952340wwang		} else {
32377d89b08766c878a2594b15d203e513acf952340wwang			inquiry_string = inquiry_ms;
32477d89b08766c878a2594b15d203e513acf952340wwang		}
32577d89b08766c878a2594b15d203e513acf952340wwang	} else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) {
32677d89b08766c878a2594b15d203e513acf952340wwang		inquiry_string = inquiry_sdms;
32777d89b08766c878a2594b15d203e513acf952340wwang	} else {
32877d89b08766c878a2594b15d203e513acf952340wwang		inquiry_string = inquiry_default;
32977d89b08766c878a2594b15d203e513acf952340wwang	}
33077d89b08766c878a2594b15d203e513acf952340wwang
33177d89b08766c878a2594b15d203e513acf952340wwang	buf = vmalloc(scsi_bufflen(srb));
33277d89b08766c878a2594b15d203e513acf952340wwang	if (buf == NULL) {
33377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
33477d89b08766c878a2594b15d203e513acf952340wwang	}
33577d89b08766c878a2594b15d203e513acf952340wwang
33677d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_MAGIC_GATE
33777d89b08766c878a2594b15d203e513acf952340wwang	if ((chip->mspro_formatter_enable) &&
33877d89b08766c878a2594b15d203e513acf952340wwang			(chip->lun2card[lun] & MS_CARD))
33977d89b08766c878a2594b15d203e513acf952340wwang#else
34077d89b08766c878a2594b15d203e513acf952340wwang	if (chip->mspro_formatter_enable)
34177d89b08766c878a2594b15d203e513acf952340wwang#endif
34277d89b08766c878a2594b15d203e513acf952340wwang	{
34377d89b08766c878a2594b15d203e513acf952340wwang		if (!card || (card == MS_CARD)) {
34477d89b08766c878a2594b15d203e513acf952340wwang			pro_formatter_flag = 1;
34577d89b08766c878a2594b15d203e513acf952340wwang		}
34677d89b08766c878a2594b15d203e513acf952340wwang	}
34777d89b08766c878a2594b15d203e513acf952340wwang
34877d89b08766c878a2594b15d203e513acf952340wwang	if (pro_formatter_flag) {
34977d89b08766c878a2594b15d203e513acf952340wwang		if (scsi_bufflen(srb) < 56) {
35077d89b08766c878a2594b15d203e513acf952340wwang			sendbytes = (unsigned char)(scsi_bufflen(srb));
35177d89b08766c878a2594b15d203e513acf952340wwang		} else {
35277d89b08766c878a2594b15d203e513acf952340wwang			sendbytes = 56;
35377d89b08766c878a2594b15d203e513acf952340wwang		}
35477d89b08766c878a2594b15d203e513acf952340wwang	} else {
35577d89b08766c878a2594b15d203e513acf952340wwang		if (scsi_bufflen(srb) < 36) {
35677d89b08766c878a2594b15d203e513acf952340wwang			sendbytes = (unsigned char)(scsi_bufflen(srb));
35777d89b08766c878a2594b15d203e513acf952340wwang		} else {
35877d89b08766c878a2594b15d203e513acf952340wwang			sendbytes = 36;
35977d89b08766c878a2594b15d203e513acf952340wwang		}
36077d89b08766c878a2594b15d203e513acf952340wwang	}
36177d89b08766c878a2594b15d203e513acf952340wwang
36277d89b08766c878a2594b15d203e513acf952340wwang	if (sendbytes > 8) {
36377d89b08766c878a2594b15d203e513acf952340wwang		memcpy(buf, inquiry_buf, 8);
36477d89b08766c878a2594b15d203e513acf952340wwang		memcpy(buf + 8, inquiry_string,	sendbytes - 8);
36577d89b08766c878a2594b15d203e513acf952340wwang		if (pro_formatter_flag) {
36677d89b08766c878a2594b15d203e513acf952340wwang			/* Additional Length */
36777d89b08766c878a2594b15d203e513acf952340wwang			buf[4] = 0x33;
36877d89b08766c878a2594b15d203e513acf952340wwang		}
36977d89b08766c878a2594b15d203e513acf952340wwang	} else {
37077d89b08766c878a2594b15d203e513acf952340wwang		memcpy(buf, inquiry_buf, sendbytes);
37177d89b08766c878a2594b15d203e513acf952340wwang	}
37277d89b08766c878a2594b15d203e513acf952340wwang
37377d89b08766c878a2594b15d203e513acf952340wwang	if (pro_formatter_flag) {
37477d89b08766c878a2594b15d203e513acf952340wwang		if (sendbytes > 36) {
37577d89b08766c878a2594b15d203e513acf952340wwang			memcpy(buf + 36, formatter_inquiry_str, sendbytes - 36);
37677d89b08766c878a2594b15d203e513acf952340wwang		}
37777d89b08766c878a2594b15d203e513acf952340wwang	}
37877d89b08766c878a2594b15d203e513acf952340wwang
37977d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
38077d89b08766c878a2594b15d203e513acf952340wwang
38177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
38277d89b08766c878a2594b15d203e513acf952340wwang	vfree(buf);
38377d89b08766c878a2594b15d203e513acf952340wwang
38477d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
38577d89b08766c878a2594b15d203e513acf952340wwang}
38677d89b08766c878a2594b15d203e513acf952340wwang
38777d89b08766c878a2594b15d203e513acf952340wwang
38877d89b08766c878a2594b15d203e513acf952340wwangstatic int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip)
38977d89b08766c878a2594b15d203e513acf952340wwang{
39077d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
39177d89b08766c878a2594b15d203e513acf952340wwang
39277d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb));
39377d89b08766c878a2594b15d203e513acf952340wwang
39477d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[1] == 1)
39577d89b08766c878a2594b15d203e513acf952340wwang		return TRANSPORT_GOOD;
39677d89b08766c878a2594b15d203e513acf952340wwang
39777d89b08766c878a2594b15d203e513acf952340wwang	switch (srb->cmnd[0x4]) {
39877d89b08766c878a2594b15d203e513acf952340wwang	case STOP_MEDIUM:
39977d89b08766c878a2594b15d203e513acf952340wwang		/* Media disabled */
40077d89b08766c878a2594b15d203e513acf952340wwang		return TRANSPORT_GOOD;
40177d89b08766c878a2594b15d203e513acf952340wwang
40277d89b08766c878a2594b15d203e513acf952340wwang	case UNLOAD_MEDIUM:
40377d89b08766c878a2594b15d203e513acf952340wwang		/* Media shall be unload */
40477d89b08766c878a2594b15d203e513acf952340wwang		if (check_card_ready(chip, lun))
40577d89b08766c878a2594b15d203e513acf952340wwang			eject_card(chip, lun);
40677d89b08766c878a2594b15d203e513acf952340wwang		return TRANSPORT_GOOD;
40777d89b08766c878a2594b15d203e513acf952340wwang
40877d89b08766c878a2594b15d203e513acf952340wwang	case MAKE_MEDIUM_READY:
40977d89b08766c878a2594b15d203e513acf952340wwang	case LOAD_MEDIUM:
41077d89b08766c878a2594b15d203e513acf952340wwang		if (check_card_ready(chip, lun)) {
41177d89b08766c878a2594b15d203e513acf952340wwang			return TRANSPORT_GOOD;
41277d89b08766c878a2594b15d203e513acf952340wwang		} else {
41377d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
41477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
41577d89b08766c878a2594b15d203e513acf952340wwang		}
41677d89b08766c878a2594b15d203e513acf952340wwang
41777d89b08766c878a2594b15d203e513acf952340wwang		break;
41877d89b08766c878a2594b15d203e513acf952340wwang	}
41977d89b08766c878a2594b15d203e513acf952340wwang
42077d89b08766c878a2594b15d203e513acf952340wwang	TRACE_RET(chip, TRANSPORT_ERROR);
42177d89b08766c878a2594b15d203e513acf952340wwang}
42277d89b08766c878a2594b15d203e513acf952340wwang
42377d89b08766c878a2594b15d203e513acf952340wwang
42477d89b08766c878a2594b15d203e513acf952340wwangstatic int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip)
42577d89b08766c878a2594b15d203e513acf952340wwang{
42677d89b08766c878a2594b15d203e513acf952340wwang	int prevent;
42777d89b08766c878a2594b15d203e513acf952340wwang
42877d89b08766c878a2594b15d203e513acf952340wwang	prevent = srb->cmnd[4] & 0x1;
42977d89b08766c878a2594b15d203e513acf952340wwang
43077d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
43177d89b08766c878a2594b15d203e513acf952340wwang
43277d89b08766c878a2594b15d203e513acf952340wwang	if (prevent) {
43377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
43477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
43577d89b08766c878a2594b15d203e513acf952340wwang	}
43677d89b08766c878a2594b15d203e513acf952340wwang
43777d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
43877d89b08766c878a2594b15d203e513acf952340wwang}
43977d89b08766c878a2594b15d203e513acf952340wwang
44077d89b08766c878a2594b15d203e513acf952340wwang
44177d89b08766c878a2594b15d203e513acf952340wwangstatic int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
44277d89b08766c878a2594b15d203e513acf952340wwang{
44377d89b08766c878a2594b15d203e513acf952340wwang	struct sense_data_t *sense;
44477d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
44577d89b08766c878a2594b15d203e513acf952340wwang	struct ms_info *ms_card = &(chip->ms_card);
44677d89b08766c878a2594b15d203e513acf952340wwang	unsigned char *tmp, *buf;
44777d89b08766c878a2594b15d203e513acf952340wwang
44877d89b08766c878a2594b15d203e513acf952340wwang	sense = &(chip->sense_buffer[lun]);
44977d89b08766c878a2594b15d203e513acf952340wwang
45077d89b08766c878a2594b15d203e513acf952340wwang	if ((get_lun_card(chip, lun) == MS_CARD) && ms_card->pro_under_formatting) {
45177d89b08766c878a2594b15d203e513acf952340wwang		if (ms_card->format_status == FORMAT_SUCCESS) {
45277d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
45377d89b08766c878a2594b15d203e513acf952340wwang			ms_card->pro_under_formatting = 0;
45477d89b08766c878a2594b15d203e513acf952340wwang			ms_card->progress = 0;
45577d89b08766c878a2594b15d203e513acf952340wwang		} else if (ms_card->format_status == FORMAT_IN_PROGRESS) {
45677d89b08766c878a2594b15d203e513acf952340wwang			/* Logical Unit Not Ready Format in Progress */
45777d89b08766c878a2594b15d203e513acf952340wwang			set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
45877d89b08766c878a2594b15d203e513acf952340wwang					0, (u16)(ms_card->progress));
45977d89b08766c878a2594b15d203e513acf952340wwang		} else {
46077d89b08766c878a2594b15d203e513acf952340wwang			/* Format Command Failed */
46177d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
46277d89b08766c878a2594b15d203e513acf952340wwang			ms_card->pro_under_formatting = 0;
46377d89b08766c878a2594b15d203e513acf952340wwang			ms_card->progress = 0;
46477d89b08766c878a2594b15d203e513acf952340wwang		}
46577d89b08766c878a2594b15d203e513acf952340wwang
46677d89b08766c878a2594b15d203e513acf952340wwang		rtsx_set_stat(chip, RTSX_STAT_RUN);
46777d89b08766c878a2594b15d203e513acf952340wwang	}
46877d89b08766c878a2594b15d203e513acf952340wwang
46977d89b08766c878a2594b15d203e513acf952340wwang	buf = vmalloc(scsi_bufflen(srb));
47077d89b08766c878a2594b15d203e513acf952340wwang	if (buf == NULL) {
47177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
47277d89b08766c878a2594b15d203e513acf952340wwang	}
47377d89b08766c878a2594b15d203e513acf952340wwang
47477d89b08766c878a2594b15d203e513acf952340wwang	tmp = (unsigned char *)sense;
47577d89b08766c878a2594b15d203e513acf952340wwang	memcpy(buf, tmp, scsi_bufflen(srb));
47677d89b08766c878a2594b15d203e513acf952340wwang
47777d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
47877d89b08766c878a2594b15d203e513acf952340wwang	vfree(buf);
47977d89b08766c878a2594b15d203e513acf952340wwang
48077d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
48177d89b08766c878a2594b15d203e513acf952340wwang	/* Reset Sense Data */
48277d89b08766c878a2594b15d203e513acf952340wwang	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
48377d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
48477d89b08766c878a2594b15d203e513acf952340wwang}
48577d89b08766c878a2594b15d203e513acf952340wwang
48677d89b08766c878a2594b15d203e513acf952340wwangstatic void ms_mode_sense(struct rtsx_chip *chip, u8 cmd,
48777d89b08766c878a2594b15d203e513acf952340wwang		int lun, u8 *buf, int buf_len)
48877d89b08766c878a2594b15d203e513acf952340wwang{
48977d89b08766c878a2594b15d203e513acf952340wwang	struct ms_info *ms_card = &(chip->ms_card);
49077d89b08766c878a2594b15d203e513acf952340wwang	int sys_info_offset;
49177d89b08766c878a2594b15d203e513acf952340wwang	int data_size = buf_len;
49277d89b08766c878a2594b15d203e513acf952340wwang	int support_format = 0;
49377d89b08766c878a2594b15d203e513acf952340wwang	int i = 0;
49477d89b08766c878a2594b15d203e513acf952340wwang
49577d89b08766c878a2594b15d203e513acf952340wwang	if (cmd == MODE_SENSE) {
49677d89b08766c878a2594b15d203e513acf952340wwang		sys_info_offset = 8;
49777d89b08766c878a2594b15d203e513acf952340wwang		if (data_size > 0x68) {
49877d89b08766c878a2594b15d203e513acf952340wwang			data_size = 0x68;
49977d89b08766c878a2594b15d203e513acf952340wwang		}
50077d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x67;  /* Mode Data Length */
50177d89b08766c878a2594b15d203e513acf952340wwang	} else {
50277d89b08766c878a2594b15d203e513acf952340wwang		sys_info_offset = 12;
50377d89b08766c878a2594b15d203e513acf952340wwang		if (data_size > 0x6C) {
50477d89b08766c878a2594b15d203e513acf952340wwang			data_size = 0x6C;
50577d89b08766c878a2594b15d203e513acf952340wwang		}
50677d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x00;  /* Mode Data Length (MSB) */
50777d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x6A;  /* Mode Data Length (LSB) */
50877d89b08766c878a2594b15d203e513acf952340wwang	}
50977d89b08766c878a2594b15d203e513acf952340wwang
51077d89b08766c878a2594b15d203e513acf952340wwang	/* Medium Type Code */
51177d89b08766c878a2594b15d203e513acf952340wwang	if (check_card_ready(chip, lun)) {
51277d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_MSXC(ms_card)) {
51377d89b08766c878a2594b15d203e513acf952340wwang			support_format = 1;
51477d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0x40;
51577d89b08766c878a2594b15d203e513acf952340wwang		} else if (CHK_MSPRO(ms_card)) {
51677d89b08766c878a2594b15d203e513acf952340wwang			support_format = 1;
51777d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0x20;
51877d89b08766c878a2594b15d203e513acf952340wwang		} else {
51977d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0x10;
52077d89b08766c878a2594b15d203e513acf952340wwang		}
52177d89b08766c878a2594b15d203e513acf952340wwang
52277d89b08766c878a2594b15d203e513acf952340wwang		/* WP */
52377d89b08766c878a2594b15d203e513acf952340wwang		if (check_card_wp(chip, lun)) {
52477d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0x80;
52577d89b08766c878a2594b15d203e513acf952340wwang		} else {
52677d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0x00;
52777d89b08766c878a2594b15d203e513acf952340wwang		}
52877d89b08766c878a2594b15d203e513acf952340wwang	} else {
52977d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x00;	/* MediaType */
53077d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x00;	/* WP */
53177d89b08766c878a2594b15d203e513acf952340wwang	}
53277d89b08766c878a2594b15d203e513acf952340wwang
53377d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = 0x00;		/* Reserved */
53477d89b08766c878a2594b15d203e513acf952340wwang
53577d89b08766c878a2594b15d203e513acf952340wwang	if (cmd == MODE_SENSE_10) {
53677d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x00;  /* Reserved */
53777d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x00;  /* Block descriptor length(MSB) */
53877d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x00;  /* Block descriptor length(LSB) */
53977d89b08766c878a2594b15d203e513acf952340wwang
54077d89b08766c878a2594b15d203e513acf952340wwang		/* The Following Data is the content of "Page 0x20" */
54177d89b08766c878a2594b15d203e513acf952340wwang		if (data_size >= 9)
54277d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0x20;		/* Page Code */
54377d89b08766c878a2594b15d203e513acf952340wwang		if (data_size >= 10)
54477d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0x62;		/* Page Length */
54577d89b08766c878a2594b15d203e513acf952340wwang		if (data_size >= 11)
54677d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0x00;		/* No Access Control */
54777d89b08766c878a2594b15d203e513acf952340wwang		if (data_size >= 12) {
54877d89b08766c878a2594b15d203e513acf952340wwang			if (support_format) {
54977d89b08766c878a2594b15d203e513acf952340wwang				buf[i++] = 0xC0;	/* SF, SGM */
55077d89b08766c878a2594b15d203e513acf952340wwang			} else {
55177d89b08766c878a2594b15d203e513acf952340wwang				buf[i++] = 0x00;
55277d89b08766c878a2594b15d203e513acf952340wwang			}
55377d89b08766c878a2594b15d203e513acf952340wwang		}
55477d89b08766c878a2594b15d203e513acf952340wwang	} else {
55577d89b08766c878a2594b15d203e513acf952340wwang		/* The Following Data is the content of "Page 0x20" */
55677d89b08766c878a2594b15d203e513acf952340wwang		if (data_size >= 5)
55777d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0x20;		/* Page Code */
55877d89b08766c878a2594b15d203e513acf952340wwang		if (data_size >= 6)
55977d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0x62;		/* Page Length */
56077d89b08766c878a2594b15d203e513acf952340wwang		if (data_size >= 7)
56177d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0x00;		/* No Access Control */
56277d89b08766c878a2594b15d203e513acf952340wwang		if (data_size >= 8) {
56377d89b08766c878a2594b15d203e513acf952340wwang			if (support_format) {
56477d89b08766c878a2594b15d203e513acf952340wwang				buf[i++] = 0xC0;	/* SF, SGM */
56577d89b08766c878a2594b15d203e513acf952340wwang			} else {
56677d89b08766c878a2594b15d203e513acf952340wwang				buf[i++] = 0x00;
56777d89b08766c878a2594b15d203e513acf952340wwang			}
56877d89b08766c878a2594b15d203e513acf952340wwang		}
56977d89b08766c878a2594b15d203e513acf952340wwang	}
57077d89b08766c878a2594b15d203e513acf952340wwang
57177d89b08766c878a2594b15d203e513acf952340wwang	if (data_size > sys_info_offset) {
57277d89b08766c878a2594b15d203e513acf952340wwang		/* 96 Bytes Attribute Data */
57377d89b08766c878a2594b15d203e513acf952340wwang		int len = data_size - sys_info_offset;
57477d89b08766c878a2594b15d203e513acf952340wwang		len = (len < 96) ? len : 96;
57577d89b08766c878a2594b15d203e513acf952340wwang
57677d89b08766c878a2594b15d203e513acf952340wwang		memcpy(buf + sys_info_offset, ms_card->raw_sys_info, len);
57777d89b08766c878a2594b15d203e513acf952340wwang	}
57877d89b08766c878a2594b15d203e513acf952340wwang}
57977d89b08766c878a2594b15d203e513acf952340wwang
58077d89b08766c878a2594b15d203e513acf952340wwangstatic int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
58177d89b08766c878a2594b15d203e513acf952340wwang{
58277d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
58377d89b08766c878a2594b15d203e513acf952340wwang	unsigned int dataSize;
58477d89b08766c878a2594b15d203e513acf952340wwang	int status;
58577d89b08766c878a2594b15d203e513acf952340wwang	int pro_formatter_flag;
58677d89b08766c878a2594b15d203e513acf952340wwang	unsigned char pageCode, *buf;
58777d89b08766c878a2594b15d203e513acf952340wwang	u8 card = get_lun_card(chip, lun);
58877d89b08766c878a2594b15d203e513acf952340wwang
58977d89b08766c878a2594b15d203e513acf952340wwang#ifndef SUPPORT_MAGIC_GATE
59077d89b08766c878a2594b15d203e513acf952340wwang	if (!check_card_ready(chip, lun)) {
59177d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
59277d89b08766c878a2594b15d203e513acf952340wwang		scsi_set_resid(srb, scsi_bufflen(srb));
59377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
59477d89b08766c878a2594b15d203e513acf952340wwang	}
59577d89b08766c878a2594b15d203e513acf952340wwang#endif
59677d89b08766c878a2594b15d203e513acf952340wwang
59777d89b08766c878a2594b15d203e513acf952340wwang	pro_formatter_flag = 0;
59877d89b08766c878a2594b15d203e513acf952340wwang	dataSize = 8;
59977d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_MAGIC_GATE
60077d89b08766c878a2594b15d203e513acf952340wwang	if ((chip->lun2card[lun] & MS_CARD)) {
60177d89b08766c878a2594b15d203e513acf952340wwang		if (!card || (card == MS_CARD)) {
60277d89b08766c878a2594b15d203e513acf952340wwang			dataSize = 108;
60377d89b08766c878a2594b15d203e513acf952340wwang			if (chip->mspro_formatter_enable) {
60477d89b08766c878a2594b15d203e513acf952340wwang				pro_formatter_flag = 1;
60577d89b08766c878a2594b15d203e513acf952340wwang			}
60677d89b08766c878a2594b15d203e513acf952340wwang		}
60777d89b08766c878a2594b15d203e513acf952340wwang	}
60877d89b08766c878a2594b15d203e513acf952340wwang#else
60977d89b08766c878a2594b15d203e513acf952340wwang	if (card == MS_CARD) {
61077d89b08766c878a2594b15d203e513acf952340wwang		if (chip->mspro_formatter_enable) {
61177d89b08766c878a2594b15d203e513acf952340wwang			pro_formatter_flag = 1;
61277d89b08766c878a2594b15d203e513acf952340wwang			dataSize = 108;
61377d89b08766c878a2594b15d203e513acf952340wwang		}
61477d89b08766c878a2594b15d203e513acf952340wwang	}
61577d89b08766c878a2594b15d203e513acf952340wwang#endif
61677d89b08766c878a2594b15d203e513acf952340wwang
61777d89b08766c878a2594b15d203e513acf952340wwang	buf = kmalloc(dataSize, GFP_KERNEL);
61877d89b08766c878a2594b15d203e513acf952340wwang	if (buf == NULL) {
61977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
62077d89b08766c878a2594b15d203e513acf952340wwang	}
62177d89b08766c878a2594b15d203e513acf952340wwang
62277d89b08766c878a2594b15d203e513acf952340wwang	pageCode = srb->cmnd[2] & 0x3f;
62377d89b08766c878a2594b15d203e513acf952340wwang
62477d89b08766c878a2594b15d203e513acf952340wwang	if ((pageCode == 0x3F) || (pageCode == 0x1C) ||
62577d89b08766c878a2594b15d203e513acf952340wwang		(pageCode == 0x00) ||
62677d89b08766c878a2594b15d203e513acf952340wwang		(pro_formatter_flag && (pageCode == 0x20))) {
62777d89b08766c878a2594b15d203e513acf952340wwang		if (srb->cmnd[0] == MODE_SENSE) {
62877d89b08766c878a2594b15d203e513acf952340wwang			if ((pageCode == 0x3F) || (pageCode == 0x20)) {
62977d89b08766c878a2594b15d203e513acf952340wwang				ms_mode_sense(chip, srb->cmnd[0],
63077d89b08766c878a2594b15d203e513acf952340wwang					      lun, buf, dataSize);
63177d89b08766c878a2594b15d203e513acf952340wwang			} else {
63277d89b08766c878a2594b15d203e513acf952340wwang				dataSize = 4;
63377d89b08766c878a2594b15d203e513acf952340wwang				buf[0] = 0x03;
63477d89b08766c878a2594b15d203e513acf952340wwang				buf[1] = 0x00;
63577d89b08766c878a2594b15d203e513acf952340wwang				if (check_card_wp(chip, lun)) {
63677d89b08766c878a2594b15d203e513acf952340wwang					buf[2] = 0x80;
63777d89b08766c878a2594b15d203e513acf952340wwang				} else {
63877d89b08766c878a2594b15d203e513acf952340wwang					buf[2] = 0x00;
63977d89b08766c878a2594b15d203e513acf952340wwang				}
64077d89b08766c878a2594b15d203e513acf952340wwang				buf[3] = 0x00;
64177d89b08766c878a2594b15d203e513acf952340wwang			}
64277d89b08766c878a2594b15d203e513acf952340wwang		} else {
64377d89b08766c878a2594b15d203e513acf952340wwang			if ((pageCode == 0x3F) || (pageCode == 0x20)) {
64477d89b08766c878a2594b15d203e513acf952340wwang				ms_mode_sense(chip, srb->cmnd[0],
64577d89b08766c878a2594b15d203e513acf952340wwang					      lun, buf, dataSize);
64677d89b08766c878a2594b15d203e513acf952340wwang			} else {
64777d89b08766c878a2594b15d203e513acf952340wwang				dataSize = 8;
64877d89b08766c878a2594b15d203e513acf952340wwang				buf[0] = 0x00;
64977d89b08766c878a2594b15d203e513acf952340wwang				buf[1] = 0x06;
65077d89b08766c878a2594b15d203e513acf952340wwang				buf[2] = 0x00;
65177d89b08766c878a2594b15d203e513acf952340wwang				if (check_card_wp(chip, lun)) {
65277d89b08766c878a2594b15d203e513acf952340wwang					buf[3] = 0x80;
65377d89b08766c878a2594b15d203e513acf952340wwang				} else {
65477d89b08766c878a2594b15d203e513acf952340wwang					buf[3] = 0x00;
65577d89b08766c878a2594b15d203e513acf952340wwang				}
65677d89b08766c878a2594b15d203e513acf952340wwang				buf[4] = 0x00;
65777d89b08766c878a2594b15d203e513acf952340wwang				buf[5] = 0x00;
65877d89b08766c878a2594b15d203e513acf952340wwang				buf[6] = 0x00;
65977d89b08766c878a2594b15d203e513acf952340wwang				buf[7] = 0x00;
66077d89b08766c878a2594b15d203e513acf952340wwang			}
66177d89b08766c878a2594b15d203e513acf952340wwang		}
66277d89b08766c878a2594b15d203e513acf952340wwang		status = TRANSPORT_GOOD;
66377d89b08766c878a2594b15d203e513acf952340wwang	} else {
66477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
66577d89b08766c878a2594b15d203e513acf952340wwang		scsi_set_resid(srb, scsi_bufflen(srb));
66677d89b08766c878a2594b15d203e513acf952340wwang		status = TRANSPORT_FAILED;
66777d89b08766c878a2594b15d203e513acf952340wwang	}
66877d89b08766c878a2594b15d203e513acf952340wwang
66977d89b08766c878a2594b15d203e513acf952340wwang	if (status == TRANSPORT_GOOD) {
67077d89b08766c878a2594b15d203e513acf952340wwang		unsigned int len = min(scsi_bufflen(srb), dataSize);
67177d89b08766c878a2594b15d203e513acf952340wwang		rtsx_stor_set_xfer_buf(buf, len, srb);
67277d89b08766c878a2594b15d203e513acf952340wwang		scsi_set_resid(srb, scsi_bufflen(srb) - len);
67377d89b08766c878a2594b15d203e513acf952340wwang	}
67477d89b08766c878a2594b15d203e513acf952340wwang	kfree(buf);
67577d89b08766c878a2594b15d203e513acf952340wwang
67677d89b08766c878a2594b15d203e513acf952340wwang	return status;
67777d89b08766c878a2594b15d203e513acf952340wwang}
67877d89b08766c878a2594b15d203e513acf952340wwang
67977d89b08766c878a2594b15d203e513acf952340wwangstatic int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
68077d89b08766c878a2594b15d203e513acf952340wwang{
68177d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
68277d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
68377d89b08766c878a2594b15d203e513acf952340wwang#endif
68477d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
68577d89b08766c878a2594b15d203e513acf952340wwang	int retval;
68677d89b08766c878a2594b15d203e513acf952340wwang	u32 start_sec;
68777d89b08766c878a2594b15d203e513acf952340wwang	u16 sec_cnt;
68877d89b08766c878a2594b15d203e513acf952340wwang
68977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
69077d89b08766c878a2594b15d203e513acf952340wwang
69177d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
69277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
69377d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
69477d89b08766c878a2594b15d203e513acf952340wwang	}
69577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
69677d89b08766c878a2594b15d203e513acf952340wwang
69777d89b08766c878a2594b15d203e513acf952340wwang	if (!check_card_ready(chip, lun) || (get_card_size(chip, lun) == 0)) {
69877d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
69977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
70077d89b08766c878a2594b15d203e513acf952340wwang	}
70177d89b08766c878a2594b15d203e513acf952340wwang
70277d89b08766c878a2594b15d203e513acf952340wwang	if (!(CHK_BIT(chip->lun_mc, lun))) {
70377d89b08766c878a2594b15d203e513acf952340wwang		SET_BIT(chip->lun_mc, lun);
70477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
70577d89b08766c878a2594b15d203e513acf952340wwang		return TRANSPORT_FAILED;
70677d89b08766c878a2594b15d203e513acf952340wwang	}
70777d89b08766c878a2594b15d203e513acf952340wwang
70877d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
70977d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->sd_erase_status) {
71077d89b08766c878a2594b15d203e513acf952340wwang		/* Accessing to any card is forbidden
71177d89b08766c878a2594b15d203e513acf952340wwang		 * until the erase procedure of SD is completed
71277d89b08766c878a2594b15d203e513acf952340wwang		 */
71377d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("SD card being erased!\n");
71477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
71577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
71677d89b08766c878a2594b15d203e513acf952340wwang	}
71777d89b08766c878a2594b15d203e513acf952340wwang
71877d89b08766c878a2594b15d203e513acf952340wwang	if (get_lun_card(chip, lun) == SD_CARD) {
71977d89b08766c878a2594b15d203e513acf952340wwang		if (sd_card->sd_lock_status & SD_LOCKED) {
72077d89b08766c878a2594b15d203e513acf952340wwang			RTSX_DEBUGP("SD card locked!\n");
72177d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
72277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
72377d89b08766c878a2594b15d203e513acf952340wwang		}
72477d89b08766c878a2594b15d203e513acf952340wwang	}
72577d89b08766c878a2594b15d203e513acf952340wwang#endif
72677d89b08766c878a2594b15d203e513acf952340wwang
72777d89b08766c878a2594b15d203e513acf952340wwang	if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) {
72877d89b08766c878a2594b15d203e513acf952340wwang		start_sec = ((u32)srb->cmnd[2] << 24) | ((u32)srb->cmnd[3] << 16) |
72977d89b08766c878a2594b15d203e513acf952340wwang			((u32)srb->cmnd[4] << 8) | ((u32)srb->cmnd[5]);
73077d89b08766c878a2594b15d203e513acf952340wwang		sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
73177d89b08766c878a2594b15d203e513acf952340wwang	} else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) {
73277d89b08766c878a2594b15d203e513acf952340wwang		start_sec = ((u32)(srb->cmnd[1] & 0x1F) << 16) |
73377d89b08766c878a2594b15d203e513acf952340wwang			((u32)srb->cmnd[2] << 8) | ((u32)srb->cmnd[3]);
73477d89b08766c878a2594b15d203e513acf952340wwang		sec_cnt = srb->cmnd[4];
73577d89b08766c878a2594b15d203e513acf952340wwang	} else if ((srb->cmnd[0] == VENDOR_CMND) && (srb->cmnd[1] == SCSI_APP_CMD) &&
73677d89b08766c878a2594b15d203e513acf952340wwang			((srb->cmnd[2] == PP_READ10) || (srb->cmnd[2] == PP_WRITE10))) {
73777d89b08766c878a2594b15d203e513acf952340wwang		start_sec = ((u32)srb->cmnd[4] << 24) | ((u32)srb->cmnd[5] << 16) |
73877d89b08766c878a2594b15d203e513acf952340wwang			((u32)srb->cmnd[6] << 8) | ((u32)srb->cmnd[7]);
73977d89b08766c878a2594b15d203e513acf952340wwang		sec_cnt = ((u16)(srb->cmnd[9]) << 8) | srb->cmnd[10];
74077d89b08766c878a2594b15d203e513acf952340wwang	} else {
74177d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
74277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
74377d89b08766c878a2594b15d203e513acf952340wwang	}
74477d89b08766c878a2594b15d203e513acf952340wwang
74577d89b08766c878a2594b15d203e513acf952340wwang	/* In some test, we will receive a start_sec like 0xFFFFFFFF.
74677d89b08766c878a2594b15d203e513acf952340wwang	 * In this situation, start_sec + sec_cnt will overflow, so we
74777d89b08766c878a2594b15d203e513acf952340wwang	 * need to judge start_sec at first
74877d89b08766c878a2594b15d203e513acf952340wwang	 */
74977d89b08766c878a2594b15d203e513acf952340wwang	if ((start_sec > get_card_size(chip, lun)) ||
75077d89b08766c878a2594b15d203e513acf952340wwang			((start_sec + sec_cnt) > get_card_size(chip, lun))) {
75177d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE);
75277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
75377d89b08766c878a2594b15d203e513acf952340wwang	}
75477d89b08766c878a2594b15d203e513acf952340wwang
75577d89b08766c878a2594b15d203e513acf952340wwang	if (sec_cnt == 0) {
75677d89b08766c878a2594b15d203e513acf952340wwang		scsi_set_resid(srb, 0);
75777d89b08766c878a2594b15d203e513acf952340wwang		return TRANSPORT_GOOD;
75877d89b08766c878a2594b15d203e513acf952340wwang	}
75977d89b08766c878a2594b15d203e513acf952340wwang
76077d89b08766c878a2594b15d203e513acf952340wwang	if (chip->rw_fail_cnt[lun] == 3) {
76177d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("read/write fail three times in succession\n");
76277d89b08766c878a2594b15d203e513acf952340wwang		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
76377d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
76477d89b08766c878a2594b15d203e513acf952340wwang		} else {
76577d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
76677d89b08766c878a2594b15d203e513acf952340wwang		}
76777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
76877d89b08766c878a2594b15d203e513acf952340wwang	}
76977d89b08766c878a2594b15d203e513acf952340wwang
77077d89b08766c878a2594b15d203e513acf952340wwang	if (srb->sc_data_direction == DMA_TO_DEVICE) {
77177d89b08766c878a2594b15d203e513acf952340wwang		if (check_card_wp(chip, lun)) {
77277d89b08766c878a2594b15d203e513acf952340wwang			RTSX_DEBUGP("Write protected card!\n");
77377d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
77477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
77577d89b08766c878a2594b15d203e513acf952340wwang		}
77677d89b08766c878a2594b15d203e513acf952340wwang		if (CHECK_PID(chip, 0x5209) && chip->max_payload) {
77777d89b08766c878a2594b15d203e513acf952340wwang			u8 val = 0x10 | (chip->max_payload << 5);
77877d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_write_cfg_dw(chip, 0, 0x78, 0xFF, val);
77977d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
78077d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_ERROR);
78177d89b08766c878a2594b15d203e513acf952340wwang			}
78277d89b08766c878a2594b15d203e513acf952340wwang		}
78377d89b08766c878a2594b15d203e513acf952340wwang	}
78477d89b08766c878a2594b15d203e513acf952340wwang
78577d89b08766c878a2594b15d203e513acf952340wwang	retval = card_rw(srb, chip, start_sec, sec_cnt);
78677d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
78777d89b08766c878a2594b15d203e513acf952340wwang		if (chip->need_release & chip->lun2card[lun]) {
78877d89b08766c878a2594b15d203e513acf952340wwang			chip->rw_fail_cnt[lun] = 0;
78977d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
79077d89b08766c878a2594b15d203e513acf952340wwang		} else {
79177d89b08766c878a2594b15d203e513acf952340wwang			chip->rw_fail_cnt[lun]++;
79277d89b08766c878a2594b15d203e513acf952340wwang			if (srb->sc_data_direction == DMA_FROM_DEVICE) {
79377d89b08766c878a2594b15d203e513acf952340wwang				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
79477d89b08766c878a2594b15d203e513acf952340wwang			} else {
79577d89b08766c878a2594b15d203e513acf952340wwang				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
79677d89b08766c878a2594b15d203e513acf952340wwang			}
79777d89b08766c878a2594b15d203e513acf952340wwang		}
79877d89b08766c878a2594b15d203e513acf952340wwang		retval = TRANSPORT_FAILED;
79977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_GOTO(chip, Exit);
80077d89b08766c878a2594b15d203e513acf952340wwang	} else {
80177d89b08766c878a2594b15d203e513acf952340wwang		chip->rw_fail_cnt[lun] = 0;
80277d89b08766c878a2594b15d203e513acf952340wwang		retval = TRANSPORT_GOOD;
80377d89b08766c878a2594b15d203e513acf952340wwang	}
80477d89b08766c878a2594b15d203e513acf952340wwang
80577d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
80677d89b08766c878a2594b15d203e513acf952340wwang
80777d89b08766c878a2594b15d203e513acf952340wwangExit:
80877d89b08766c878a2594b15d203e513acf952340wwang	if (srb->sc_data_direction == DMA_TO_DEVICE) {
80977d89b08766c878a2594b15d203e513acf952340wwang		if (CHECK_PID(chip, 0x5209) && chip->max_payload) {
81077d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_write_cfg_dw(chip, 0, 0x78, 0xFF, 0x10);
81177d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
81277d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_ERROR);
81377d89b08766c878a2594b15d203e513acf952340wwang			}
81477d89b08766c878a2594b15d203e513acf952340wwang		}
81577d89b08766c878a2594b15d203e513acf952340wwang	}
81677d89b08766c878a2594b15d203e513acf952340wwang
81777d89b08766c878a2594b15d203e513acf952340wwang	return retval;
81877d89b08766c878a2594b15d203e513acf952340wwang}
81977d89b08766c878a2594b15d203e513acf952340wwang
82077d89b08766c878a2594b15d203e513acf952340wwangstatic int read_format_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
82177d89b08766c878a2594b15d203e513acf952340wwang{
82277d89b08766c878a2594b15d203e513acf952340wwang	unsigned char *buf;
82377d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
82477d89b08766c878a2594b15d203e513acf952340wwang	unsigned int buf_len;
82577d89b08766c878a2594b15d203e513acf952340wwang	u8 card = get_lun_card(chip, lun);
82677d89b08766c878a2594b15d203e513acf952340wwang	u32 card_size;
82777d89b08766c878a2594b15d203e513acf952340wwang	int desc_cnt;
82877d89b08766c878a2594b15d203e513acf952340wwang	int i = 0;
82977d89b08766c878a2594b15d203e513acf952340wwang
83077d89b08766c878a2594b15d203e513acf952340wwang	if (!check_card_ready(chip, lun)) {
83177d89b08766c878a2594b15d203e513acf952340wwang		if (!chip->mspro_formatter_enable) {
83277d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
83377d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
83477d89b08766c878a2594b15d203e513acf952340wwang		}
83577d89b08766c878a2594b15d203e513acf952340wwang	}
83677d89b08766c878a2594b15d203e513acf952340wwang
83777d89b08766c878a2594b15d203e513acf952340wwang	buf_len = (scsi_bufflen(srb) > 12) ? 0x14 : 12;
83877d89b08766c878a2594b15d203e513acf952340wwang
83977d89b08766c878a2594b15d203e513acf952340wwang	buf = kmalloc(buf_len, GFP_KERNEL);
84077d89b08766c878a2594b15d203e513acf952340wwang	if (buf == NULL) {
84177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
84277d89b08766c878a2594b15d203e513acf952340wwang	}
84377d89b08766c878a2594b15d203e513acf952340wwang
84477d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = 0;
84577d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = 0;
84677d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = 0;
84777d89b08766c878a2594b15d203e513acf952340wwang
84877d89b08766c878a2594b15d203e513acf952340wwang	/* Capacity List Length */
84977d89b08766c878a2594b15d203e513acf952340wwang	if ((buf_len > 12) && chip->mspro_formatter_enable &&
85077d89b08766c878a2594b15d203e513acf952340wwang			(chip->lun2card[lun] & MS_CARD) &&
85177d89b08766c878a2594b15d203e513acf952340wwang			(!card || (card == MS_CARD))) {
85277d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x10;
85377d89b08766c878a2594b15d203e513acf952340wwang		desc_cnt = 2;
85477d89b08766c878a2594b15d203e513acf952340wwang	} else {
85577d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x08;
85677d89b08766c878a2594b15d203e513acf952340wwang		desc_cnt = 1;
85777d89b08766c878a2594b15d203e513acf952340wwang	}
85877d89b08766c878a2594b15d203e513acf952340wwang
85977d89b08766c878a2594b15d203e513acf952340wwang	while (desc_cnt) {
86077d89b08766c878a2594b15d203e513acf952340wwang		if (check_card_ready(chip, lun)) {
86177d89b08766c878a2594b15d203e513acf952340wwang			card_size = get_card_size(chip, lun);
86277d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = (unsigned char)(card_size >> 24);
86377d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = (unsigned char)(card_size >> 16);
86477d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = (unsigned char)(card_size >> 8);
86577d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = (unsigned char)card_size;
86677d89b08766c878a2594b15d203e513acf952340wwang
86777d89b08766c878a2594b15d203e513acf952340wwang			if (desc_cnt == 2) {
86877d89b08766c878a2594b15d203e513acf952340wwang				buf[i++] = 2;
86977d89b08766c878a2594b15d203e513acf952340wwang			} else {
87077d89b08766c878a2594b15d203e513acf952340wwang				buf[i++] = 0;
87177d89b08766c878a2594b15d203e513acf952340wwang			}
87277d89b08766c878a2594b15d203e513acf952340wwang		} else {
87377d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0xFF;
87477d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0xFF;
87577d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0xFF;
87677d89b08766c878a2594b15d203e513acf952340wwang			buf[i++] = 0xFF;
87777d89b08766c878a2594b15d203e513acf952340wwang
87877d89b08766c878a2594b15d203e513acf952340wwang			if (desc_cnt == 2) {
87977d89b08766c878a2594b15d203e513acf952340wwang				buf[i++] = 3;
88077d89b08766c878a2594b15d203e513acf952340wwang			} else {
88177d89b08766c878a2594b15d203e513acf952340wwang				buf[i++] = 0;
88277d89b08766c878a2594b15d203e513acf952340wwang			}
88377d89b08766c878a2594b15d203e513acf952340wwang		}
88477d89b08766c878a2594b15d203e513acf952340wwang
88577d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x00;
88677d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x02;
88777d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x00;
88877d89b08766c878a2594b15d203e513acf952340wwang
88977d89b08766c878a2594b15d203e513acf952340wwang		desc_cnt--;
89077d89b08766c878a2594b15d203e513acf952340wwang	}
89177d89b08766c878a2594b15d203e513acf952340wwang
89277d89b08766c878a2594b15d203e513acf952340wwang	buf_len = min(scsi_bufflen(srb), buf_len);
89377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, buf_len, srb);
89477d89b08766c878a2594b15d203e513acf952340wwang	kfree(buf);
89577d89b08766c878a2594b15d203e513acf952340wwang
89677d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
89777d89b08766c878a2594b15d203e513acf952340wwang
89877d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
89977d89b08766c878a2594b15d203e513acf952340wwang}
90077d89b08766c878a2594b15d203e513acf952340wwang
90177d89b08766c878a2594b15d203e513acf952340wwangstatic int read_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
90277d89b08766c878a2594b15d203e513acf952340wwang{
90377d89b08766c878a2594b15d203e513acf952340wwang	unsigned char *buf;
90477d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
90577d89b08766c878a2594b15d203e513acf952340wwang	u32 card_size;
90677d89b08766c878a2594b15d203e513acf952340wwang
90777d89b08766c878a2594b15d203e513acf952340wwang	if (!check_card_ready(chip, lun)) {
90877d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
90977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
91077d89b08766c878a2594b15d203e513acf952340wwang	}
91177d89b08766c878a2594b15d203e513acf952340wwang
91277d89b08766c878a2594b15d203e513acf952340wwang	if (!(CHK_BIT(chip->lun_mc, lun))) {
91377d89b08766c878a2594b15d203e513acf952340wwang		SET_BIT(chip->lun_mc, lun);
91477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
91577d89b08766c878a2594b15d203e513acf952340wwang		return TRANSPORT_FAILED;
91677d89b08766c878a2594b15d203e513acf952340wwang	}
91777d89b08766c878a2594b15d203e513acf952340wwang
91877d89b08766c878a2594b15d203e513acf952340wwang	buf = kmalloc(8, GFP_KERNEL);
91977d89b08766c878a2594b15d203e513acf952340wwang	if (buf == NULL) {
92077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
92177d89b08766c878a2594b15d203e513acf952340wwang	}
92277d89b08766c878a2594b15d203e513acf952340wwang
92377d89b08766c878a2594b15d203e513acf952340wwang	card_size = get_card_size(chip, lun);
92477d89b08766c878a2594b15d203e513acf952340wwang	buf[0] = (unsigned char)((card_size - 1) >> 24);
92577d89b08766c878a2594b15d203e513acf952340wwang	buf[1] = (unsigned char)((card_size - 1) >> 16);
92677d89b08766c878a2594b15d203e513acf952340wwang	buf[2] = (unsigned char)((card_size - 1) >> 8);
92777d89b08766c878a2594b15d203e513acf952340wwang	buf[3] = (unsigned char)(card_size - 1);
92877d89b08766c878a2594b15d203e513acf952340wwang
92977d89b08766c878a2594b15d203e513acf952340wwang	buf[4] = 0x00;
93077d89b08766c878a2594b15d203e513acf952340wwang	buf[5] = 0x00;
93177d89b08766c878a2594b15d203e513acf952340wwang	buf[6] = 0x02;
93277d89b08766c878a2594b15d203e513acf952340wwang	buf[7] = 0x00;
93377d89b08766c878a2594b15d203e513acf952340wwang
93477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
93577d89b08766c878a2594b15d203e513acf952340wwang	kfree(buf);
93677d89b08766c878a2594b15d203e513acf952340wwang
93777d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
93877d89b08766c878a2594b15d203e513acf952340wwang
93977d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
94077d89b08766c878a2594b15d203e513acf952340wwang}
94177d89b08766c878a2594b15d203e513acf952340wwang
94277d89b08766c878a2594b15d203e513acf952340wwangstatic int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
94377d89b08766c878a2594b15d203e513acf952340wwang{
94477d89b08766c878a2594b15d203e513acf952340wwang	unsigned short len, i;
94577d89b08766c878a2594b15d203e513acf952340wwang	int retval;
94677d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
94777d89b08766c878a2594b15d203e513acf952340wwang
94877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
94977d89b08766c878a2594b15d203e513acf952340wwang
95077d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
95177d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
95277d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
95377d89b08766c878a2594b15d203e513acf952340wwang	}
95477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
95577d89b08766c878a2594b15d203e513acf952340wwang
95677d89b08766c878a2594b15d203e513acf952340wwang	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
95777d89b08766c878a2594b15d203e513acf952340wwang
95877d89b08766c878a2594b15d203e513acf952340wwang	buf = (u8 *)vmalloc(len);
95977d89b08766c878a2594b15d203e513acf952340wwang	if (!buf) {
96077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
96177d89b08766c878a2594b15d203e513acf952340wwang	}
96277d89b08766c878a2594b15d203e513acf952340wwang
96377d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_force_power_on(chip, SSC_PDCTL);
96477d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
96577d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
96677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
96777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
96877d89b08766c878a2594b15d203e513acf952340wwang	}
96977d89b08766c878a2594b15d203e513acf952340wwang
97077d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < len; i++) {
97177d89b08766c878a2594b15d203e513acf952340wwang		retval = spi_read_eeprom(chip, i, buf + i);
97277d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
97377d89b08766c878a2594b15d203e513acf952340wwang			vfree(buf);
97477d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
97577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
97677d89b08766c878a2594b15d203e513acf952340wwang		}
97777d89b08766c878a2594b15d203e513acf952340wwang	}
97877d89b08766c878a2594b15d203e513acf952340wwang
97977d89b08766c878a2594b15d203e513acf952340wwang	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
98077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, len, srb);
98177d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - len);
98277d89b08766c878a2594b15d203e513acf952340wwang
98377d89b08766c878a2594b15d203e513acf952340wwang	vfree(buf);
98477d89b08766c878a2594b15d203e513acf952340wwang
98577d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
98677d89b08766c878a2594b15d203e513acf952340wwang}
98777d89b08766c878a2594b15d203e513acf952340wwang
98877d89b08766c878a2594b15d203e513acf952340wwangstatic int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
98977d89b08766c878a2594b15d203e513acf952340wwang{
99077d89b08766c878a2594b15d203e513acf952340wwang	unsigned short len, i;
99177d89b08766c878a2594b15d203e513acf952340wwang	int retval;
99277d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
99377d89b08766c878a2594b15d203e513acf952340wwang
99477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
99577d89b08766c878a2594b15d203e513acf952340wwang
99677d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
99777d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
99877d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
99977d89b08766c878a2594b15d203e513acf952340wwang	}
100077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
100177d89b08766c878a2594b15d203e513acf952340wwang
100277d89b08766c878a2594b15d203e513acf952340wwang	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
100377d89b08766c878a2594b15d203e513acf952340wwang
100477d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_force_power_on(chip, SSC_PDCTL);
100577d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
100677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
100777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
100877d89b08766c878a2594b15d203e513acf952340wwang	}
100977d89b08766c878a2594b15d203e513acf952340wwang
101077d89b08766c878a2594b15d203e513acf952340wwang	if (len == 511) {
101177d89b08766c878a2594b15d203e513acf952340wwang		retval = spi_erase_eeprom_chip(chip);
101277d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
101377d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
101477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
101577d89b08766c878a2594b15d203e513acf952340wwang		}
101677d89b08766c878a2594b15d203e513acf952340wwang	} else {
101777d89b08766c878a2594b15d203e513acf952340wwang		len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
101877d89b08766c878a2594b15d203e513acf952340wwang		buf = (u8 *)vmalloc(len);
101977d89b08766c878a2594b15d203e513acf952340wwang		if (buf == NULL) {
102077d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_ERROR);
102177d89b08766c878a2594b15d203e513acf952340wwang		}
102277d89b08766c878a2594b15d203e513acf952340wwang
102377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_stor_get_xfer_buf(buf, len, srb);
102477d89b08766c878a2594b15d203e513acf952340wwang		scsi_set_resid(srb, scsi_bufflen(srb) - len);
102577d89b08766c878a2594b15d203e513acf952340wwang
102677d89b08766c878a2594b15d203e513acf952340wwang		for (i = 0; i < len; i++) {
102777d89b08766c878a2594b15d203e513acf952340wwang			retval = spi_write_eeprom(chip, i, buf[i]);
102877d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
102977d89b08766c878a2594b15d203e513acf952340wwang				vfree(buf);
103077d89b08766c878a2594b15d203e513acf952340wwang				set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
103177d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
103277d89b08766c878a2594b15d203e513acf952340wwang			}
103377d89b08766c878a2594b15d203e513acf952340wwang		}
103477d89b08766c878a2594b15d203e513acf952340wwang
103577d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
103677d89b08766c878a2594b15d203e513acf952340wwang	}
103777d89b08766c878a2594b15d203e513acf952340wwang
103877d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
103977d89b08766c878a2594b15d203e513acf952340wwang}
104077d89b08766c878a2594b15d203e513acf952340wwang
104177d89b08766c878a2594b15d203e513acf952340wwangstatic int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
104277d89b08766c878a2594b15d203e513acf952340wwang{
104377d89b08766c878a2594b15d203e513acf952340wwang	unsigned short addr, len, i;
104477d89b08766c878a2594b15d203e513acf952340wwang	int retval;
104577d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
104677d89b08766c878a2594b15d203e513acf952340wwang
104777d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
104877d89b08766c878a2594b15d203e513acf952340wwang
104977d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
105077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
105177d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
105277d89b08766c878a2594b15d203e513acf952340wwang	}
105377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
105477d89b08766c878a2594b15d203e513acf952340wwang
105577d89b08766c878a2594b15d203e513acf952340wwang	addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3];
105677d89b08766c878a2594b15d203e513acf952340wwang	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
105777d89b08766c878a2594b15d203e513acf952340wwang
105877d89b08766c878a2594b15d203e513acf952340wwang	if (addr < 0xFC00) {
105977d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
106077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
106177d89b08766c878a2594b15d203e513acf952340wwang	}
106277d89b08766c878a2594b15d203e513acf952340wwang
106377d89b08766c878a2594b15d203e513acf952340wwang	buf = (u8 *)vmalloc(len);
106477d89b08766c878a2594b15d203e513acf952340wwang	if (!buf) {
106577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
106677d89b08766c878a2594b15d203e513acf952340wwang	}
106777d89b08766c878a2594b15d203e513acf952340wwang
106877d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_force_power_on(chip, SSC_PDCTL);
106977d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
107077d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
107177d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
107277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
107377d89b08766c878a2594b15d203e513acf952340wwang	}
107477d89b08766c878a2594b15d203e513acf952340wwang
107577d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < len; i++) {
107677d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_read_register(chip, addr + i, buf + i);
107777d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
107877d89b08766c878a2594b15d203e513acf952340wwang			vfree(buf);
107977d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
108077d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
108177d89b08766c878a2594b15d203e513acf952340wwang		}
108277d89b08766c878a2594b15d203e513acf952340wwang	}
108377d89b08766c878a2594b15d203e513acf952340wwang
108477d89b08766c878a2594b15d203e513acf952340wwang	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
108577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, len, srb);
108677d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - len);
108777d89b08766c878a2594b15d203e513acf952340wwang
108877d89b08766c878a2594b15d203e513acf952340wwang	vfree(buf);
108977d89b08766c878a2594b15d203e513acf952340wwang
109077d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
109177d89b08766c878a2594b15d203e513acf952340wwang}
109277d89b08766c878a2594b15d203e513acf952340wwang
109377d89b08766c878a2594b15d203e513acf952340wwangstatic int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
109477d89b08766c878a2594b15d203e513acf952340wwang{
109577d89b08766c878a2594b15d203e513acf952340wwang	unsigned short addr, len, i;
109677d89b08766c878a2594b15d203e513acf952340wwang	int retval;
109777d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
109877d89b08766c878a2594b15d203e513acf952340wwang
109977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
110077d89b08766c878a2594b15d203e513acf952340wwang
110177d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
110277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
110377d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
110477d89b08766c878a2594b15d203e513acf952340wwang	}
110577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
110677d89b08766c878a2594b15d203e513acf952340wwang
110777d89b08766c878a2594b15d203e513acf952340wwang	addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3];
110877d89b08766c878a2594b15d203e513acf952340wwang	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
110977d89b08766c878a2594b15d203e513acf952340wwang
111077d89b08766c878a2594b15d203e513acf952340wwang	if (addr < 0xFC00) {
111177d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
111277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
111377d89b08766c878a2594b15d203e513acf952340wwang	}
111477d89b08766c878a2594b15d203e513acf952340wwang
111577d89b08766c878a2594b15d203e513acf952340wwang	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
111677d89b08766c878a2594b15d203e513acf952340wwang	buf = (u8 *)vmalloc(len);
111777d89b08766c878a2594b15d203e513acf952340wwang	if (buf == NULL) {
111877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
111977d89b08766c878a2594b15d203e513acf952340wwang	}
112077d89b08766c878a2594b15d203e513acf952340wwang
112177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_get_xfer_buf(buf, len, srb);
112277d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - len);
112377d89b08766c878a2594b15d203e513acf952340wwang
112477d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_force_power_on(chip, SSC_PDCTL);
112577d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
112677d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
112777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
112877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
112977d89b08766c878a2594b15d203e513acf952340wwang	}
113077d89b08766c878a2594b15d203e513acf952340wwang
113177d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < len; i++) {
113277d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_register(chip, addr + i, 0xFF, buf[i]);
113377d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
113477d89b08766c878a2594b15d203e513acf952340wwang			vfree(buf);
113577d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
113677d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
113777d89b08766c878a2594b15d203e513acf952340wwang		}
113877d89b08766c878a2594b15d203e513acf952340wwang	}
113977d89b08766c878a2594b15d203e513acf952340wwang
114077d89b08766c878a2594b15d203e513acf952340wwang	vfree(buf);
114177d89b08766c878a2594b15d203e513acf952340wwang
114277d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
114377d89b08766c878a2594b15d203e513acf952340wwang}
114477d89b08766c878a2594b15d203e513acf952340wwang
114577d89b08766c878a2594b15d203e513acf952340wwangstatic int get_sd_csd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
114677d89b08766c878a2594b15d203e513acf952340wwang{
114777d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
114877d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
114977d89b08766c878a2594b15d203e513acf952340wwang
115077d89b08766c878a2594b15d203e513acf952340wwang	if (!check_card_ready(chip, lun)) {
115177d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
115277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
115377d89b08766c878a2594b15d203e513acf952340wwang	}
115477d89b08766c878a2594b15d203e513acf952340wwang
115577d89b08766c878a2594b15d203e513acf952340wwang	if (get_lun_card(chip, lun) != SD_CARD) {
115677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
115777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
115877d89b08766c878a2594b15d203e513acf952340wwang	}
115977d89b08766c878a2594b15d203e513acf952340wwang
116077d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
116177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(sd_card->raw_csd, scsi_bufflen(srb), srb);
116277d89b08766c878a2594b15d203e513acf952340wwang
116377d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
116477d89b08766c878a2594b15d203e513acf952340wwang}
116577d89b08766c878a2594b15d203e513acf952340wwang
116677d89b08766c878a2594b15d203e513acf952340wwangstatic int toggle_gpio_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
116777d89b08766c878a2594b15d203e513acf952340wwang{
116877d89b08766c878a2594b15d203e513acf952340wwang	u8 gpio = srb->cmnd[2];
116977d89b08766c878a2594b15d203e513acf952340wwang
117077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
117177d89b08766c878a2594b15d203e513acf952340wwang
117277d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
117377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
117477d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
117577d89b08766c878a2594b15d203e513acf952340wwang	}
117677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
117777d89b08766c878a2594b15d203e513acf952340wwang
117877d89b08766c878a2594b15d203e513acf952340wwang	if (gpio > 3)
117977d89b08766c878a2594b15d203e513acf952340wwang		gpio = 1;
118077d89b08766c878a2594b15d203e513acf952340wwang	toggle_gpio(chip, gpio);
118177d89b08766c878a2594b15d203e513acf952340wwang
118277d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
118377d89b08766c878a2594b15d203e513acf952340wwang}
118477d89b08766c878a2594b15d203e513acf952340wwang
118577d89b08766c878a2594b15d203e513acf952340wwang#ifdef _MSG_TRACE
118677d89b08766c878a2594b15d203e513acf952340wwangstatic int trace_msg_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
118777d89b08766c878a2594b15d203e513acf952340wwang{
118877d89b08766c878a2594b15d203e513acf952340wwang	unsigned char *ptr, *buf = NULL;
118977d89b08766c878a2594b15d203e513acf952340wwang	int i, msg_cnt;
119077d89b08766c878a2594b15d203e513acf952340wwang	u8 clear;
119177d89b08766c878a2594b15d203e513acf952340wwang	unsigned int buf_len;
119277d89b08766c878a2594b15d203e513acf952340wwang
119377d89b08766c878a2594b15d203e513acf952340wwang	buf_len = 4 + ((2 + MSG_FUNC_LEN + MSG_FILE_LEN + TIME_VAL_LEN) * TRACE_ITEM_CNT);
119477d89b08766c878a2594b15d203e513acf952340wwang
119577d89b08766c878a2594b15d203e513acf952340wwang	if ((scsi_bufflen(srb) < buf_len) || (scsi_sglist(srb) == NULL)) {
119677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
119777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
119877d89b08766c878a2594b15d203e513acf952340wwang	}
119977d89b08766c878a2594b15d203e513acf952340wwang
120077d89b08766c878a2594b15d203e513acf952340wwang	clear = srb->cmnd[2];
120177d89b08766c878a2594b15d203e513acf952340wwang
120277d89b08766c878a2594b15d203e513acf952340wwang	buf = (unsigned char *)vmalloc(scsi_bufflen(srb));
120377d89b08766c878a2594b15d203e513acf952340wwang	if (buf == NULL) {
120477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
120577d89b08766c878a2594b15d203e513acf952340wwang	}
120677d89b08766c878a2594b15d203e513acf952340wwang	ptr = buf;
120777d89b08766c878a2594b15d203e513acf952340wwang
120877d89b08766c878a2594b15d203e513acf952340wwang	if (chip->trace_msg[chip->msg_idx].valid) {
120977d89b08766c878a2594b15d203e513acf952340wwang		msg_cnt = TRACE_ITEM_CNT;
121077d89b08766c878a2594b15d203e513acf952340wwang	} else {
121177d89b08766c878a2594b15d203e513acf952340wwang		msg_cnt = chip->msg_idx;
121277d89b08766c878a2594b15d203e513acf952340wwang	}
121377d89b08766c878a2594b15d203e513acf952340wwang	*(ptr++) = (u8)(msg_cnt >> 24);
121477d89b08766c878a2594b15d203e513acf952340wwang	*(ptr++) = (u8)(msg_cnt >> 16);
121577d89b08766c878a2594b15d203e513acf952340wwang	*(ptr++) = (u8)(msg_cnt >> 8);
121677d89b08766c878a2594b15d203e513acf952340wwang	*(ptr++) = (u8)msg_cnt;
121777d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("Trace message count is %d\n", msg_cnt);
121877d89b08766c878a2594b15d203e513acf952340wwang
121977d89b08766c878a2594b15d203e513acf952340wwang	for (i = 1; i <= msg_cnt; i++) {
122077d89b08766c878a2594b15d203e513acf952340wwang		int j, idx;
122177d89b08766c878a2594b15d203e513acf952340wwang
122277d89b08766c878a2594b15d203e513acf952340wwang		idx = chip->msg_idx - i;
122377d89b08766c878a2594b15d203e513acf952340wwang		if (idx < 0)
122477d89b08766c878a2594b15d203e513acf952340wwang			idx += TRACE_ITEM_CNT;
122577d89b08766c878a2594b15d203e513acf952340wwang
122677d89b08766c878a2594b15d203e513acf952340wwang		*(ptr++) = (u8)(chip->trace_msg[idx].line >> 8);
122777d89b08766c878a2594b15d203e513acf952340wwang		*(ptr++) = (u8)(chip->trace_msg[idx].line);
122877d89b08766c878a2594b15d203e513acf952340wwang		for (j = 0; j < MSG_FUNC_LEN; j++) {
122977d89b08766c878a2594b15d203e513acf952340wwang			*(ptr++) = chip->trace_msg[idx].func[j];
123077d89b08766c878a2594b15d203e513acf952340wwang		}
123177d89b08766c878a2594b15d203e513acf952340wwang		for (j = 0; j < MSG_FILE_LEN; j++) {
123277d89b08766c878a2594b15d203e513acf952340wwang			*(ptr++) = chip->trace_msg[idx].file[j];
123377d89b08766c878a2594b15d203e513acf952340wwang		}
123477d89b08766c878a2594b15d203e513acf952340wwang		for (j = 0; j < TIME_VAL_LEN; j++) {
123577d89b08766c878a2594b15d203e513acf952340wwang			*(ptr++) = chip->trace_msg[idx].timeval_buf[j];
123677d89b08766c878a2594b15d203e513acf952340wwang		}
123777d89b08766c878a2594b15d203e513acf952340wwang	}
123877d89b08766c878a2594b15d203e513acf952340wwang
123977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
124077d89b08766c878a2594b15d203e513acf952340wwang	vfree(buf);
124177d89b08766c878a2594b15d203e513acf952340wwang
124277d89b08766c878a2594b15d203e513acf952340wwang	if (clear) {
124377d89b08766c878a2594b15d203e513acf952340wwang		chip->msg_idx = 0;
124477d89b08766c878a2594b15d203e513acf952340wwang		for (i = 0; i < TRACE_ITEM_CNT; i++)
124577d89b08766c878a2594b15d203e513acf952340wwang			chip->trace_msg[i].valid = 0;
124677d89b08766c878a2594b15d203e513acf952340wwang	}
124777d89b08766c878a2594b15d203e513acf952340wwang
124877d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
124977d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
125077d89b08766c878a2594b15d203e513acf952340wwang}
125177d89b08766c878a2594b15d203e513acf952340wwang#endif
125277d89b08766c878a2594b15d203e513acf952340wwang
125377d89b08766c878a2594b15d203e513acf952340wwangstatic int read_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
125477d89b08766c878a2594b15d203e513acf952340wwang{
125577d89b08766c878a2594b15d203e513acf952340wwang	u8 addr, buf[4];
125677d89b08766c878a2594b15d203e513acf952340wwang	u32 val;
125777d89b08766c878a2594b15d203e513acf952340wwang	unsigned int len;
125877d89b08766c878a2594b15d203e513acf952340wwang
125977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
126077d89b08766c878a2594b15d203e513acf952340wwang
126177d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
126277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
126377d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
126477d89b08766c878a2594b15d203e513acf952340wwang	}
126577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
126677d89b08766c878a2594b15d203e513acf952340wwang
126777d89b08766c878a2594b15d203e513acf952340wwang	addr = srb->cmnd[4];
126877d89b08766c878a2594b15d203e513acf952340wwang
126977d89b08766c878a2594b15d203e513acf952340wwang	val = rtsx_readl(chip, addr);
127077d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("Host register (0x%x): 0x%x\n", addr, val);
127177d89b08766c878a2594b15d203e513acf952340wwang
127277d89b08766c878a2594b15d203e513acf952340wwang	buf[0] = (u8)(val >> 24);
127377d89b08766c878a2594b15d203e513acf952340wwang	buf[1] = (u8)(val >> 16);
127477d89b08766c878a2594b15d203e513acf952340wwang	buf[2] = (u8)(val >> 8);
127577d89b08766c878a2594b15d203e513acf952340wwang	buf[3] = (u8)val;
127677d89b08766c878a2594b15d203e513acf952340wwang
127777d89b08766c878a2594b15d203e513acf952340wwang	len = min(scsi_bufflen(srb), (unsigned int)4);
127877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, len, srb);
127977d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - len);
128077d89b08766c878a2594b15d203e513acf952340wwang
128177d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
128277d89b08766c878a2594b15d203e513acf952340wwang}
128377d89b08766c878a2594b15d203e513acf952340wwang
128477d89b08766c878a2594b15d203e513acf952340wwangstatic int write_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
128577d89b08766c878a2594b15d203e513acf952340wwang{
128677d89b08766c878a2594b15d203e513acf952340wwang	u8 addr, buf[4];
128777d89b08766c878a2594b15d203e513acf952340wwang	u32 val;
128877d89b08766c878a2594b15d203e513acf952340wwang	unsigned int len;
128977d89b08766c878a2594b15d203e513acf952340wwang
129077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
129177d89b08766c878a2594b15d203e513acf952340wwang
129277d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
129377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
129477d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
129577d89b08766c878a2594b15d203e513acf952340wwang	}
129677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
129777d89b08766c878a2594b15d203e513acf952340wwang
129877d89b08766c878a2594b15d203e513acf952340wwang	addr = srb->cmnd[4];
129977d89b08766c878a2594b15d203e513acf952340wwang
130077d89b08766c878a2594b15d203e513acf952340wwang	len = min(scsi_bufflen(srb), (unsigned int)4);
130177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_get_xfer_buf(buf, len, srb);
130277d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - len);
130377d89b08766c878a2594b15d203e513acf952340wwang
130477d89b08766c878a2594b15d203e513acf952340wwang	val = ((u32)buf[0] << 24) | ((u32)buf[1] << 16) | ((u32)buf[2] << 8) | buf[3];
130577d89b08766c878a2594b15d203e513acf952340wwang
130677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_writel(chip, addr, val);
130777d89b08766c878a2594b15d203e513acf952340wwang
130877d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
130977d89b08766c878a2594b15d203e513acf952340wwang}
131077d89b08766c878a2594b15d203e513acf952340wwang
131177d89b08766c878a2594b15d203e513acf952340wwangstatic int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
131277d89b08766c878a2594b15d203e513acf952340wwang{
131377d89b08766c878a2594b15d203e513acf952340wwang	unsigned lun = SCSI_LUN(srb);
131477d89b08766c878a2594b15d203e513acf952340wwang
131577d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[3] == 1) {
131677d89b08766c878a2594b15d203e513acf952340wwang		/* Variable Clock */
131777d89b08766c878a2594b15d203e513acf952340wwang		struct xd_info *xd_card = &(chip->xd_card);
131877d89b08766c878a2594b15d203e513acf952340wwang		struct sd_info *sd_card = &(chip->sd_card);
131977d89b08766c878a2594b15d203e513acf952340wwang		struct ms_info *ms_card = &(chip->ms_card);
132077d89b08766c878a2594b15d203e513acf952340wwang
132177d89b08766c878a2594b15d203e513acf952340wwang		switch (srb->cmnd[4]) {
132277d89b08766c878a2594b15d203e513acf952340wwang		case XD_CARD:
132377d89b08766c878a2594b15d203e513acf952340wwang			xd_card->xd_clock = srb->cmnd[5];
132477d89b08766c878a2594b15d203e513acf952340wwang			break;
132577d89b08766c878a2594b15d203e513acf952340wwang
132677d89b08766c878a2594b15d203e513acf952340wwang		case SD_CARD:
132777d89b08766c878a2594b15d203e513acf952340wwang			sd_card->sd_clock = srb->cmnd[5];
132877d89b08766c878a2594b15d203e513acf952340wwang			break;
132977d89b08766c878a2594b15d203e513acf952340wwang
133077d89b08766c878a2594b15d203e513acf952340wwang		case MS_CARD:
133177d89b08766c878a2594b15d203e513acf952340wwang			ms_card->ms_clock = srb->cmnd[5];
133277d89b08766c878a2594b15d203e513acf952340wwang			break;
133377d89b08766c878a2594b15d203e513acf952340wwang
133477d89b08766c878a2594b15d203e513acf952340wwang		default:
133577d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
133677d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
133777d89b08766c878a2594b15d203e513acf952340wwang		}
133877d89b08766c878a2594b15d203e513acf952340wwang	} else if (srb->cmnd[3] == 2) {
133977d89b08766c878a2594b15d203e513acf952340wwang		if (srb->cmnd[4]) {
134077d89b08766c878a2594b15d203e513acf952340wwang			chip->blink_led = 1;
134177d89b08766c878a2594b15d203e513acf952340wwang		} else {
134277d89b08766c878a2594b15d203e513acf952340wwang			int retval;
134377d89b08766c878a2594b15d203e513acf952340wwang
134477d89b08766c878a2594b15d203e513acf952340wwang			chip->blink_led = 0;
134577d89b08766c878a2594b15d203e513acf952340wwang
134677d89b08766c878a2594b15d203e513acf952340wwang			rtsx_disable_aspm(chip);
134777d89b08766c878a2594b15d203e513acf952340wwang
134877d89b08766c878a2594b15d203e513acf952340wwang			if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
134977d89b08766c878a2594b15d203e513acf952340wwang				rtsx_exit_ss(chip);
135077d89b08766c878a2594b15d203e513acf952340wwang				wait_timeout(100);
135177d89b08766c878a2594b15d203e513acf952340wwang			}
135277d89b08766c878a2594b15d203e513acf952340wwang			rtsx_set_stat(chip, RTSX_STAT_RUN);
135377d89b08766c878a2594b15d203e513acf952340wwang
135477d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_force_power_on(chip, SSC_PDCTL);
135577d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
135677d89b08766c878a2594b15d203e513acf952340wwang				set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
135777d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
135877d89b08766c878a2594b15d203e513acf952340wwang			}
135977d89b08766c878a2594b15d203e513acf952340wwang
136077d89b08766c878a2594b15d203e513acf952340wwang			turn_off_led(chip, LED_GPIO);
136177d89b08766c878a2594b15d203e513acf952340wwang		}
136277d89b08766c878a2594b15d203e513acf952340wwang	} else {
136377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
136477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
136577d89b08766c878a2594b15d203e513acf952340wwang	}
136677d89b08766c878a2594b15d203e513acf952340wwang
136777d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
136877d89b08766c878a2594b15d203e513acf952340wwang}
136977d89b08766c878a2594b15d203e513acf952340wwang
137077d89b08766c878a2594b15d203e513acf952340wwangstatic int get_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
137177d89b08766c878a2594b15d203e513acf952340wwang{
137277d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
137377d89b08766c878a2594b15d203e513acf952340wwang
137477d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[3] == 1) {
137577d89b08766c878a2594b15d203e513acf952340wwang		struct xd_info *xd_card = &(chip->xd_card);
137677d89b08766c878a2594b15d203e513acf952340wwang		struct sd_info *sd_card = &(chip->sd_card);
137777d89b08766c878a2594b15d203e513acf952340wwang		struct ms_info *ms_card = &(chip->ms_card);
137877d89b08766c878a2594b15d203e513acf952340wwang		u8 tmp;
137977d89b08766c878a2594b15d203e513acf952340wwang
138077d89b08766c878a2594b15d203e513acf952340wwang		switch (srb->cmnd[4]) {
138177d89b08766c878a2594b15d203e513acf952340wwang		case XD_CARD:
138277d89b08766c878a2594b15d203e513acf952340wwang			tmp = (u8)(xd_card->xd_clock);
138377d89b08766c878a2594b15d203e513acf952340wwang			break;
138477d89b08766c878a2594b15d203e513acf952340wwang
138577d89b08766c878a2594b15d203e513acf952340wwang		case SD_CARD:
138677d89b08766c878a2594b15d203e513acf952340wwang			tmp = (u8)(sd_card->sd_clock);
138777d89b08766c878a2594b15d203e513acf952340wwang			break;
138877d89b08766c878a2594b15d203e513acf952340wwang
138977d89b08766c878a2594b15d203e513acf952340wwang		case MS_CARD:
139077d89b08766c878a2594b15d203e513acf952340wwang			tmp = (u8)(ms_card->ms_clock);
139177d89b08766c878a2594b15d203e513acf952340wwang			break;
139277d89b08766c878a2594b15d203e513acf952340wwang
139377d89b08766c878a2594b15d203e513acf952340wwang		default:
139477d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
139577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
139677d89b08766c878a2594b15d203e513acf952340wwang		}
139777d89b08766c878a2594b15d203e513acf952340wwang
139877d89b08766c878a2594b15d203e513acf952340wwang		rtsx_stor_set_xfer_buf(&tmp, 1, srb);
139977d89b08766c878a2594b15d203e513acf952340wwang	} else if (srb->cmnd[3] == 2) {
140077d89b08766c878a2594b15d203e513acf952340wwang		u8 tmp = chip->blink_led;
140177d89b08766c878a2594b15d203e513acf952340wwang		rtsx_stor_set_xfer_buf(&tmp, 1, srb);
140277d89b08766c878a2594b15d203e513acf952340wwang	} else {
140377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
140477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
140577d89b08766c878a2594b15d203e513acf952340wwang	}
140677d89b08766c878a2594b15d203e513acf952340wwang
140777d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
140877d89b08766c878a2594b15d203e513acf952340wwang}
140977d89b08766c878a2594b15d203e513acf952340wwang
141077d89b08766c878a2594b15d203e513acf952340wwangstatic int dma_access_ring_buffer(struct scsi_cmnd *srb, struct rtsx_chip *chip)
141177d89b08766c878a2594b15d203e513acf952340wwang{
141277d89b08766c878a2594b15d203e513acf952340wwang	int retval;
141377d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
141477d89b08766c878a2594b15d203e513acf952340wwang	u16 len;
141577d89b08766c878a2594b15d203e513acf952340wwang
141677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
141777d89b08766c878a2594b15d203e513acf952340wwang
141877d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
141977d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
142077d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
142177d89b08766c878a2594b15d203e513acf952340wwang	}
142277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
142377d89b08766c878a2594b15d203e513acf952340wwang
142477d89b08766c878a2594b15d203e513acf952340wwang	len = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
142577d89b08766c878a2594b15d203e513acf952340wwang	len = min(len, (u16)scsi_bufflen(srb));
142677d89b08766c878a2594b15d203e513acf952340wwang
142777d89b08766c878a2594b15d203e513acf952340wwang	if (srb->sc_data_direction == DMA_FROM_DEVICE) {
142877d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("Read from device\n");
142977d89b08766c878a2594b15d203e513acf952340wwang	} else {
143077d89b08766c878a2594b15d203e513acf952340wwang		RTSX_DEBUGP("Write to device\n");
143177d89b08766c878a2594b15d203e513acf952340wwang	}
143277d89b08766c878a2594b15d203e513acf952340wwang
143377d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_transfer_data(chip, 0, scsi_sglist(srb), len,
143477d89b08766c878a2594b15d203e513acf952340wwang			scsi_sg_count(srb), srb->sc_data_direction, 1000);
143577d89b08766c878a2594b15d203e513acf952340wwang	if (retval < 0) {
143677d89b08766c878a2594b15d203e513acf952340wwang		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
143777d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
143877d89b08766c878a2594b15d203e513acf952340wwang		} else {
143977d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
144077d89b08766c878a2594b15d203e513acf952340wwang		}
144177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
144277d89b08766c878a2594b15d203e513acf952340wwang	}
144377d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
144477d89b08766c878a2594b15d203e513acf952340wwang
144577d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
144677d89b08766c878a2594b15d203e513acf952340wwang}
144777d89b08766c878a2594b15d203e513acf952340wwang
144877d89b08766c878a2594b15d203e513acf952340wwangstatic int get_dev_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
144977d89b08766c878a2594b15d203e513acf952340wwang{
145077d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
145177d89b08766c878a2594b15d203e513acf952340wwang	struct ms_info *ms_card = &(chip->ms_card);
145277d89b08766c878a2594b15d203e513acf952340wwang	int buf_len;
145377d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
145477d89b08766c878a2594b15d203e513acf952340wwang	u8 card = get_lun_card(chip, lun);
145577d89b08766c878a2594b15d203e513acf952340wwang	u8 status[32];
145677d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_OCP
145777d89b08766c878a2594b15d203e513acf952340wwang	u8 oc_now_mask = 0, oc_ever_mask = 0;
145877d89b08766c878a2594b15d203e513acf952340wwang#endif
145977d89b08766c878a2594b15d203e513acf952340wwang
146077d89b08766c878a2594b15d203e513acf952340wwang	memset(status, 0, 32);
146177d89b08766c878a2594b15d203e513acf952340wwang
146277d89b08766c878a2594b15d203e513acf952340wwang	status[0] = (u8)(chip->product_id);
146377d89b08766c878a2594b15d203e513acf952340wwang	status[1] = chip->ic_version;
146477d89b08766c878a2594b15d203e513acf952340wwang
146577d89b08766c878a2594b15d203e513acf952340wwang	if (chip->auto_delink_en) {
146677d89b08766c878a2594b15d203e513acf952340wwang		status[2] = 0x10;
146777d89b08766c878a2594b15d203e513acf952340wwang	} else {
146877d89b08766c878a2594b15d203e513acf952340wwang		status[2] = 0x00;
146977d89b08766c878a2594b15d203e513acf952340wwang	}
147077d89b08766c878a2594b15d203e513acf952340wwang
147177d89b08766c878a2594b15d203e513acf952340wwang	status[3] = 20;
147277d89b08766c878a2594b15d203e513acf952340wwang	status[4] = 10;
147377d89b08766c878a2594b15d203e513acf952340wwang	status[5] = 05;
147477d89b08766c878a2594b15d203e513acf952340wwang	status[6] = 21;
147577d89b08766c878a2594b15d203e513acf952340wwang
147677d89b08766c878a2594b15d203e513acf952340wwang	if (chip->card_wp) {
147777d89b08766c878a2594b15d203e513acf952340wwang		status[7] = 0x20;
147877d89b08766c878a2594b15d203e513acf952340wwang	} else {
147977d89b08766c878a2594b15d203e513acf952340wwang		status[7] = 0x00;
148077d89b08766c878a2594b15d203e513acf952340wwang	}
148177d89b08766c878a2594b15d203e513acf952340wwang
148277d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_OCP
148377d89b08766c878a2594b15d203e513acf952340wwang	status[8] = 0;
148477d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && (chip->lun2card[lun] == MS_CARD)) {
148577d89b08766c878a2594b15d203e513acf952340wwang		oc_now_mask = MS_OC_NOW;
148677d89b08766c878a2594b15d203e513acf952340wwang		oc_ever_mask = MS_OC_EVER;
148777d89b08766c878a2594b15d203e513acf952340wwang	} else {
148877d89b08766c878a2594b15d203e513acf952340wwang		oc_now_mask = SD_OC_NOW;
148977d89b08766c878a2594b15d203e513acf952340wwang		oc_ever_mask = SD_OC_EVER;
149077d89b08766c878a2594b15d203e513acf952340wwang	}
149177d89b08766c878a2594b15d203e513acf952340wwang
149277d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ocp_stat & oc_now_mask) {
149377d89b08766c878a2594b15d203e513acf952340wwang		status[8] |= 0x02;
149477d89b08766c878a2594b15d203e513acf952340wwang	}
149577d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ocp_stat & oc_ever_mask) {
149677d89b08766c878a2594b15d203e513acf952340wwang		status[8] |= 0x01;
149777d89b08766c878a2594b15d203e513acf952340wwang	}
149877d89b08766c878a2594b15d203e513acf952340wwang#endif
149977d89b08766c878a2594b15d203e513acf952340wwang
150077d89b08766c878a2594b15d203e513acf952340wwang	if (card == SD_CARD) {
150177d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_SD(sd_card)) {
150277d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_SD_HCXC(sd_card)) {
150377d89b08766c878a2594b15d203e513acf952340wwang				if (sd_card->capacity > 0x4000000) {
150477d89b08766c878a2594b15d203e513acf952340wwang					status[0x0E] = 0x02;
150577d89b08766c878a2594b15d203e513acf952340wwang				} else {
150677d89b08766c878a2594b15d203e513acf952340wwang					status[0x0E] = 0x01;
150777d89b08766c878a2594b15d203e513acf952340wwang				}
150877d89b08766c878a2594b15d203e513acf952340wwang			} else {
150977d89b08766c878a2594b15d203e513acf952340wwang				status[0x0E] = 0x00;
151077d89b08766c878a2594b15d203e513acf952340wwang			}
151177d89b08766c878a2594b15d203e513acf952340wwang
151277d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_SD_SDR104(sd_card)) {
151377d89b08766c878a2594b15d203e513acf952340wwang				status[0x0F] = 0x03;
151477d89b08766c878a2594b15d203e513acf952340wwang			} else if (CHK_SD_DDR50(sd_card)) {
151577d89b08766c878a2594b15d203e513acf952340wwang				status[0x0F] = 0x04;
151677d89b08766c878a2594b15d203e513acf952340wwang			} else if (CHK_SD_SDR50(sd_card)) {
151777d89b08766c878a2594b15d203e513acf952340wwang				status[0x0F] = 0x02;
151877d89b08766c878a2594b15d203e513acf952340wwang			} else if (CHK_SD_HS(sd_card)) {
151977d89b08766c878a2594b15d203e513acf952340wwang				status[0x0F] = 0x01;
152077d89b08766c878a2594b15d203e513acf952340wwang			} else {
152177d89b08766c878a2594b15d203e513acf952340wwang				status[0x0F] = 0x00;
152277d89b08766c878a2594b15d203e513acf952340wwang			}
152377d89b08766c878a2594b15d203e513acf952340wwang		} else {
152477d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_MMC_SECTOR_MODE(sd_card)) {
152577d89b08766c878a2594b15d203e513acf952340wwang				status[0x0E] = 0x01;
152677d89b08766c878a2594b15d203e513acf952340wwang			} else {
152777d89b08766c878a2594b15d203e513acf952340wwang				status[0x0E] = 0x00;
152877d89b08766c878a2594b15d203e513acf952340wwang			}
152977d89b08766c878a2594b15d203e513acf952340wwang
153077d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_MMC_DDR52(sd_card)) {
153177d89b08766c878a2594b15d203e513acf952340wwang				status[0x0F] = 0x03;
153277d89b08766c878a2594b15d203e513acf952340wwang			} else if (CHK_MMC_52M(sd_card)) {
153377d89b08766c878a2594b15d203e513acf952340wwang				status[0x0F] = 0x02;
153477d89b08766c878a2594b15d203e513acf952340wwang			} else if (CHK_MMC_26M(sd_card)) {
153577d89b08766c878a2594b15d203e513acf952340wwang				status[0x0F] = 0x01;
153677d89b08766c878a2594b15d203e513acf952340wwang			} else {
153777d89b08766c878a2594b15d203e513acf952340wwang				status[0x0F] = 0x00;
153877d89b08766c878a2594b15d203e513acf952340wwang			}
153977d89b08766c878a2594b15d203e513acf952340wwang		}
154077d89b08766c878a2594b15d203e513acf952340wwang	} else if (card == MS_CARD) {
154177d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_MSPRO(ms_card)) {
154277d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_MSXC(ms_card)) {
154377d89b08766c878a2594b15d203e513acf952340wwang				status[0x0E] = 0x01;
154477d89b08766c878a2594b15d203e513acf952340wwang			} else {
154577d89b08766c878a2594b15d203e513acf952340wwang				status[0x0E] = 0x00;
154677d89b08766c878a2594b15d203e513acf952340wwang			}
154777d89b08766c878a2594b15d203e513acf952340wwang
154877d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_HG8BIT(ms_card)) {
154977d89b08766c878a2594b15d203e513acf952340wwang				status[0x0F] = 0x01;
155077d89b08766c878a2594b15d203e513acf952340wwang			} else {
155177d89b08766c878a2594b15d203e513acf952340wwang				status[0x0F] = 0x00;
155277d89b08766c878a2594b15d203e513acf952340wwang			}
155377d89b08766c878a2594b15d203e513acf952340wwang		}
155477d89b08766c878a2594b15d203e513acf952340wwang	}
155577d89b08766c878a2594b15d203e513acf952340wwang
155677d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
155777d89b08766c878a2594b15d203e513acf952340wwang	if (card == SD_CARD) {
155877d89b08766c878a2594b15d203e513acf952340wwang		status[0x17] = 0x80;
155977d89b08766c878a2594b15d203e513acf952340wwang		if (sd_card->sd_erase_status)
156077d89b08766c878a2594b15d203e513acf952340wwang			status[0x17] |= 0x01;
156177d89b08766c878a2594b15d203e513acf952340wwang		if (sd_card->sd_lock_status & SD_LOCKED) {
156277d89b08766c878a2594b15d203e513acf952340wwang			status[0x17] |= 0x02;
156377d89b08766c878a2594b15d203e513acf952340wwang			status[0x07] |= 0x40;
156477d89b08766c878a2594b15d203e513acf952340wwang		}
156577d89b08766c878a2594b15d203e513acf952340wwang		if (sd_card->sd_lock_status & SD_PWD_EXIST)
156677d89b08766c878a2594b15d203e513acf952340wwang			status[0x17] |= 0x04;
156777d89b08766c878a2594b15d203e513acf952340wwang	} else {
156877d89b08766c878a2594b15d203e513acf952340wwang		status[0x17] = 0x00;
156977d89b08766c878a2594b15d203e513acf952340wwang	}
157077d89b08766c878a2594b15d203e513acf952340wwang
157177d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("status[0x17] = 0x%x\n", status[0x17]);
157277d89b08766c878a2594b15d203e513acf952340wwang#endif
157377d89b08766c878a2594b15d203e513acf952340wwang
157477d89b08766c878a2594b15d203e513acf952340wwang	status[0x18] = 0x8A;
157577d89b08766c878a2594b15d203e513acf952340wwang	status[0x1A] = 0x28;
157677d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
157777d89b08766c878a2594b15d203e513acf952340wwang	status[0x1F] = 0x01;
157877d89b08766c878a2594b15d203e513acf952340wwang#endif
157977d89b08766c878a2594b15d203e513acf952340wwang
158077d89b08766c878a2594b15d203e513acf952340wwang	buf_len = min(scsi_bufflen(srb), (unsigned int)sizeof(status));
158177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(status, buf_len, srb);
158277d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
158377d89b08766c878a2594b15d203e513acf952340wwang
158477d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
158577d89b08766c878a2594b15d203e513acf952340wwang}
158677d89b08766c878a2594b15d203e513acf952340wwang
158777d89b08766c878a2594b15d203e513acf952340wwangstatic int set_chip_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
158877d89b08766c878a2594b15d203e513acf952340wwang{
158977d89b08766c878a2594b15d203e513acf952340wwang	int phy_debug_mode;
159077d89b08766c878a2594b15d203e513acf952340wwang	int retval;
159177d89b08766c878a2594b15d203e513acf952340wwang	u16 reg;
159277d89b08766c878a2594b15d203e513acf952340wwang
159377d89b08766c878a2594b15d203e513acf952340wwang	if (!CHECK_PID(chip, 0x5208)) {
159477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
159577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
159677d89b08766c878a2594b15d203e513acf952340wwang	}
159777d89b08766c878a2594b15d203e513acf952340wwang
159877d89b08766c878a2594b15d203e513acf952340wwang	phy_debug_mode = (int)(srb->cmnd[3]);
159977d89b08766c878a2594b15d203e513acf952340wwang
160077d89b08766c878a2594b15d203e513acf952340wwang	if (phy_debug_mode) {
160177d89b08766c878a2594b15d203e513acf952340wwang		chip->phy_debug_mode = 1;
160277d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0);
160377d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
160477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
160577d89b08766c878a2594b15d203e513acf952340wwang		}
160677d89b08766c878a2594b15d203e513acf952340wwang		rtsx_disable_bus_int(chip);
160777d89b08766c878a2594b15d203e513acf952340wwang
160877d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_read_phy_register(chip, 0x1C, &reg);
160977d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
161077d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
161177d89b08766c878a2594b15d203e513acf952340wwang		}
161277d89b08766c878a2594b15d203e513acf952340wwang		reg |= 0x0001;
161377d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_phy_register(chip, 0x1C, reg);
161477d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
161577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
161677d89b08766c878a2594b15d203e513acf952340wwang		}
161777d89b08766c878a2594b15d203e513acf952340wwang	} else {
161877d89b08766c878a2594b15d203e513acf952340wwang		chip->phy_debug_mode = 0;
161977d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0x77);
162077d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
162177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
162277d89b08766c878a2594b15d203e513acf952340wwang		}
162377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_enable_bus_int(chip);
162477d89b08766c878a2594b15d203e513acf952340wwang
162577d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_read_phy_register(chip, 0x1C, &reg);
162677d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
162777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
162877d89b08766c878a2594b15d203e513acf952340wwang		}
162977d89b08766c878a2594b15d203e513acf952340wwang		reg &= 0xFFFE;
163077d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_phy_register(chip, 0x1C, reg);
163177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
163277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
163377d89b08766c878a2594b15d203e513acf952340wwang		}
163477d89b08766c878a2594b15d203e513acf952340wwang	}
163577d89b08766c878a2594b15d203e513acf952340wwang
163677d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
163777d89b08766c878a2594b15d203e513acf952340wwang}
163877d89b08766c878a2594b15d203e513acf952340wwang
163977d89b08766c878a2594b15d203e513acf952340wwangstatic int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip)
164077d89b08766c878a2594b15d203e513acf952340wwang{
164177d89b08766c878a2594b15d203e513acf952340wwang	int retval =  STATUS_SUCCESS;
164277d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
164377d89b08766c878a2594b15d203e513acf952340wwang	u8 cmd_type, mask, value, idx;
164477d89b08766c878a2594b15d203e513acf952340wwang	u16 addr;
164577d89b08766c878a2594b15d203e513acf952340wwang
164677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
164777d89b08766c878a2594b15d203e513acf952340wwang
164877d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
164977d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
165077d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
165177d89b08766c878a2594b15d203e513acf952340wwang	}
165277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
165377d89b08766c878a2594b15d203e513acf952340wwang
165477d89b08766c878a2594b15d203e513acf952340wwang	switch (srb->cmnd[3]) {
165577d89b08766c878a2594b15d203e513acf952340wwang	case INIT_BATCHCMD:
165677d89b08766c878a2594b15d203e513acf952340wwang		rtsx_init_cmd(chip);
165777d89b08766c878a2594b15d203e513acf952340wwang		break;
165877d89b08766c878a2594b15d203e513acf952340wwang
165977d89b08766c878a2594b15d203e513acf952340wwang	case ADD_BATCHCMD:
166077d89b08766c878a2594b15d203e513acf952340wwang		cmd_type = srb->cmnd[4];
166177d89b08766c878a2594b15d203e513acf952340wwang		if (cmd_type > 2) {
166277d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
166377d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
166477d89b08766c878a2594b15d203e513acf952340wwang		}
166577d89b08766c878a2594b15d203e513acf952340wwang		addr = (srb->cmnd[5] << 8) | srb->cmnd[6];
166677d89b08766c878a2594b15d203e513acf952340wwang		mask = srb->cmnd[7];
166777d89b08766c878a2594b15d203e513acf952340wwang		value = srb->cmnd[8];
166877d89b08766c878a2594b15d203e513acf952340wwang		rtsx_add_cmd(chip, cmd_type, addr, mask, value);
166977d89b08766c878a2594b15d203e513acf952340wwang		break;
167077d89b08766c878a2594b15d203e513acf952340wwang
167177d89b08766c878a2594b15d203e513acf952340wwang	case SEND_BATCHCMD:
167277d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_send_cmd(chip, 0, 1000);
167377d89b08766c878a2594b15d203e513acf952340wwang		break;
167477d89b08766c878a2594b15d203e513acf952340wwang
167577d89b08766c878a2594b15d203e513acf952340wwang	case GET_BATCHRSP:
167677d89b08766c878a2594b15d203e513acf952340wwang		idx = srb->cmnd[4];
167777d89b08766c878a2594b15d203e513acf952340wwang		value = *(rtsx_get_cmd_data(chip) + idx);
167877d89b08766c878a2594b15d203e513acf952340wwang		if (scsi_bufflen(srb) < 1) {
167977d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
168077d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
168177d89b08766c878a2594b15d203e513acf952340wwang		}
168277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_stor_set_xfer_buf(&value, 1, srb);
168377d89b08766c878a2594b15d203e513acf952340wwang		scsi_set_resid(srb, 0);
168477d89b08766c878a2594b15d203e513acf952340wwang		break;
168577d89b08766c878a2594b15d203e513acf952340wwang
168677d89b08766c878a2594b15d203e513acf952340wwang	default:
168777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
168877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
168977d89b08766c878a2594b15d203e513acf952340wwang	}
169077d89b08766c878a2594b15d203e513acf952340wwang
169177d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
169277d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
169377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
169477d89b08766c878a2594b15d203e513acf952340wwang	}
169577d89b08766c878a2594b15d203e513acf952340wwang
169677d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
169777d89b08766c878a2594b15d203e513acf952340wwang}
169877d89b08766c878a2594b15d203e513acf952340wwang
169977d89b08766c878a2594b15d203e513acf952340wwangstatic int suit_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
170077d89b08766c878a2594b15d203e513acf952340wwang{
170177d89b08766c878a2594b15d203e513acf952340wwang	int result;
170277d89b08766c878a2594b15d203e513acf952340wwang
170377d89b08766c878a2594b15d203e513acf952340wwang	switch (srb->cmnd[3]) {
170477d89b08766c878a2594b15d203e513acf952340wwang	case INIT_BATCHCMD:
170577d89b08766c878a2594b15d203e513acf952340wwang	case ADD_BATCHCMD:
170677d89b08766c878a2594b15d203e513acf952340wwang	case SEND_BATCHCMD:
170777d89b08766c878a2594b15d203e513acf952340wwang	case GET_BATCHRSP:
170877d89b08766c878a2594b15d203e513acf952340wwang		result = rw_mem_cmd_buf(srb, chip);
170977d89b08766c878a2594b15d203e513acf952340wwang		break;
171077d89b08766c878a2594b15d203e513acf952340wwang	default:
171177d89b08766c878a2594b15d203e513acf952340wwang		result = TRANSPORT_ERROR;
171277d89b08766c878a2594b15d203e513acf952340wwang	}
171377d89b08766c878a2594b15d203e513acf952340wwang
171477d89b08766c878a2594b15d203e513acf952340wwang	return result;
171577d89b08766c878a2594b15d203e513acf952340wwang}
171677d89b08766c878a2594b15d203e513acf952340wwang
171777d89b08766c878a2594b15d203e513acf952340wwangstatic int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
171877d89b08766c878a2594b15d203e513acf952340wwang{
171977d89b08766c878a2594b15d203e513acf952340wwang	unsigned short addr, len, i;
172077d89b08766c878a2594b15d203e513acf952340wwang	int retval;
172177d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
172277d89b08766c878a2594b15d203e513acf952340wwang	u16 val;
172377d89b08766c878a2594b15d203e513acf952340wwang
172477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
172577d89b08766c878a2594b15d203e513acf952340wwang
172677d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
172777d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
172877d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
172977d89b08766c878a2594b15d203e513acf952340wwang	}
173077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
173177d89b08766c878a2594b15d203e513acf952340wwang
173277d89b08766c878a2594b15d203e513acf952340wwang	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
173377d89b08766c878a2594b15d203e513acf952340wwang	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
173477d89b08766c878a2594b15d203e513acf952340wwang
173577d89b08766c878a2594b15d203e513acf952340wwang	if (len % 2)
173677d89b08766c878a2594b15d203e513acf952340wwang		len -= len % 2;
173777d89b08766c878a2594b15d203e513acf952340wwang
173877d89b08766c878a2594b15d203e513acf952340wwang	if (len) {
173977d89b08766c878a2594b15d203e513acf952340wwang		buf = (u8 *)vmalloc(len);
174077d89b08766c878a2594b15d203e513acf952340wwang		if (!buf) {
174177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_ERROR);
174277d89b08766c878a2594b15d203e513acf952340wwang		}
174377d89b08766c878a2594b15d203e513acf952340wwang
174477d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_force_power_on(chip, SSC_PDCTL);
174577d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
174677d89b08766c878a2594b15d203e513acf952340wwang			vfree(buf);
174777d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
174877d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
174977d89b08766c878a2594b15d203e513acf952340wwang		}
175077d89b08766c878a2594b15d203e513acf952340wwang
175177d89b08766c878a2594b15d203e513acf952340wwang		for (i = 0; i < len / 2; i++) {
175277d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_read_phy_register(chip, addr + i, &val);
175377d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
175477d89b08766c878a2594b15d203e513acf952340wwang				vfree(buf);
175577d89b08766c878a2594b15d203e513acf952340wwang				set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
175677d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
175777d89b08766c878a2594b15d203e513acf952340wwang			}
175877d89b08766c878a2594b15d203e513acf952340wwang
175977d89b08766c878a2594b15d203e513acf952340wwang			buf[2*i] = (u8)(val >> 8);
176077d89b08766c878a2594b15d203e513acf952340wwang			buf[2*i+1] = (u8)val;
176177d89b08766c878a2594b15d203e513acf952340wwang		}
176277d89b08766c878a2594b15d203e513acf952340wwang
176377d89b08766c878a2594b15d203e513acf952340wwang		len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
176477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_stor_set_xfer_buf(buf, len, srb);
176577d89b08766c878a2594b15d203e513acf952340wwang		scsi_set_resid(srb, scsi_bufflen(srb) - len);
176677d89b08766c878a2594b15d203e513acf952340wwang
176777d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
176877d89b08766c878a2594b15d203e513acf952340wwang	}
176977d89b08766c878a2594b15d203e513acf952340wwang
177077d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
177177d89b08766c878a2594b15d203e513acf952340wwang}
177277d89b08766c878a2594b15d203e513acf952340wwang
177377d89b08766c878a2594b15d203e513acf952340wwangstatic int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
177477d89b08766c878a2594b15d203e513acf952340wwang{
177577d89b08766c878a2594b15d203e513acf952340wwang	unsigned short addr, len, i;
177677d89b08766c878a2594b15d203e513acf952340wwang	int retval;
177777d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
177877d89b08766c878a2594b15d203e513acf952340wwang	u16 val;
177977d89b08766c878a2594b15d203e513acf952340wwang
178077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
178177d89b08766c878a2594b15d203e513acf952340wwang
178277d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
178377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
178477d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
178577d89b08766c878a2594b15d203e513acf952340wwang	}
178677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
178777d89b08766c878a2594b15d203e513acf952340wwang
178877d89b08766c878a2594b15d203e513acf952340wwang	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
178977d89b08766c878a2594b15d203e513acf952340wwang	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
179077d89b08766c878a2594b15d203e513acf952340wwang
179177d89b08766c878a2594b15d203e513acf952340wwang	if (len % 2)
179277d89b08766c878a2594b15d203e513acf952340wwang		len -= len % 2;
179377d89b08766c878a2594b15d203e513acf952340wwang
179477d89b08766c878a2594b15d203e513acf952340wwang	if (len) {
179577d89b08766c878a2594b15d203e513acf952340wwang		len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
179677d89b08766c878a2594b15d203e513acf952340wwang
179777d89b08766c878a2594b15d203e513acf952340wwang		buf = (u8 *)vmalloc(len);
179877d89b08766c878a2594b15d203e513acf952340wwang		if (buf == NULL) {
179977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_ERROR);
180077d89b08766c878a2594b15d203e513acf952340wwang		}
180177d89b08766c878a2594b15d203e513acf952340wwang
180277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_stor_get_xfer_buf(buf, len, srb);
180377d89b08766c878a2594b15d203e513acf952340wwang		scsi_set_resid(srb, scsi_bufflen(srb) - len);
180477d89b08766c878a2594b15d203e513acf952340wwang
180577d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_force_power_on(chip, SSC_PDCTL);
180677d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
180777d89b08766c878a2594b15d203e513acf952340wwang			vfree(buf);
180877d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
180977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
181077d89b08766c878a2594b15d203e513acf952340wwang		}
181177d89b08766c878a2594b15d203e513acf952340wwang
181277d89b08766c878a2594b15d203e513acf952340wwang		for (i = 0; i < len / 2; i++) {
181377d89b08766c878a2594b15d203e513acf952340wwang			val = ((u16)buf[2*i] << 8) | buf[2*i+1];
181477d89b08766c878a2594b15d203e513acf952340wwang			retval = rtsx_write_phy_register(chip, addr + i, val);
181577d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
181677d89b08766c878a2594b15d203e513acf952340wwang				vfree(buf);
181777d89b08766c878a2594b15d203e513acf952340wwang				set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
181877d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
181977d89b08766c878a2594b15d203e513acf952340wwang			}
182077d89b08766c878a2594b15d203e513acf952340wwang		}
182177d89b08766c878a2594b15d203e513acf952340wwang
182277d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
182377d89b08766c878a2594b15d203e513acf952340wwang	}
182477d89b08766c878a2594b15d203e513acf952340wwang
182577d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
182677d89b08766c878a2594b15d203e513acf952340wwang}
182777d89b08766c878a2594b15d203e513acf952340wwang
182877d89b08766c878a2594b15d203e513acf952340wwangstatic int erase_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
182977d89b08766c878a2594b15d203e513acf952340wwang{
183077d89b08766c878a2594b15d203e513acf952340wwang	unsigned short addr;
183177d89b08766c878a2594b15d203e513acf952340wwang	int retval;
183277d89b08766c878a2594b15d203e513acf952340wwang	u8 mode;
183377d89b08766c878a2594b15d203e513acf952340wwang
183477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
183577d89b08766c878a2594b15d203e513acf952340wwang
183677d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
183777d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
183877d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
183977d89b08766c878a2594b15d203e513acf952340wwang	}
184077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
184177d89b08766c878a2594b15d203e513acf952340wwang
184277d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_force_power_on(chip, SSC_PDCTL);
184377d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
184477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
184577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
184677d89b08766c878a2594b15d203e513acf952340wwang	}
184777d89b08766c878a2594b15d203e513acf952340wwang
184877d89b08766c878a2594b15d203e513acf952340wwang	mode = srb->cmnd[3];
184977d89b08766c878a2594b15d203e513acf952340wwang	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
185077d89b08766c878a2594b15d203e513acf952340wwang
185177d89b08766c878a2594b15d203e513acf952340wwang	if (mode == 0) {
185277d89b08766c878a2594b15d203e513acf952340wwang		retval = spi_erase_eeprom_chip(chip);
185377d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
185477d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
185577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
185677d89b08766c878a2594b15d203e513acf952340wwang		}
185777d89b08766c878a2594b15d203e513acf952340wwang	} else if (mode == 1) {
185877d89b08766c878a2594b15d203e513acf952340wwang		retval = spi_erase_eeprom_byte(chip, addr);
185977d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
186077d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
186177d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
186277d89b08766c878a2594b15d203e513acf952340wwang		}
186377d89b08766c878a2594b15d203e513acf952340wwang	} else {
186477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
186577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
186677d89b08766c878a2594b15d203e513acf952340wwang	}
186777d89b08766c878a2594b15d203e513acf952340wwang
186877d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
186977d89b08766c878a2594b15d203e513acf952340wwang}
187077d89b08766c878a2594b15d203e513acf952340wwang
187177d89b08766c878a2594b15d203e513acf952340wwangstatic int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
187277d89b08766c878a2594b15d203e513acf952340wwang{
187377d89b08766c878a2594b15d203e513acf952340wwang	unsigned short addr, len, i;
187477d89b08766c878a2594b15d203e513acf952340wwang	int retval;
187577d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
187677d89b08766c878a2594b15d203e513acf952340wwang
187777d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
187877d89b08766c878a2594b15d203e513acf952340wwang
187977d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
188077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
188177d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
188277d89b08766c878a2594b15d203e513acf952340wwang	}
188377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
188477d89b08766c878a2594b15d203e513acf952340wwang
188577d89b08766c878a2594b15d203e513acf952340wwang	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
188677d89b08766c878a2594b15d203e513acf952340wwang	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
188777d89b08766c878a2594b15d203e513acf952340wwang
188877d89b08766c878a2594b15d203e513acf952340wwang	buf = (u8 *)vmalloc(len);
188977d89b08766c878a2594b15d203e513acf952340wwang	if (!buf) {
189077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
189177d89b08766c878a2594b15d203e513acf952340wwang	}
189277d89b08766c878a2594b15d203e513acf952340wwang
189377d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_force_power_on(chip, SSC_PDCTL);
189477d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
189577d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
189677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
189777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
189877d89b08766c878a2594b15d203e513acf952340wwang	}
189977d89b08766c878a2594b15d203e513acf952340wwang
190077d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < len; i++) {
190177d89b08766c878a2594b15d203e513acf952340wwang		retval = spi_read_eeprom(chip, addr + i, buf + i);
190277d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
190377d89b08766c878a2594b15d203e513acf952340wwang			vfree(buf);
190477d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
190577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
190677d89b08766c878a2594b15d203e513acf952340wwang		}
190777d89b08766c878a2594b15d203e513acf952340wwang	}
190877d89b08766c878a2594b15d203e513acf952340wwang
190977d89b08766c878a2594b15d203e513acf952340wwang	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
191077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, len, srb);
191177d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - len);
191277d89b08766c878a2594b15d203e513acf952340wwang
191377d89b08766c878a2594b15d203e513acf952340wwang	vfree(buf);
191477d89b08766c878a2594b15d203e513acf952340wwang
191577d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
191677d89b08766c878a2594b15d203e513acf952340wwang}
191777d89b08766c878a2594b15d203e513acf952340wwang
191877d89b08766c878a2594b15d203e513acf952340wwangstatic int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
191977d89b08766c878a2594b15d203e513acf952340wwang{
192077d89b08766c878a2594b15d203e513acf952340wwang	unsigned short addr, len, i;
192177d89b08766c878a2594b15d203e513acf952340wwang	int retval;
192277d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
192377d89b08766c878a2594b15d203e513acf952340wwang
192477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
192577d89b08766c878a2594b15d203e513acf952340wwang
192677d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
192777d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
192877d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
192977d89b08766c878a2594b15d203e513acf952340wwang	}
193077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
193177d89b08766c878a2594b15d203e513acf952340wwang
193277d89b08766c878a2594b15d203e513acf952340wwang	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
193377d89b08766c878a2594b15d203e513acf952340wwang	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
193477d89b08766c878a2594b15d203e513acf952340wwang
193577d89b08766c878a2594b15d203e513acf952340wwang	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
193677d89b08766c878a2594b15d203e513acf952340wwang	buf = (u8 *)vmalloc(len);
193777d89b08766c878a2594b15d203e513acf952340wwang	if (buf == NULL) {
193877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
193977d89b08766c878a2594b15d203e513acf952340wwang	}
194077d89b08766c878a2594b15d203e513acf952340wwang
194177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_get_xfer_buf(buf, len, srb);
194277d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - len);
194377d89b08766c878a2594b15d203e513acf952340wwang
194477d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_force_power_on(chip, SSC_PDCTL);
194577d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
194677d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
194777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
194877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
194977d89b08766c878a2594b15d203e513acf952340wwang	}
195077d89b08766c878a2594b15d203e513acf952340wwang
195177d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < len; i++) {
195277d89b08766c878a2594b15d203e513acf952340wwang		retval = spi_write_eeprom(chip, addr + i, buf[i]);
195377d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
195477d89b08766c878a2594b15d203e513acf952340wwang			vfree(buf);
195577d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
195677d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
195777d89b08766c878a2594b15d203e513acf952340wwang		}
195877d89b08766c878a2594b15d203e513acf952340wwang	}
195977d89b08766c878a2594b15d203e513acf952340wwang
196077d89b08766c878a2594b15d203e513acf952340wwang	vfree(buf);
196177d89b08766c878a2594b15d203e513acf952340wwang
196277d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
196377d89b08766c878a2594b15d203e513acf952340wwang}
196477d89b08766c878a2594b15d203e513acf952340wwang
196577d89b08766c878a2594b15d203e513acf952340wwangstatic int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
196677d89b08766c878a2594b15d203e513acf952340wwang{
196777d89b08766c878a2594b15d203e513acf952340wwang	int retval;
196877d89b08766c878a2594b15d203e513acf952340wwang	u8 addr, len, i;
196977d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
197077d89b08766c878a2594b15d203e513acf952340wwang
197177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
197277d89b08766c878a2594b15d203e513acf952340wwang
197377d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
197477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
197577d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
197677d89b08766c878a2594b15d203e513acf952340wwang	}
197777d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
197877d89b08766c878a2594b15d203e513acf952340wwang
197977d89b08766c878a2594b15d203e513acf952340wwang	addr = srb->cmnd[4];
198077d89b08766c878a2594b15d203e513acf952340wwang	len = srb->cmnd[5];
198177d89b08766c878a2594b15d203e513acf952340wwang
198277d89b08766c878a2594b15d203e513acf952340wwang	buf = (u8 *)vmalloc(len);
198377d89b08766c878a2594b15d203e513acf952340wwang	if (!buf) {
198477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
198577d89b08766c878a2594b15d203e513acf952340wwang	}
198677d89b08766c878a2594b15d203e513acf952340wwang
198777d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_force_power_on(chip, SSC_PDCTL);
198877d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
198977d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
199077d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
199177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
199277d89b08766c878a2594b15d203e513acf952340wwang	}
199377d89b08766c878a2594b15d203e513acf952340wwang
199477d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < len; i++) {
199577d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_read_efuse(chip, addr + i, buf + i);
199677d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
199777d89b08766c878a2594b15d203e513acf952340wwang			vfree(buf);
199877d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
199977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
200077d89b08766c878a2594b15d203e513acf952340wwang		}
200177d89b08766c878a2594b15d203e513acf952340wwang	}
200277d89b08766c878a2594b15d203e513acf952340wwang
200377d89b08766c878a2594b15d203e513acf952340wwang	len = (u8)min(scsi_bufflen(srb), (unsigned int)len);
200477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, len, srb);
200577d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - len);
200677d89b08766c878a2594b15d203e513acf952340wwang
200777d89b08766c878a2594b15d203e513acf952340wwang	vfree(buf);
200877d89b08766c878a2594b15d203e513acf952340wwang
200977d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
201077d89b08766c878a2594b15d203e513acf952340wwang}
201177d89b08766c878a2594b15d203e513acf952340wwang
201277d89b08766c878a2594b15d203e513acf952340wwangstatic int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
201377d89b08766c878a2594b15d203e513acf952340wwang{
201477d89b08766c878a2594b15d203e513acf952340wwang	int retval, result = TRANSPORT_GOOD;
201577d89b08766c878a2594b15d203e513acf952340wwang	u16 val;
201677d89b08766c878a2594b15d203e513acf952340wwang	u8 addr, len, i;
201777d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
201877d89b08766c878a2594b15d203e513acf952340wwang
201977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
202077d89b08766c878a2594b15d203e513acf952340wwang
202177d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
202277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
202377d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
202477d89b08766c878a2594b15d203e513acf952340wwang	}
202577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
202677d89b08766c878a2594b15d203e513acf952340wwang
202777d89b08766c878a2594b15d203e513acf952340wwang	addr = srb->cmnd[4];
202877d89b08766c878a2594b15d203e513acf952340wwang	len = srb->cmnd[5];
202977d89b08766c878a2594b15d203e513acf952340wwang
203077d89b08766c878a2594b15d203e513acf952340wwang	len = (u8)min(scsi_bufflen(srb), (unsigned int)len);
203177d89b08766c878a2594b15d203e513acf952340wwang	buf = (u8 *)vmalloc(len);
203277d89b08766c878a2594b15d203e513acf952340wwang	if (buf == NULL) {
203377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
203477d89b08766c878a2594b15d203e513acf952340wwang	}
203577d89b08766c878a2594b15d203e513acf952340wwang
203677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_get_xfer_buf(buf, len, srb);
203777d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - len);
203877d89b08766c878a2594b15d203e513acf952340wwang
203977d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_force_power_on(chip, SSC_PDCTL);
204077d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
204177d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
204277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
204377d89b08766c878a2594b15d203e513acf952340wwang	}
204477d89b08766c878a2594b15d203e513acf952340wwang
204577d89b08766c878a2594b15d203e513acf952340wwang	if (chip->asic_code) {
204677d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_read_phy_register(chip, 0x08, &val);
204777d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
204877d89b08766c878a2594b15d203e513acf952340wwang			vfree(buf);
204977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_ERROR);
205077d89b08766c878a2594b15d203e513acf952340wwang		}
205177d89b08766c878a2594b15d203e513acf952340wwang
205277d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF);
205377d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
205477d89b08766c878a2594b15d203e513acf952340wwang			vfree(buf);
205577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_ERROR);
205677d89b08766c878a2594b15d203e513acf952340wwang		}
205777d89b08766c878a2594b15d203e513acf952340wwang
205877d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(600);
205977d89b08766c878a2594b15d203e513acf952340wwang
206077d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_phy_register(chip, 0x08, 0x4C00 | chip->phy_voltage);
206177d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
206277d89b08766c878a2594b15d203e513acf952340wwang			vfree(buf);
206377d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_ERROR);
206477d89b08766c878a2594b15d203e513acf952340wwang		}
206577d89b08766c878a2594b15d203e513acf952340wwang
206677d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
206777d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
206877d89b08766c878a2594b15d203e513acf952340wwang			vfree(buf);
206977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_ERROR);
207077d89b08766c878a2594b15d203e513acf952340wwang		}
207177d89b08766c878a2594b15d203e513acf952340wwang
207277d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(600);
207377d89b08766c878a2594b15d203e513acf952340wwang	}
207477d89b08766c878a2594b15d203e513acf952340wwang
207577d89b08766c878a2594b15d203e513acf952340wwang	retval = card_power_on(chip, SPI_CARD);
207677d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
207777d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
207877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
207977d89b08766c878a2594b15d203e513acf952340wwang	}
208077d89b08766c878a2594b15d203e513acf952340wwang
208177d89b08766c878a2594b15d203e513acf952340wwang	wait_timeout(50);
208277d89b08766c878a2594b15d203e513acf952340wwang
208377d89b08766c878a2594b15d203e513acf952340wwang	for (i = 0; i < len; i++) {
208477d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_efuse(chip, addr + i, buf[i]);
208577d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
208677d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
208777d89b08766c878a2594b15d203e513acf952340wwang			result = TRANSPORT_FAILED;
208877d89b08766c878a2594b15d203e513acf952340wwang			TRACE_GOTO(chip, Exit);
208977d89b08766c878a2594b15d203e513acf952340wwang		}
209077d89b08766c878a2594b15d203e513acf952340wwang	}
209177d89b08766c878a2594b15d203e513acf952340wwang
209277d89b08766c878a2594b15d203e513acf952340wwangExit:
209377d89b08766c878a2594b15d203e513acf952340wwang	vfree(buf);
209477d89b08766c878a2594b15d203e513acf952340wwang
209577d89b08766c878a2594b15d203e513acf952340wwang	retval = card_power_off(chip, SPI_CARD);
209677d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
209777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
209877d89b08766c878a2594b15d203e513acf952340wwang	}
209977d89b08766c878a2594b15d203e513acf952340wwang
210077d89b08766c878a2594b15d203e513acf952340wwang	if (chip->asic_code) {
210177d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF);
210277d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
210377d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_ERROR);
210477d89b08766c878a2594b15d203e513acf952340wwang		}
210577d89b08766c878a2594b15d203e513acf952340wwang
210677d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(600);
210777d89b08766c878a2594b15d203e513acf952340wwang
210877d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_phy_register(chip, 0x08, val);
210977d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
211077d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_ERROR);
211177d89b08766c878a2594b15d203e513acf952340wwang		}
211277d89b08766c878a2594b15d203e513acf952340wwang
211377d89b08766c878a2594b15d203e513acf952340wwang		retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
211477d89b08766c878a2594b15d203e513acf952340wwang		if (retval != STATUS_SUCCESS) {
211577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_ERROR);
211677d89b08766c878a2594b15d203e513acf952340wwang		}
211777d89b08766c878a2594b15d203e513acf952340wwang	}
211877d89b08766c878a2594b15d203e513acf952340wwang
211977d89b08766c878a2594b15d203e513acf952340wwang	return result;
212077d89b08766c878a2594b15d203e513acf952340wwang}
212177d89b08766c878a2594b15d203e513acf952340wwang
212277d89b08766c878a2594b15d203e513acf952340wwangstatic int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
212377d89b08766c878a2594b15d203e513acf952340wwang{
212477d89b08766c878a2594b15d203e513acf952340wwang	int retval;
212577d89b08766c878a2594b15d203e513acf952340wwang	u8 func, func_max;
212677d89b08766c878a2594b15d203e513acf952340wwang	u16 addr, len;
212777d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
212877d89b08766c878a2594b15d203e513acf952340wwang
212977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
213077d89b08766c878a2594b15d203e513acf952340wwang
213177d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
213277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
213377d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
213477d89b08766c878a2594b15d203e513acf952340wwang	}
213577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
213677d89b08766c878a2594b15d203e513acf952340wwang
213777d89b08766c878a2594b15d203e513acf952340wwang	func = srb->cmnd[3];
213877d89b08766c878a2594b15d203e513acf952340wwang	addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
213977d89b08766c878a2594b15d203e513acf952340wwang	len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7];
214077d89b08766c878a2594b15d203e513acf952340wwang
214177d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("%s: func = %d, addr = 0x%x, len = %d\n", __func__, func, addr, len);
214277d89b08766c878a2594b15d203e513acf952340wwang
214377d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
214477d89b08766c878a2594b15d203e513acf952340wwang		func_max = 1;
214577d89b08766c878a2594b15d203e513acf952340wwang	} else {
214677d89b08766c878a2594b15d203e513acf952340wwang		func_max = 0;
214777d89b08766c878a2594b15d203e513acf952340wwang	}
214877d89b08766c878a2594b15d203e513acf952340wwang
214977d89b08766c878a2594b15d203e513acf952340wwang	if (func > func_max) {
215077d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
215177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
215277d89b08766c878a2594b15d203e513acf952340wwang	}
215377d89b08766c878a2594b15d203e513acf952340wwang
215477d89b08766c878a2594b15d203e513acf952340wwang	buf = (u8 *)vmalloc(len);
215577d89b08766c878a2594b15d203e513acf952340wwang	if (!buf) {
215677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
215777d89b08766c878a2594b15d203e513acf952340wwang	}
215877d89b08766c878a2594b15d203e513acf952340wwang
215977d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_read_cfg_seq(chip, func, addr, buf, len);
216077d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
216177d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
216277d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
216377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
216477d89b08766c878a2594b15d203e513acf952340wwang	}
216577d89b08766c878a2594b15d203e513acf952340wwang
216677d89b08766c878a2594b15d203e513acf952340wwang	len = (u16)min(scsi_bufflen(srb), (unsigned int)len);
216777d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, len, srb);
216877d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - len);
216977d89b08766c878a2594b15d203e513acf952340wwang
217077d89b08766c878a2594b15d203e513acf952340wwang	vfree(buf);
217177d89b08766c878a2594b15d203e513acf952340wwang
217277d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
217377d89b08766c878a2594b15d203e513acf952340wwang}
217477d89b08766c878a2594b15d203e513acf952340wwang
217577d89b08766c878a2594b15d203e513acf952340wwangstatic int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
217677d89b08766c878a2594b15d203e513acf952340wwang{
217777d89b08766c878a2594b15d203e513acf952340wwang	int retval;
217877d89b08766c878a2594b15d203e513acf952340wwang	u8 func, func_max;
217977d89b08766c878a2594b15d203e513acf952340wwang	u16 addr, len;
218077d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
218177d89b08766c878a2594b15d203e513acf952340wwang
218277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
218377d89b08766c878a2594b15d203e513acf952340wwang
218477d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
218577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
218677d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
218777d89b08766c878a2594b15d203e513acf952340wwang	}
218877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
218977d89b08766c878a2594b15d203e513acf952340wwang
219077d89b08766c878a2594b15d203e513acf952340wwang	func = srb->cmnd[3];
219177d89b08766c878a2594b15d203e513acf952340wwang	addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
219277d89b08766c878a2594b15d203e513acf952340wwang	len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7];
219377d89b08766c878a2594b15d203e513acf952340wwang
219477d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("%s: func = %d, addr = 0x%x\n", __func__, func, addr);
219577d89b08766c878a2594b15d203e513acf952340wwang
219677d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
219777d89b08766c878a2594b15d203e513acf952340wwang		func_max = 1;
219877d89b08766c878a2594b15d203e513acf952340wwang	} else {
219977d89b08766c878a2594b15d203e513acf952340wwang		func_max = 0;
220077d89b08766c878a2594b15d203e513acf952340wwang	}
220177d89b08766c878a2594b15d203e513acf952340wwang
220277d89b08766c878a2594b15d203e513acf952340wwang	if (func > func_max) {
220377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
220477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
220577d89b08766c878a2594b15d203e513acf952340wwang	}
220677d89b08766c878a2594b15d203e513acf952340wwang
220777d89b08766c878a2594b15d203e513acf952340wwang	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
220877d89b08766c878a2594b15d203e513acf952340wwang	buf = (u8 *)vmalloc(len);
220977d89b08766c878a2594b15d203e513acf952340wwang	if (!buf) {
221077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
221177d89b08766c878a2594b15d203e513acf952340wwang	}
221277d89b08766c878a2594b15d203e513acf952340wwang
221377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_get_xfer_buf(buf, len, srb);
221477d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - len);
221577d89b08766c878a2594b15d203e513acf952340wwang
221677d89b08766c878a2594b15d203e513acf952340wwang	retval = rtsx_write_cfg_seq(chip, func, addr, buf, len);
221777d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
221877d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
221977d89b08766c878a2594b15d203e513acf952340wwang		vfree(buf);
222077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
222177d89b08766c878a2594b15d203e513acf952340wwang	}
222277d89b08766c878a2594b15d203e513acf952340wwang
222377d89b08766c878a2594b15d203e513acf952340wwang	vfree(buf);
222477d89b08766c878a2594b15d203e513acf952340wwang
222577d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
222677d89b08766c878a2594b15d203e513acf952340wwang}
222777d89b08766c878a2594b15d203e513acf952340wwang
222877d89b08766c878a2594b15d203e513acf952340wwangstatic int app_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
222977d89b08766c878a2594b15d203e513acf952340wwang{
223077d89b08766c878a2594b15d203e513acf952340wwang	int result;
223177d89b08766c878a2594b15d203e513acf952340wwang
223277d89b08766c878a2594b15d203e513acf952340wwang	switch (srb->cmnd[2]) {
223377d89b08766c878a2594b15d203e513acf952340wwang	case PP_READ10:
223477d89b08766c878a2594b15d203e513acf952340wwang	case PP_WRITE10:
223577d89b08766c878a2594b15d203e513acf952340wwang		result = read_write(srb, chip);
223677d89b08766c878a2594b15d203e513acf952340wwang		break;
223777d89b08766c878a2594b15d203e513acf952340wwang
223877d89b08766c878a2594b15d203e513acf952340wwang	case READ_HOST_REG:
223977d89b08766c878a2594b15d203e513acf952340wwang		result = read_host_reg(srb, chip);
224077d89b08766c878a2594b15d203e513acf952340wwang		break;
224177d89b08766c878a2594b15d203e513acf952340wwang
224277d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_HOST_REG:
224377d89b08766c878a2594b15d203e513acf952340wwang		result = write_host_reg(srb, chip);
224477d89b08766c878a2594b15d203e513acf952340wwang		break;
224577d89b08766c878a2594b15d203e513acf952340wwang
224677d89b08766c878a2594b15d203e513acf952340wwang	case GET_VAR:
224777d89b08766c878a2594b15d203e513acf952340wwang		result = get_variable(srb, chip);
224877d89b08766c878a2594b15d203e513acf952340wwang		break;
224977d89b08766c878a2594b15d203e513acf952340wwang
225077d89b08766c878a2594b15d203e513acf952340wwang	case SET_VAR:
225177d89b08766c878a2594b15d203e513acf952340wwang		result = set_variable(srb, chip);
225277d89b08766c878a2594b15d203e513acf952340wwang		break;
225377d89b08766c878a2594b15d203e513acf952340wwang
225477d89b08766c878a2594b15d203e513acf952340wwang	case DMA_READ:
225577d89b08766c878a2594b15d203e513acf952340wwang	case DMA_WRITE:
225677d89b08766c878a2594b15d203e513acf952340wwang		result = dma_access_ring_buffer(srb, chip);
225777d89b08766c878a2594b15d203e513acf952340wwang		break;
225877d89b08766c878a2594b15d203e513acf952340wwang
225977d89b08766c878a2594b15d203e513acf952340wwang	case READ_PHY:
226077d89b08766c878a2594b15d203e513acf952340wwang		result = read_phy_register(srb, chip);
226177d89b08766c878a2594b15d203e513acf952340wwang		break;
226277d89b08766c878a2594b15d203e513acf952340wwang
226377d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_PHY:
226477d89b08766c878a2594b15d203e513acf952340wwang		result = write_phy_register(srb, chip);
226577d89b08766c878a2594b15d203e513acf952340wwang		break;
226677d89b08766c878a2594b15d203e513acf952340wwang
226777d89b08766c878a2594b15d203e513acf952340wwang	case ERASE_EEPROM2:
226877d89b08766c878a2594b15d203e513acf952340wwang		result = erase_eeprom2(srb, chip);
226977d89b08766c878a2594b15d203e513acf952340wwang		break;
227077d89b08766c878a2594b15d203e513acf952340wwang
227177d89b08766c878a2594b15d203e513acf952340wwang	case READ_EEPROM2:
227277d89b08766c878a2594b15d203e513acf952340wwang		result = read_eeprom2(srb, chip);
227377d89b08766c878a2594b15d203e513acf952340wwang		break;
227477d89b08766c878a2594b15d203e513acf952340wwang
227577d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_EEPROM2:
227677d89b08766c878a2594b15d203e513acf952340wwang		result = write_eeprom2(srb, chip);
227777d89b08766c878a2594b15d203e513acf952340wwang		break;
227877d89b08766c878a2594b15d203e513acf952340wwang
227977d89b08766c878a2594b15d203e513acf952340wwang	case READ_EFUSE:
228077d89b08766c878a2594b15d203e513acf952340wwang		result = read_efuse(srb, chip);
228177d89b08766c878a2594b15d203e513acf952340wwang		break;
228277d89b08766c878a2594b15d203e513acf952340wwang
228377d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_EFUSE:
228477d89b08766c878a2594b15d203e513acf952340wwang		result = write_efuse(srb, chip);
228577d89b08766c878a2594b15d203e513acf952340wwang		break;
228677d89b08766c878a2594b15d203e513acf952340wwang
228777d89b08766c878a2594b15d203e513acf952340wwang	case READ_CFG:
228877d89b08766c878a2594b15d203e513acf952340wwang		result = read_cfg_byte(srb, chip);
228977d89b08766c878a2594b15d203e513acf952340wwang		break;
229077d89b08766c878a2594b15d203e513acf952340wwang
229177d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_CFG:
229277d89b08766c878a2594b15d203e513acf952340wwang		result = write_cfg_byte(srb, chip);
229377d89b08766c878a2594b15d203e513acf952340wwang		break;
229477d89b08766c878a2594b15d203e513acf952340wwang
229577d89b08766c878a2594b15d203e513acf952340wwang	case SET_CHIP_MODE:
229677d89b08766c878a2594b15d203e513acf952340wwang		result = set_chip_mode(srb, chip);
229777d89b08766c878a2594b15d203e513acf952340wwang		break;
229877d89b08766c878a2594b15d203e513acf952340wwang
229977d89b08766c878a2594b15d203e513acf952340wwang	case SUIT_CMD:
230077d89b08766c878a2594b15d203e513acf952340wwang		result = suit_cmd(srb, chip);
230177d89b08766c878a2594b15d203e513acf952340wwang		break;
230277d89b08766c878a2594b15d203e513acf952340wwang
230377d89b08766c878a2594b15d203e513acf952340wwang	case GET_DEV_STATUS:
230477d89b08766c878a2594b15d203e513acf952340wwang		result = get_dev_status(srb, chip);
230577d89b08766c878a2594b15d203e513acf952340wwang		break;
230677d89b08766c878a2594b15d203e513acf952340wwang
230777d89b08766c878a2594b15d203e513acf952340wwang	default:
230877d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
230977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
231077d89b08766c878a2594b15d203e513acf952340wwang	}
231177d89b08766c878a2594b15d203e513acf952340wwang
231277d89b08766c878a2594b15d203e513acf952340wwang	return result;
231377d89b08766c878a2594b15d203e513acf952340wwang}
231477d89b08766c878a2594b15d203e513acf952340wwang
231577d89b08766c878a2594b15d203e513acf952340wwang
231677d89b08766c878a2594b15d203e513acf952340wwangstatic int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
231777d89b08766c878a2594b15d203e513acf952340wwang{
231877d89b08766c878a2594b15d203e513acf952340wwang	u8 rtsx_status[16];
231977d89b08766c878a2594b15d203e513acf952340wwang	int buf_len;
232077d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
232177d89b08766c878a2594b15d203e513acf952340wwang
232277d89b08766c878a2594b15d203e513acf952340wwang	rtsx_status[0] = (u8)(chip->vendor_id >> 8);
232377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_status[1] = (u8)(chip->vendor_id);
232477d89b08766c878a2594b15d203e513acf952340wwang
232577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_status[2] = (u8)(chip->product_id >> 8);
232677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_status[3] = (u8)(chip->product_id);
232777d89b08766c878a2594b15d203e513acf952340wwang
232877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_status[4] = (u8)lun;
232977d89b08766c878a2594b15d203e513acf952340wwang
233077d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
233177d89b08766c878a2594b15d203e513acf952340wwang		if (chip->lun2card[lun] == SD_CARD) {
233277d89b08766c878a2594b15d203e513acf952340wwang			rtsx_status[5] = 2;
233377d89b08766c878a2594b15d203e513acf952340wwang		} else {
233477d89b08766c878a2594b15d203e513acf952340wwang			rtsx_status[5] = 3;
233577d89b08766c878a2594b15d203e513acf952340wwang		}
233677d89b08766c878a2594b15d203e513acf952340wwang	} else {
233777d89b08766c878a2594b15d203e513acf952340wwang		if (chip->card_exist) {
233877d89b08766c878a2594b15d203e513acf952340wwang			if (chip->card_exist & XD_CARD) {
233977d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[5] = 4;
234077d89b08766c878a2594b15d203e513acf952340wwang			} else if (chip->card_exist & SD_CARD) {
234177d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[5] = 2;
234277d89b08766c878a2594b15d203e513acf952340wwang			} else if (chip->card_exist & MS_CARD) {
234377d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[5] = 3;
234477d89b08766c878a2594b15d203e513acf952340wwang			} else {
234577d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[5] = 7;
234677d89b08766c878a2594b15d203e513acf952340wwang			}
234777d89b08766c878a2594b15d203e513acf952340wwang		} else {
234877d89b08766c878a2594b15d203e513acf952340wwang			rtsx_status[5] = 7;
234977d89b08766c878a2594b15d203e513acf952340wwang		}
235077d89b08766c878a2594b15d203e513acf952340wwang	}
235177d89b08766c878a2594b15d203e513acf952340wwang
235277d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
235377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[6] = 2;
235477d89b08766c878a2594b15d203e513acf952340wwang	} else {
235577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[6] = 1;
235677d89b08766c878a2594b15d203e513acf952340wwang	}
235777d89b08766c878a2594b15d203e513acf952340wwang
235877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_status[7] = (u8)(chip->product_id);
235977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_status[8] = chip->ic_version;
236077d89b08766c878a2594b15d203e513acf952340wwang
236177d89b08766c878a2594b15d203e513acf952340wwang	if (check_card_exist(chip, lun)) {
236277d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[9] = 1;
236377d89b08766c878a2594b15d203e513acf952340wwang	} else {
236477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[9] = 0;
236577d89b08766c878a2594b15d203e513acf952340wwang	}
236677d89b08766c878a2594b15d203e513acf952340wwang
236777d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
236877d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[10] = 0;
236977d89b08766c878a2594b15d203e513acf952340wwang	} else {
237077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[10] = 1;
237177d89b08766c878a2594b15d203e513acf952340wwang	}
237277d89b08766c878a2594b15d203e513acf952340wwang
237377d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
237477d89b08766c878a2594b15d203e513acf952340wwang		if (chip->lun2card[lun] == SD_CARD) {
237577d89b08766c878a2594b15d203e513acf952340wwang			rtsx_status[11] = SD_CARD;
237677d89b08766c878a2594b15d203e513acf952340wwang		} else {
237777d89b08766c878a2594b15d203e513acf952340wwang			rtsx_status[11] = MS_CARD;
237877d89b08766c878a2594b15d203e513acf952340wwang		}
237977d89b08766c878a2594b15d203e513acf952340wwang	} else {
238077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[11] = XD_CARD | SD_CARD | MS_CARD;
238177d89b08766c878a2594b15d203e513acf952340wwang	}
238277d89b08766c878a2594b15d203e513acf952340wwang
238377d89b08766c878a2594b15d203e513acf952340wwang	if (check_card_ready(chip, lun)) {
238477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[12] = 1;
238577d89b08766c878a2594b15d203e513acf952340wwang	} else {
238677d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[12] = 0;
238777d89b08766c878a2594b15d203e513acf952340wwang	}
238877d89b08766c878a2594b15d203e513acf952340wwang
238977d89b08766c878a2594b15d203e513acf952340wwang	if (get_lun_card(chip, lun) == XD_CARD) {
239077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[13] = 0x40;
239177d89b08766c878a2594b15d203e513acf952340wwang	} else if (get_lun_card(chip, lun) == SD_CARD) {
239277d89b08766c878a2594b15d203e513acf952340wwang		struct sd_info *sd_card = &(chip->sd_card);
239377d89b08766c878a2594b15d203e513acf952340wwang
239477d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[13] = 0x20;
239577d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_SD(sd_card)) {
239677d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_SD_HCXC(sd_card))
239777d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[13] |= 0x04;
239877d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_SD_HS(sd_card))
239977d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[13] |= 0x02;
240077d89b08766c878a2594b15d203e513acf952340wwang		} else {
240177d89b08766c878a2594b15d203e513acf952340wwang			rtsx_status[13] |= 0x08;
240277d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_MMC_52M(sd_card))
240377d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[13] |= 0x02;
240477d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_MMC_SECTOR_MODE(sd_card))
240577d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[13] |= 0x04;
240677d89b08766c878a2594b15d203e513acf952340wwang		}
240777d89b08766c878a2594b15d203e513acf952340wwang	} else if (get_lun_card(chip, lun) == MS_CARD) {
240877d89b08766c878a2594b15d203e513acf952340wwang		struct ms_info *ms_card = &(chip->ms_card);
240977d89b08766c878a2594b15d203e513acf952340wwang
241077d89b08766c878a2594b15d203e513acf952340wwang		if (CHK_MSPRO(ms_card)) {
241177d89b08766c878a2594b15d203e513acf952340wwang			rtsx_status[13] = 0x38;
241277d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_HG8BIT(ms_card))
241377d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[13] |= 0x04;
241477d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_MSXC
241577d89b08766c878a2594b15d203e513acf952340wwang			if (CHK_MSXC(ms_card))
241677d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[13] |= 0x01;
241777d89b08766c878a2594b15d203e513acf952340wwang#endif
241877d89b08766c878a2594b15d203e513acf952340wwang		} else {
241977d89b08766c878a2594b15d203e513acf952340wwang			rtsx_status[13] = 0x30;
242077d89b08766c878a2594b15d203e513acf952340wwang		}
242177d89b08766c878a2594b15d203e513acf952340wwang	} else {
242277d89b08766c878a2594b15d203e513acf952340wwang		if (CHECK_LUN_MODE(chip, DEFAULT_SINGLE)) {
242377d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SDIO
242477d89b08766c878a2594b15d203e513acf952340wwang			if (chip->sd_io && chip->sd_int) {
242577d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[13] = 0x60;
242677d89b08766c878a2594b15d203e513acf952340wwang			} else {
242777d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[13] = 0x70;
242877d89b08766c878a2594b15d203e513acf952340wwang			}
242977d89b08766c878a2594b15d203e513acf952340wwang#else
243077d89b08766c878a2594b15d203e513acf952340wwang			rtsx_status[13] = 0x70;
243177d89b08766c878a2594b15d203e513acf952340wwang#endif
243277d89b08766c878a2594b15d203e513acf952340wwang		} else {
243377d89b08766c878a2594b15d203e513acf952340wwang			if (chip->lun2card[lun] == SD_CARD) {
243477d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[13] = 0x20;
243577d89b08766c878a2594b15d203e513acf952340wwang			} else {
243677d89b08766c878a2594b15d203e513acf952340wwang				rtsx_status[13] = 0x30;
243777d89b08766c878a2594b15d203e513acf952340wwang			}
243877d89b08766c878a2594b15d203e513acf952340wwang		}
243977d89b08766c878a2594b15d203e513acf952340wwang	}
244077d89b08766c878a2594b15d203e513acf952340wwang
244177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_status[14] = 0x78;
244277d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
244377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[15] = 0x83;
244477d89b08766c878a2594b15d203e513acf952340wwang	} else {
244577d89b08766c878a2594b15d203e513acf952340wwang		rtsx_status[15] = 0x82;
244677d89b08766c878a2594b15d203e513acf952340wwang	}
244777d89b08766c878a2594b15d203e513acf952340wwang
244877d89b08766c878a2594b15d203e513acf952340wwang	buf_len = min(scsi_bufflen(srb), (unsigned int)sizeof(rtsx_status));
244977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(rtsx_status, buf_len, srb);
245077d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
245177d89b08766c878a2594b15d203e513acf952340wwang
245277d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
245377d89b08766c878a2594b15d203e513acf952340wwang}
245477d89b08766c878a2594b15d203e513acf952340wwang
245577d89b08766c878a2594b15d203e513acf952340wwangstatic int get_card_bus_width(struct scsi_cmnd *srb, struct rtsx_chip *chip)
245677d89b08766c878a2594b15d203e513acf952340wwang{
245777d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
245877d89b08766c878a2594b15d203e513acf952340wwang	u8 card, bus_width;
245977d89b08766c878a2594b15d203e513acf952340wwang
246077d89b08766c878a2594b15d203e513acf952340wwang	if (!check_card_ready(chip, lun)) {
246177d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
246277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
246377d89b08766c878a2594b15d203e513acf952340wwang	}
246477d89b08766c878a2594b15d203e513acf952340wwang
246577d89b08766c878a2594b15d203e513acf952340wwang	card = get_lun_card(chip, lun);
246677d89b08766c878a2594b15d203e513acf952340wwang	if ((card == SD_CARD) || (card == MS_CARD)) {
246777d89b08766c878a2594b15d203e513acf952340wwang		bus_width = chip->card_bus_width[lun];
246877d89b08766c878a2594b15d203e513acf952340wwang	} else {
246977d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
247077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
247177d89b08766c878a2594b15d203e513acf952340wwang	}
247277d89b08766c878a2594b15d203e513acf952340wwang
247377d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
247477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(&bus_width, scsi_bufflen(srb), srb);
247577d89b08766c878a2594b15d203e513acf952340wwang
247677d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
247777d89b08766c878a2594b15d203e513acf952340wwang}
247877d89b08766c878a2594b15d203e513acf952340wwang
247977d89b08766c878a2594b15d203e513acf952340wwangstatic int spi_vendor_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
248077d89b08766c878a2594b15d203e513acf952340wwang{
248177d89b08766c878a2594b15d203e513acf952340wwang	int result;
248277d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
248377d89b08766c878a2594b15d203e513acf952340wwang	u8 gpio_dir;
248477d89b08766c878a2594b15d203e513acf952340wwang
248577d89b08766c878a2594b15d203e513acf952340wwang	if (CHECK_PID(chip, 0x5208) && CHECK_PID(chip, 0x5288)) {
248677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
248777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
248877d89b08766c878a2594b15d203e513acf952340wwang	}
248977d89b08766c878a2594b15d203e513acf952340wwang
249077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
249177d89b08766c878a2594b15d203e513acf952340wwang
249277d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
249377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
249477d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
249577d89b08766c878a2594b15d203e513acf952340wwang	}
249677d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
249777d89b08766c878a2594b15d203e513acf952340wwang
249877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_force_power_on(chip, SSC_PDCTL);
249977d89b08766c878a2594b15d203e513acf952340wwang
250077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_read_register(chip, CARD_GPIO_DIR, &gpio_dir);
250177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir & 0x06);
250277d89b08766c878a2594b15d203e513acf952340wwang
250377d89b08766c878a2594b15d203e513acf952340wwang	switch (srb->cmnd[2]) {
250477d89b08766c878a2594b15d203e513acf952340wwang	case SCSI_SPI_GETSTATUS:
250577d89b08766c878a2594b15d203e513acf952340wwang		result = spi_get_status(srb, chip);
250677d89b08766c878a2594b15d203e513acf952340wwang		break;
250777d89b08766c878a2594b15d203e513acf952340wwang
250877d89b08766c878a2594b15d203e513acf952340wwang	case SCSI_SPI_SETPARAMETER:
250977d89b08766c878a2594b15d203e513acf952340wwang		result = spi_set_parameter(srb, chip);
251077d89b08766c878a2594b15d203e513acf952340wwang		break;
251177d89b08766c878a2594b15d203e513acf952340wwang
251277d89b08766c878a2594b15d203e513acf952340wwang	case SCSI_SPI_READFALSHID:
251377d89b08766c878a2594b15d203e513acf952340wwang		result = spi_read_flash_id(srb, chip);
251477d89b08766c878a2594b15d203e513acf952340wwang		break;
251577d89b08766c878a2594b15d203e513acf952340wwang
251677d89b08766c878a2594b15d203e513acf952340wwang	case SCSI_SPI_READFLASH:
251777d89b08766c878a2594b15d203e513acf952340wwang		result = spi_read_flash(srb, chip);
251877d89b08766c878a2594b15d203e513acf952340wwang		break;
251977d89b08766c878a2594b15d203e513acf952340wwang
252077d89b08766c878a2594b15d203e513acf952340wwang	case SCSI_SPI_WRITEFLASH:
252177d89b08766c878a2594b15d203e513acf952340wwang		result = spi_write_flash(srb, chip);
252277d89b08766c878a2594b15d203e513acf952340wwang		break;
252377d89b08766c878a2594b15d203e513acf952340wwang
252477d89b08766c878a2594b15d203e513acf952340wwang	case SCSI_SPI_WRITEFLASHSTATUS:
252577d89b08766c878a2594b15d203e513acf952340wwang		result = spi_write_flash_status(srb, chip);
252677d89b08766c878a2594b15d203e513acf952340wwang		break;
252777d89b08766c878a2594b15d203e513acf952340wwang
252877d89b08766c878a2594b15d203e513acf952340wwang	case SCSI_SPI_ERASEFLASH:
252977d89b08766c878a2594b15d203e513acf952340wwang		result = spi_erase_flash(srb, chip);
253077d89b08766c878a2594b15d203e513acf952340wwang		break;
253177d89b08766c878a2594b15d203e513acf952340wwang
253277d89b08766c878a2594b15d203e513acf952340wwang	default:
253377d89b08766c878a2594b15d203e513acf952340wwang		rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
253477d89b08766c878a2594b15d203e513acf952340wwang
253577d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
253677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
253777d89b08766c878a2594b15d203e513acf952340wwang	}
253877d89b08766c878a2594b15d203e513acf952340wwang
253977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
254077d89b08766c878a2594b15d203e513acf952340wwang
254177d89b08766c878a2594b15d203e513acf952340wwang	if (result != STATUS_SUCCESS) {
254277d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
254377d89b08766c878a2594b15d203e513acf952340wwang	}
254477d89b08766c878a2594b15d203e513acf952340wwang
254577d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
254677d89b08766c878a2594b15d203e513acf952340wwang}
254777d89b08766c878a2594b15d203e513acf952340wwang
254877d89b08766c878a2594b15d203e513acf952340wwangstatic int vendor_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
254977d89b08766c878a2594b15d203e513acf952340wwang{
255077d89b08766c878a2594b15d203e513acf952340wwang	int result;
255177d89b08766c878a2594b15d203e513acf952340wwang
255277d89b08766c878a2594b15d203e513acf952340wwang	switch (srb->cmnd[1]) {
255377d89b08766c878a2594b15d203e513acf952340wwang	case READ_STATUS:
255477d89b08766c878a2594b15d203e513acf952340wwang		result = read_status(srb, chip);
255577d89b08766c878a2594b15d203e513acf952340wwang		break;
255677d89b08766c878a2594b15d203e513acf952340wwang
255777d89b08766c878a2594b15d203e513acf952340wwang	case READ_MEM:
255877d89b08766c878a2594b15d203e513acf952340wwang		result = read_mem(srb, chip);
255977d89b08766c878a2594b15d203e513acf952340wwang		break;
256077d89b08766c878a2594b15d203e513acf952340wwang
256177d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_MEM:
256277d89b08766c878a2594b15d203e513acf952340wwang		result = write_mem(srb, chip);
256377d89b08766c878a2594b15d203e513acf952340wwang		break;
256477d89b08766c878a2594b15d203e513acf952340wwang
256577d89b08766c878a2594b15d203e513acf952340wwang	case READ_EEPROM:
256677d89b08766c878a2594b15d203e513acf952340wwang		result = read_eeprom(srb, chip);
256777d89b08766c878a2594b15d203e513acf952340wwang		break;
256877d89b08766c878a2594b15d203e513acf952340wwang
256977d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_EEPROM:
257077d89b08766c878a2594b15d203e513acf952340wwang		result = write_eeprom(srb, chip);
257177d89b08766c878a2594b15d203e513acf952340wwang		break;
257277d89b08766c878a2594b15d203e513acf952340wwang
257377d89b08766c878a2594b15d203e513acf952340wwang	case TOGGLE_GPIO:
257477d89b08766c878a2594b15d203e513acf952340wwang		result = toggle_gpio_cmd(srb, chip);
257577d89b08766c878a2594b15d203e513acf952340wwang		break;
257677d89b08766c878a2594b15d203e513acf952340wwang
257777d89b08766c878a2594b15d203e513acf952340wwang	case GET_SD_CSD:
257877d89b08766c878a2594b15d203e513acf952340wwang		result = get_sd_csd(srb, chip);
257977d89b08766c878a2594b15d203e513acf952340wwang		break;
258077d89b08766c878a2594b15d203e513acf952340wwang
258177d89b08766c878a2594b15d203e513acf952340wwang	case GET_BUS_WIDTH:
258277d89b08766c878a2594b15d203e513acf952340wwang		result = get_card_bus_width(srb, chip);
258377d89b08766c878a2594b15d203e513acf952340wwang		break;
258477d89b08766c878a2594b15d203e513acf952340wwang
258577d89b08766c878a2594b15d203e513acf952340wwang#ifdef _MSG_TRACE
258677d89b08766c878a2594b15d203e513acf952340wwang	case TRACE_MSG:
258777d89b08766c878a2594b15d203e513acf952340wwang		result = trace_msg_cmd(srb, chip);
258877d89b08766c878a2594b15d203e513acf952340wwang		break;
258977d89b08766c878a2594b15d203e513acf952340wwang#endif
259077d89b08766c878a2594b15d203e513acf952340wwang
259177d89b08766c878a2594b15d203e513acf952340wwang	case SCSI_APP_CMD:
259277d89b08766c878a2594b15d203e513acf952340wwang		result = app_cmd(srb, chip);
259377d89b08766c878a2594b15d203e513acf952340wwang		break;
259477d89b08766c878a2594b15d203e513acf952340wwang
259577d89b08766c878a2594b15d203e513acf952340wwang	case SPI_VENDOR_COMMAND:
259677d89b08766c878a2594b15d203e513acf952340wwang		result = spi_vendor_cmd(srb, chip);
259777d89b08766c878a2594b15d203e513acf952340wwang		break;
259877d89b08766c878a2594b15d203e513acf952340wwang
259977d89b08766c878a2594b15d203e513acf952340wwang	default:
260077d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
260177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
260277d89b08766c878a2594b15d203e513acf952340wwang	}
260377d89b08766c878a2594b15d203e513acf952340wwang
260477d89b08766c878a2594b15d203e513acf952340wwang	return result;
260577d89b08766c878a2594b15d203e513acf952340wwang}
260677d89b08766c878a2594b15d203e513acf952340wwang
260777d89b08766c878a2594b15d203e513acf952340wwang#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK)
260877d89b08766c878a2594b15d203e513acf952340wwangvoid led_shine(struct scsi_cmnd *srb, struct rtsx_chip *chip)
260977d89b08766c878a2594b15d203e513acf952340wwang{
261077d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
261177d89b08766c878a2594b15d203e513acf952340wwang	u16 sec_cnt;
261277d89b08766c878a2594b15d203e513acf952340wwang
261377d89b08766c878a2594b15d203e513acf952340wwang	if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) {
261477d89b08766c878a2594b15d203e513acf952340wwang		sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
261577d89b08766c878a2594b15d203e513acf952340wwang	} else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) {
261677d89b08766c878a2594b15d203e513acf952340wwang		sec_cnt = srb->cmnd[4];
261777d89b08766c878a2594b15d203e513acf952340wwang	} else {
261877d89b08766c878a2594b15d203e513acf952340wwang		return;
261977d89b08766c878a2594b15d203e513acf952340wwang	}
262077d89b08766c878a2594b15d203e513acf952340wwang
262177d89b08766c878a2594b15d203e513acf952340wwang	if (chip->rw_cap[lun] >= GPIO_TOGGLE_THRESHOLD) {
262277d89b08766c878a2594b15d203e513acf952340wwang		toggle_gpio(chip, LED_GPIO);
262377d89b08766c878a2594b15d203e513acf952340wwang		chip->rw_cap[lun] = 0;
262477d89b08766c878a2594b15d203e513acf952340wwang	} else {
262577d89b08766c878a2594b15d203e513acf952340wwang		chip->rw_cap[lun] += sec_cnt;
262677d89b08766c878a2594b15d203e513acf952340wwang	}
262777d89b08766c878a2594b15d203e513acf952340wwang}
262877d89b08766c878a2594b15d203e513acf952340wwang#endif
262977d89b08766c878a2594b15d203e513acf952340wwang
263077d89b08766c878a2594b15d203e513acf952340wwangstatic int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
263177d89b08766c878a2594b15d203e513acf952340wwang{
263277d89b08766c878a2594b15d203e513acf952340wwang	struct ms_info *ms_card = &(chip->ms_card);
263377d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
263477d89b08766c878a2594b15d203e513acf952340wwang	int retval, quick_format;
263577d89b08766c878a2594b15d203e513acf952340wwang
263677d89b08766c878a2594b15d203e513acf952340wwang	if (get_lun_card(chip, lun) != MS_CARD) {
263777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
263877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
263977d89b08766c878a2594b15d203e513acf952340wwang	}
264077d89b08766c878a2594b15d203e513acf952340wwang
264177d89b08766c878a2594b15d203e513acf952340wwang	if ((srb->cmnd[3] != 0x4D) || (srb->cmnd[4] != 0x47) ||
264277d89b08766c878a2594b15d203e513acf952340wwang		(srb->cmnd[5] != 0x66) || (srb->cmnd[6] != 0x6D) ||
264377d89b08766c878a2594b15d203e513acf952340wwang		(srb->cmnd[7] != 0x74)) {
264477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
264577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
264677d89b08766c878a2594b15d203e513acf952340wwang	}
264777d89b08766c878a2594b15d203e513acf952340wwang
264877d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
264977d89b08766c878a2594b15d203e513acf952340wwang
265077d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
265177d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
265277d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
265377d89b08766c878a2594b15d203e513acf952340wwang
265477d89b08766c878a2594b15d203e513acf952340wwang		if (!check_card_ready(chip, lun) ||
265577d89b08766c878a2594b15d203e513acf952340wwang				(get_card_size(chip, lun) == 0)) {
265677d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
265777d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
265877d89b08766c878a2594b15d203e513acf952340wwang		}
265977d89b08766c878a2594b15d203e513acf952340wwang	}
266077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
266177d89b08766c878a2594b15d203e513acf952340wwang
266277d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[8] & 0x01) {
266377d89b08766c878a2594b15d203e513acf952340wwang		quick_format = 0;
266477d89b08766c878a2594b15d203e513acf952340wwang	} else {
266577d89b08766c878a2594b15d203e513acf952340wwang		quick_format = 1;
266677d89b08766c878a2594b15d203e513acf952340wwang	}
266777d89b08766c878a2594b15d203e513acf952340wwang
266877d89b08766c878a2594b15d203e513acf952340wwang	if (!(chip->card_ready & MS_CARD)) {
266977d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
267077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
267177d89b08766c878a2594b15d203e513acf952340wwang	}
267277d89b08766c878a2594b15d203e513acf952340wwang
267377d89b08766c878a2594b15d203e513acf952340wwang	if (chip->card_wp & MS_CARD) {
267477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
267577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
267677d89b08766c878a2594b15d203e513acf952340wwang	}
267777d89b08766c878a2594b15d203e513acf952340wwang
267877d89b08766c878a2594b15d203e513acf952340wwang	if (!CHK_MSPRO(ms_card)) {
267977d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
268077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
268177d89b08766c878a2594b15d203e513acf952340wwang	}
268277d89b08766c878a2594b15d203e513acf952340wwang
268377d89b08766c878a2594b15d203e513acf952340wwang	retval = mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format);
268477d89b08766c878a2594b15d203e513acf952340wwang	if (retval != STATUS_SUCCESS) {
268577d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
268677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
268777d89b08766c878a2594b15d203e513acf952340wwang	}
268877d89b08766c878a2594b15d203e513acf952340wwang
268977d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
269077d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
269177d89b08766c878a2594b15d203e513acf952340wwang}
269277d89b08766c878a2594b15d203e513acf952340wwang
269377d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_PCGL_1P18
26946680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip)
269577d89b08766c878a2594b15d203e513acf952340wwang{
269677d89b08766c878a2594b15d203e513acf952340wwang	struct ms_info *ms_card = &(chip->ms_card);
269777d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
269877d89b08766c878a2594b15d203e513acf952340wwang	u8 dev_info_id, data_len;
269977d89b08766c878a2594b15d203e513acf952340wwang	u8 *buf;
270077d89b08766c878a2594b15d203e513acf952340wwang	unsigned int buf_len;
270177d89b08766c878a2594b15d203e513acf952340wwang	int i;
270277d89b08766c878a2594b15d203e513acf952340wwang
270377d89b08766c878a2594b15d203e513acf952340wwang	if (!check_card_ready(chip, lun)) {
270477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
270577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
270677d89b08766c878a2594b15d203e513acf952340wwang	}
270777d89b08766c878a2594b15d203e513acf952340wwang	if ((get_lun_card(chip, lun) != MS_CARD)) {
270877d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
270977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
271077d89b08766c878a2594b15d203e513acf952340wwang	}
271177d89b08766c878a2594b15d203e513acf952340wwang
271277d89b08766c878a2594b15d203e513acf952340wwang	if ((srb->cmnd[2] != 0xB0) || (srb->cmnd[4] != 0x4D) ||
271377d89b08766c878a2594b15d203e513acf952340wwang		(srb->cmnd[5] != 0x53) || (srb->cmnd[6] != 0x49) ||
271477d89b08766c878a2594b15d203e513acf952340wwang		(srb->cmnd[7] != 0x44)) {
271577d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
271677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
271777d89b08766c878a2594b15d203e513acf952340wwang	}
271877d89b08766c878a2594b15d203e513acf952340wwang
271977d89b08766c878a2594b15d203e513acf952340wwang	dev_info_id = srb->cmnd[3];
272077d89b08766c878a2594b15d203e513acf952340wwang	if ((CHK_MSXC(ms_card) && (dev_info_id == 0x10)) ||
272177d89b08766c878a2594b15d203e513acf952340wwang			(!CHK_MSXC(ms_card) && (dev_info_id == 0x13)) ||
272277d89b08766c878a2594b15d203e513acf952340wwang			!CHK_MSPRO(ms_card)) {
272377d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
272477d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
272577d89b08766c878a2594b15d203e513acf952340wwang	}
272677d89b08766c878a2594b15d203e513acf952340wwang
272777d89b08766c878a2594b15d203e513acf952340wwang	if (dev_info_id == 0x15) {
272877d89b08766c878a2594b15d203e513acf952340wwang		buf_len = data_len = 0x3A;
272977d89b08766c878a2594b15d203e513acf952340wwang	} else {
273077d89b08766c878a2594b15d203e513acf952340wwang		buf_len = data_len = 0x6A;
273177d89b08766c878a2594b15d203e513acf952340wwang	}
273277d89b08766c878a2594b15d203e513acf952340wwang
2733a5232bde8449b28230f767e8b558021bb5d08e5cThomas Meyer	buf = kmalloc(buf_len, GFP_KERNEL);
273477d89b08766c878a2594b15d203e513acf952340wwang	if (!buf) {
273577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_ERROR);
273677d89b08766c878a2594b15d203e513acf952340wwang	}
273777d89b08766c878a2594b15d203e513acf952340wwang
273877d89b08766c878a2594b15d203e513acf952340wwang	i = 0;
273977d89b08766c878a2594b15d203e513acf952340wwang	/*  GET Memory Stick Media Information Response Header */
274077d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = 0x00;		/* Data length MSB */
274177d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = data_len; 		/* Data length LSB */
274277d89b08766c878a2594b15d203e513acf952340wwang	/* Device Information Type Code */
274377d89b08766c878a2594b15d203e513acf952340wwang	if (CHK_MSXC(ms_card)) {
274477d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x03;
274577d89b08766c878a2594b15d203e513acf952340wwang	} else {
274677d89b08766c878a2594b15d203e513acf952340wwang		buf[i++] = 0x02;
274777d89b08766c878a2594b15d203e513acf952340wwang	}
274877d89b08766c878a2594b15d203e513acf952340wwang	/* SGM bit */
274977d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = 0x01;
275077d89b08766c878a2594b15d203e513acf952340wwang	/* Reserved */
275177d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = 0x00;
275277d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = 0x00;
275377d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = 0x00;
275477d89b08766c878a2594b15d203e513acf952340wwang	/* Number of Device Information */
275577d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = 0x01;
275677d89b08766c878a2594b15d203e513acf952340wwang
275777d89b08766c878a2594b15d203e513acf952340wwang	/*  Device Information Body */
275877d89b08766c878a2594b15d203e513acf952340wwang
275977d89b08766c878a2594b15d203e513acf952340wwang	/* Device Information ID Number */
276077d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = dev_info_id;
276177d89b08766c878a2594b15d203e513acf952340wwang	/* Device Information Length */
276277d89b08766c878a2594b15d203e513acf952340wwang	if (dev_info_id == 0x15) {
276377d89b08766c878a2594b15d203e513acf952340wwang		data_len = 0x31;
276477d89b08766c878a2594b15d203e513acf952340wwang	} else {
276577d89b08766c878a2594b15d203e513acf952340wwang		data_len = 0x61;
276677d89b08766c878a2594b15d203e513acf952340wwang	}
276777d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = 0x00;		/* Data length MSB */
276877d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = data_len; 		/* Data length LSB */
276977d89b08766c878a2594b15d203e513acf952340wwang	/* Valid Bit */
277077d89b08766c878a2594b15d203e513acf952340wwang	buf[i++] = 0x80;
277177d89b08766c878a2594b15d203e513acf952340wwang	if ((dev_info_id == 0x10) || (dev_info_id == 0x13)) {
277277d89b08766c878a2594b15d203e513acf952340wwang		/* System Information */
277377d89b08766c878a2594b15d203e513acf952340wwang		memcpy(buf+i, ms_card->raw_sys_info, 96);
277477d89b08766c878a2594b15d203e513acf952340wwang	} else {
277577d89b08766c878a2594b15d203e513acf952340wwang		/* Model Name */
277677d89b08766c878a2594b15d203e513acf952340wwang		memcpy(buf+i, ms_card->raw_model_name, 48);
277777d89b08766c878a2594b15d203e513acf952340wwang	}
277877d89b08766c878a2594b15d203e513acf952340wwang
277977d89b08766c878a2594b15d203e513acf952340wwang	rtsx_stor_set_xfer_buf(buf, buf_len, srb);
278077d89b08766c878a2594b15d203e513acf952340wwang
278177d89b08766c878a2594b15d203e513acf952340wwang	if (dev_info_id == 0x15) {
278277d89b08766c878a2594b15d203e513acf952340wwang		scsi_set_resid(srb, scsi_bufflen(srb)-0x3C);
278377d89b08766c878a2594b15d203e513acf952340wwang	} else {
278477d89b08766c878a2594b15d203e513acf952340wwang		scsi_set_resid(srb, scsi_bufflen(srb)-0x6C);
278577d89b08766c878a2594b15d203e513acf952340wwang	}
278677d89b08766c878a2594b15d203e513acf952340wwang
278777d89b08766c878a2594b15d203e513acf952340wwang	kfree(buf);
278877d89b08766c878a2594b15d203e513acf952340wwang	return STATUS_SUCCESS;
278977d89b08766c878a2594b15d203e513acf952340wwang}
279077d89b08766c878a2594b15d203e513acf952340wwang#endif
279177d89b08766c878a2594b15d203e513acf952340wwang
279277d89b08766c878a2594b15d203e513acf952340wwangstatic int ms_sp_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
279377d89b08766c878a2594b15d203e513acf952340wwang{
279477d89b08766c878a2594b15d203e513acf952340wwang	int retval = TRANSPORT_ERROR;
279577d89b08766c878a2594b15d203e513acf952340wwang
279677d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[2] == MS_FORMAT) {
279777d89b08766c878a2594b15d203e513acf952340wwang		retval = ms_format_cmnd(srb, chip);
279877d89b08766c878a2594b15d203e513acf952340wwang	}
279977d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_PCGL_1P18
280077d89b08766c878a2594b15d203e513acf952340wwang	else if (srb->cmnd[2] == GET_MS_INFORMATION) {
280177d89b08766c878a2594b15d203e513acf952340wwang		retval = get_ms_information(srb, chip);
280277d89b08766c878a2594b15d203e513acf952340wwang	}
280377d89b08766c878a2594b15d203e513acf952340wwang#endif
280477d89b08766c878a2594b15d203e513acf952340wwang
280577d89b08766c878a2594b15d203e513acf952340wwang	return retval;
280677d89b08766c878a2594b15d203e513acf952340wwang}
280777d89b08766c878a2594b15d203e513acf952340wwang
280877d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_CPRM
280977d89b08766c878a2594b15d203e513acf952340wwangstatic int sd_extention_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
281077d89b08766c878a2594b15d203e513acf952340wwang{
281177d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
281277d89b08766c878a2594b15d203e513acf952340wwang	int result;
281377d89b08766c878a2594b15d203e513acf952340wwang
281477d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
281577d89b08766c878a2594b15d203e513acf952340wwang
281677d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
281777d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
281877d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
281977d89b08766c878a2594b15d203e513acf952340wwang	}
282077d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
282177d89b08766c878a2594b15d203e513acf952340wwang
282277d89b08766c878a2594b15d203e513acf952340wwang	sd_cleanup_work(chip);
282377d89b08766c878a2594b15d203e513acf952340wwang
282477d89b08766c878a2594b15d203e513acf952340wwang	if (!check_card_ready(chip, lun)) {
282577d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
282677d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
282777d89b08766c878a2594b15d203e513acf952340wwang	}
282877d89b08766c878a2594b15d203e513acf952340wwang	if ((get_lun_card(chip, lun) != SD_CARD)) {
282977d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
283077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
283177d89b08766c878a2594b15d203e513acf952340wwang	}
283277d89b08766c878a2594b15d203e513acf952340wwang
283377d89b08766c878a2594b15d203e513acf952340wwang	switch (srb->cmnd[0]) {
283477d89b08766c878a2594b15d203e513acf952340wwang	case SD_PASS_THRU_MODE:
283577d89b08766c878a2594b15d203e513acf952340wwang		result = sd_pass_thru_mode(srb, chip);
283677d89b08766c878a2594b15d203e513acf952340wwang		break;
283777d89b08766c878a2594b15d203e513acf952340wwang
283877d89b08766c878a2594b15d203e513acf952340wwang	case SD_EXECUTE_NO_DATA:
283977d89b08766c878a2594b15d203e513acf952340wwang		result = sd_execute_no_data(srb, chip);
284077d89b08766c878a2594b15d203e513acf952340wwang		break;
284177d89b08766c878a2594b15d203e513acf952340wwang
284277d89b08766c878a2594b15d203e513acf952340wwang	case SD_EXECUTE_READ:
284377d89b08766c878a2594b15d203e513acf952340wwang		result = sd_execute_read_data(srb, chip);
284477d89b08766c878a2594b15d203e513acf952340wwang		break;
284577d89b08766c878a2594b15d203e513acf952340wwang
284677d89b08766c878a2594b15d203e513acf952340wwang	case SD_EXECUTE_WRITE:
284777d89b08766c878a2594b15d203e513acf952340wwang		result = sd_execute_write_data(srb, chip);
284877d89b08766c878a2594b15d203e513acf952340wwang		break;
284977d89b08766c878a2594b15d203e513acf952340wwang
285077d89b08766c878a2594b15d203e513acf952340wwang	case SD_GET_RSP:
285177d89b08766c878a2594b15d203e513acf952340wwang		result = sd_get_cmd_rsp(srb, chip);
285277d89b08766c878a2594b15d203e513acf952340wwang		break;
285377d89b08766c878a2594b15d203e513acf952340wwang
285477d89b08766c878a2594b15d203e513acf952340wwang	case SD_HW_RST:
285577d89b08766c878a2594b15d203e513acf952340wwang		result = sd_hw_rst(srb, chip);
285677d89b08766c878a2594b15d203e513acf952340wwang		break;
285777d89b08766c878a2594b15d203e513acf952340wwang
285877d89b08766c878a2594b15d203e513acf952340wwang	default:
285977d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
286077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
286177d89b08766c878a2594b15d203e513acf952340wwang	}
286277d89b08766c878a2594b15d203e513acf952340wwang
286377d89b08766c878a2594b15d203e513acf952340wwang	return result;
286477d89b08766c878a2594b15d203e513acf952340wwang}
286577d89b08766c878a2594b15d203e513acf952340wwang#endif
286677d89b08766c878a2594b15d203e513acf952340wwang
286777d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_MAGIC_GATE
28686680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
286977d89b08766c878a2594b15d203e513acf952340wwang{
287077d89b08766c878a2594b15d203e513acf952340wwang	struct ms_info *ms_card = &(chip->ms_card);
287177d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
287277d89b08766c878a2594b15d203e513acf952340wwang	int retval;
287377d89b08766c878a2594b15d203e513acf952340wwang	u8 key_format;
287477d89b08766c878a2594b15d203e513acf952340wwang
287577d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("--%s--\n", __func__);
287677d89b08766c878a2594b15d203e513acf952340wwang
287777d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
287877d89b08766c878a2594b15d203e513acf952340wwang
287977d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
288077d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
288177d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
288277d89b08766c878a2594b15d203e513acf952340wwang	}
288377d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
288477d89b08766c878a2594b15d203e513acf952340wwang
288577d89b08766c878a2594b15d203e513acf952340wwang	ms_cleanup_work(chip);
288677d89b08766c878a2594b15d203e513acf952340wwang
288777d89b08766c878a2594b15d203e513acf952340wwang	if (!check_card_ready(chip, lun)) {
288877d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
288977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
289077d89b08766c878a2594b15d203e513acf952340wwang	}
289177d89b08766c878a2594b15d203e513acf952340wwang	if ((get_lun_card(chip, lun) != MS_CARD)) {
289277d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
289377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
289477d89b08766c878a2594b15d203e513acf952340wwang	}
289577d89b08766c878a2594b15d203e513acf952340wwang
289677d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[7] != KC_MG_R_PRO) {
289777d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
289877d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
289977d89b08766c878a2594b15d203e513acf952340wwang	}
290077d89b08766c878a2594b15d203e513acf952340wwang
290177d89b08766c878a2594b15d203e513acf952340wwang	if (!CHK_MSPRO(ms_card)) {
290277d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
290377d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
290477d89b08766c878a2594b15d203e513acf952340wwang	}
290577d89b08766c878a2594b15d203e513acf952340wwang
290677d89b08766c878a2594b15d203e513acf952340wwang	key_format = srb->cmnd[10] & 0x3F;
290777d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("key_format = 0x%x\n", key_format);
290877d89b08766c878a2594b15d203e513acf952340wwang
290977d89b08766c878a2594b15d203e513acf952340wwang	switch (key_format) {
291077d89b08766c878a2594b15d203e513acf952340wwang	case KF_GET_LOC_EKB:
291177d89b08766c878a2594b15d203e513acf952340wwang		if ((scsi_bufflen(srb) == 0x41C) &&
291277d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[8] == 0x04) &&
291377d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[9] == 0x1C)) {
291477d89b08766c878a2594b15d203e513acf952340wwang			retval = mg_get_local_EKB(srb, chip);
291577d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
291677d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
291777d89b08766c878a2594b15d203e513acf952340wwang			}
291877d89b08766c878a2594b15d203e513acf952340wwang		} else {
291977d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
292077d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
292177d89b08766c878a2594b15d203e513acf952340wwang		}
292277d89b08766c878a2594b15d203e513acf952340wwang		break;
292377d89b08766c878a2594b15d203e513acf952340wwang
292477d89b08766c878a2594b15d203e513acf952340wwang	case KF_RSP_CHG:
292577d89b08766c878a2594b15d203e513acf952340wwang		if ((scsi_bufflen(srb) == 0x24) &&
292677d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[8] == 0x00) &&
292777d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[9] == 0x24)) {
292877d89b08766c878a2594b15d203e513acf952340wwang			retval = mg_get_rsp_chg(srb, chip);
292977d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
293077d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
293177d89b08766c878a2594b15d203e513acf952340wwang			}
293277d89b08766c878a2594b15d203e513acf952340wwang		} else {
293377d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
293477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
293577d89b08766c878a2594b15d203e513acf952340wwang		}
293677d89b08766c878a2594b15d203e513acf952340wwang		break;
293777d89b08766c878a2594b15d203e513acf952340wwang
293877d89b08766c878a2594b15d203e513acf952340wwang	case KF_GET_ICV:
293977d89b08766c878a2594b15d203e513acf952340wwang		ms_card->mg_entry_num = srb->cmnd[5];
294077d89b08766c878a2594b15d203e513acf952340wwang		if ((scsi_bufflen(srb) == 0x404) &&
294177d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[8] == 0x04) &&
294277d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[9] == 0x04) &&
294377d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[2] == 0x00) &&
294477d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[3] == 0x00) &&
294577d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[4] == 0x00) &&
294677d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[5] < 32)) {
294777d89b08766c878a2594b15d203e513acf952340wwang			retval = mg_get_ICV(srb, chip);
294877d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
294977d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
295077d89b08766c878a2594b15d203e513acf952340wwang			}
295177d89b08766c878a2594b15d203e513acf952340wwang		} else {
295277d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
295377d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
295477d89b08766c878a2594b15d203e513acf952340wwang		}
295577d89b08766c878a2594b15d203e513acf952340wwang		break;
295677d89b08766c878a2594b15d203e513acf952340wwang
295777d89b08766c878a2594b15d203e513acf952340wwang	default:
295877d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
295977d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
296077d89b08766c878a2594b15d203e513acf952340wwang	}
296177d89b08766c878a2594b15d203e513acf952340wwang
296277d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
296377d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
296477d89b08766c878a2594b15d203e513acf952340wwang}
296577d89b08766c878a2594b15d203e513acf952340wwang
29666680d2cab316a0c0e4cea0727e6d63426a77bb12wwangstatic int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
296777d89b08766c878a2594b15d203e513acf952340wwang{
296877d89b08766c878a2594b15d203e513acf952340wwang	struct ms_info *ms_card = &(chip->ms_card);
296977d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
297077d89b08766c878a2594b15d203e513acf952340wwang	int retval;
297177d89b08766c878a2594b15d203e513acf952340wwang	u8 key_format;
297277d89b08766c878a2594b15d203e513acf952340wwang
297377d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("--%s--\n", __func__);
297477d89b08766c878a2594b15d203e513acf952340wwang
297577d89b08766c878a2594b15d203e513acf952340wwang	rtsx_disable_aspm(chip);
297677d89b08766c878a2594b15d203e513acf952340wwang
297777d89b08766c878a2594b15d203e513acf952340wwang	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
297877d89b08766c878a2594b15d203e513acf952340wwang		rtsx_exit_ss(chip);
297977d89b08766c878a2594b15d203e513acf952340wwang		wait_timeout(100);
298077d89b08766c878a2594b15d203e513acf952340wwang	}
298177d89b08766c878a2594b15d203e513acf952340wwang	rtsx_set_stat(chip, RTSX_STAT_RUN);
298277d89b08766c878a2594b15d203e513acf952340wwang
298377d89b08766c878a2594b15d203e513acf952340wwang	ms_cleanup_work(chip);
298477d89b08766c878a2594b15d203e513acf952340wwang
298577d89b08766c878a2594b15d203e513acf952340wwang	if (!check_card_ready(chip, lun)) {
298677d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
298777d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
298877d89b08766c878a2594b15d203e513acf952340wwang	}
298977d89b08766c878a2594b15d203e513acf952340wwang	if (check_card_wp(chip, lun)) {
299077d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
299177d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
299277d89b08766c878a2594b15d203e513acf952340wwang	}
299377d89b08766c878a2594b15d203e513acf952340wwang	if ((get_lun_card(chip, lun) != MS_CARD)) {
299477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
299577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
299677d89b08766c878a2594b15d203e513acf952340wwang	}
299777d89b08766c878a2594b15d203e513acf952340wwang
299877d89b08766c878a2594b15d203e513acf952340wwang	if (srb->cmnd[7] != KC_MG_R_PRO) {
299977d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
300077d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
300177d89b08766c878a2594b15d203e513acf952340wwang	}
300277d89b08766c878a2594b15d203e513acf952340wwang
300377d89b08766c878a2594b15d203e513acf952340wwang	if (!CHK_MSPRO(ms_card)) {
300477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
300577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
300677d89b08766c878a2594b15d203e513acf952340wwang	}
300777d89b08766c878a2594b15d203e513acf952340wwang
300877d89b08766c878a2594b15d203e513acf952340wwang	key_format = srb->cmnd[10] & 0x3F;
300977d89b08766c878a2594b15d203e513acf952340wwang	RTSX_DEBUGP("key_format = 0x%x\n", key_format);
301077d89b08766c878a2594b15d203e513acf952340wwang
301177d89b08766c878a2594b15d203e513acf952340wwang	switch (key_format) {
301277d89b08766c878a2594b15d203e513acf952340wwang	case KF_SET_LEAF_ID:
301377d89b08766c878a2594b15d203e513acf952340wwang		if ((scsi_bufflen(srb) == 0x0C) &&
301477d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[8] == 0x00) &&
301577d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[9] == 0x0C)) {
301677d89b08766c878a2594b15d203e513acf952340wwang			retval = mg_set_leaf_id(srb, chip);
301777d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
301877d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
301977d89b08766c878a2594b15d203e513acf952340wwang			}
302077d89b08766c878a2594b15d203e513acf952340wwang		} else {
302177d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
302277d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
302377d89b08766c878a2594b15d203e513acf952340wwang		}
302477d89b08766c878a2594b15d203e513acf952340wwang		break;
302577d89b08766c878a2594b15d203e513acf952340wwang
302677d89b08766c878a2594b15d203e513acf952340wwang	case KF_CHG_HOST:
302777d89b08766c878a2594b15d203e513acf952340wwang		if ((scsi_bufflen(srb) == 0x0C) &&
302877d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[8] == 0x00) &&
302977d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[9] == 0x0C)) {
303077d89b08766c878a2594b15d203e513acf952340wwang			retval = mg_chg(srb, chip);
303177d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
303277d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
303377d89b08766c878a2594b15d203e513acf952340wwang			}
303477d89b08766c878a2594b15d203e513acf952340wwang		} else {
303577d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
303677d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
303777d89b08766c878a2594b15d203e513acf952340wwang		}
303877d89b08766c878a2594b15d203e513acf952340wwang		break;
303977d89b08766c878a2594b15d203e513acf952340wwang
304077d89b08766c878a2594b15d203e513acf952340wwang	case KF_RSP_HOST:
304177d89b08766c878a2594b15d203e513acf952340wwang		if ((scsi_bufflen(srb) == 0x0C) &&
304277d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[8] == 0x00) &&
304377d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[9] == 0x0C)) {
304477d89b08766c878a2594b15d203e513acf952340wwang			retval = mg_rsp(srb, chip);
304577d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
304677d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
304777d89b08766c878a2594b15d203e513acf952340wwang			}
304877d89b08766c878a2594b15d203e513acf952340wwang		} else {
304977d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
305077d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
305177d89b08766c878a2594b15d203e513acf952340wwang		}
305277d89b08766c878a2594b15d203e513acf952340wwang		break;
305377d89b08766c878a2594b15d203e513acf952340wwang
305477d89b08766c878a2594b15d203e513acf952340wwang	case KF_SET_ICV:
305577d89b08766c878a2594b15d203e513acf952340wwang		ms_card->mg_entry_num = srb->cmnd[5];
305677d89b08766c878a2594b15d203e513acf952340wwang		if ((scsi_bufflen(srb) == 0x404) &&
305777d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[8] == 0x04) &&
305877d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[9] == 0x04) &&
305977d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[2] == 0x00) &&
306077d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[3] == 0x00) &&
306177d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[4] == 0x00) &&
306277d89b08766c878a2594b15d203e513acf952340wwang			(srb->cmnd[5] < 32)) {
306377d89b08766c878a2594b15d203e513acf952340wwang			retval = mg_set_ICV(srb, chip);
306477d89b08766c878a2594b15d203e513acf952340wwang			if (retval != STATUS_SUCCESS) {
306577d89b08766c878a2594b15d203e513acf952340wwang				TRACE_RET(chip, TRANSPORT_FAILED);
306677d89b08766c878a2594b15d203e513acf952340wwang			}
306777d89b08766c878a2594b15d203e513acf952340wwang		} else {
306877d89b08766c878a2594b15d203e513acf952340wwang			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
306977d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
307077d89b08766c878a2594b15d203e513acf952340wwang		}
307177d89b08766c878a2594b15d203e513acf952340wwang		break;
307277d89b08766c878a2594b15d203e513acf952340wwang
307377d89b08766c878a2594b15d203e513acf952340wwang	default:
307477d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
307577d89b08766c878a2594b15d203e513acf952340wwang		TRACE_RET(chip, TRANSPORT_FAILED);
307677d89b08766c878a2594b15d203e513acf952340wwang	}
307777d89b08766c878a2594b15d203e513acf952340wwang
307877d89b08766c878a2594b15d203e513acf952340wwang	scsi_set_resid(srb, 0);
307977d89b08766c878a2594b15d203e513acf952340wwang	return TRANSPORT_GOOD;
308077d89b08766c878a2594b15d203e513acf952340wwang}
308177d89b08766c878a2594b15d203e513acf952340wwang#endif
308277d89b08766c878a2594b15d203e513acf952340wwang
308377d89b08766c878a2594b15d203e513acf952340wwangint rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip)
308477d89b08766c878a2594b15d203e513acf952340wwang{
308577d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
308677d89b08766c878a2594b15d203e513acf952340wwang	struct sd_info *sd_card = &(chip->sd_card);
308777d89b08766c878a2594b15d203e513acf952340wwang#endif
308877d89b08766c878a2594b15d203e513acf952340wwang	struct ms_info *ms_card = &(chip->ms_card);
308977d89b08766c878a2594b15d203e513acf952340wwang	unsigned int lun = SCSI_LUN(srb);
309077d89b08766c878a2594b15d203e513acf952340wwang	int result;
309177d89b08766c878a2594b15d203e513acf952340wwang
309277d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_SD_LOCK
309377d89b08766c878a2594b15d203e513acf952340wwang	if (sd_card->sd_erase_status) {
309477d89b08766c878a2594b15d203e513acf952340wwang		/* Block all SCSI command except for
309577d89b08766c878a2594b15d203e513acf952340wwang		 * REQUEST_SENSE and rs_ppstatus
309677d89b08766c878a2594b15d203e513acf952340wwang		 */
309777d89b08766c878a2594b15d203e513acf952340wwang		if (!((srb->cmnd[0] == VENDOR_CMND) &&
309877d89b08766c878a2594b15d203e513acf952340wwang				(srb->cmnd[1] == SCSI_APP_CMD) &&
309977d89b08766c878a2594b15d203e513acf952340wwang				(srb->cmnd[2] == GET_DEV_STATUS)) &&
310077d89b08766c878a2594b15d203e513acf952340wwang				(srb->cmnd[0] != REQUEST_SENSE)) {
310177d89b08766c878a2594b15d203e513acf952340wwang			/* Logical Unit Not Ready Format in Progress */
310277d89b08766c878a2594b15d203e513acf952340wwang			set_sense_data(chip, lun, CUR_ERR,
310377d89b08766c878a2594b15d203e513acf952340wwang				       0x02, 0, 0x04, 0x04, 0, 0);
310477d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
310577d89b08766c878a2594b15d203e513acf952340wwang		}
310677d89b08766c878a2594b15d203e513acf952340wwang	}
310777d89b08766c878a2594b15d203e513acf952340wwang#endif
310877d89b08766c878a2594b15d203e513acf952340wwang
310977d89b08766c878a2594b15d203e513acf952340wwang	if ((get_lun_card(chip, lun) == MS_CARD) &&
311077d89b08766c878a2594b15d203e513acf952340wwang			(ms_card->format_status == FORMAT_IN_PROGRESS)) {
311177d89b08766c878a2594b15d203e513acf952340wwang		if ((srb->cmnd[0] != REQUEST_SENSE) && (srb->cmnd[0] != INQUIRY)) {
311277d89b08766c878a2594b15d203e513acf952340wwang			/* Logical Unit Not Ready Format in Progress */
311377d89b08766c878a2594b15d203e513acf952340wwang			set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
311477d89b08766c878a2594b15d203e513acf952340wwang					0, (u16)(ms_card->progress));
311577d89b08766c878a2594b15d203e513acf952340wwang			TRACE_RET(chip, TRANSPORT_FAILED);
311677d89b08766c878a2594b15d203e513acf952340wwang		}
311777d89b08766c878a2594b15d203e513acf952340wwang	}
311877d89b08766c878a2594b15d203e513acf952340wwang
311977d89b08766c878a2594b15d203e513acf952340wwang	switch (srb->cmnd[0]) {
312077d89b08766c878a2594b15d203e513acf952340wwang	case READ_10:
312177d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_10:
312277d89b08766c878a2594b15d203e513acf952340wwang	case READ_6:
312377d89b08766c878a2594b15d203e513acf952340wwang	case WRITE_6:
312477d89b08766c878a2594b15d203e513acf952340wwang		result = read_write(srb, chip);
312577d89b08766c878a2594b15d203e513acf952340wwang#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK)
312677d89b08766c878a2594b15d203e513acf952340wwang		led_shine(srb, chip);
312777d89b08766c878a2594b15d203e513acf952340wwang#endif
312877d89b08766c878a2594b15d203e513acf952340wwang		break;
312977d89b08766c878a2594b15d203e513acf952340wwang
313077d89b08766c878a2594b15d203e513acf952340wwang	case TEST_UNIT_READY:
313177d89b08766c878a2594b15d203e513acf952340wwang		result = test_unit_ready(srb, chip);
313277d89b08766c878a2594b15d203e513acf952340wwang		break;
313377d89b08766c878a2594b15d203e513acf952340wwang
313477d89b08766c878a2594b15d203e513acf952340wwang	case INQUIRY:
313577d89b08766c878a2594b15d203e513acf952340wwang		result = inquiry(srb, chip);
313677d89b08766c878a2594b15d203e513acf952340wwang		break;
313777d89b08766c878a2594b15d203e513acf952340wwang
313877d89b08766c878a2594b15d203e513acf952340wwang	case READ_CAPACITY:
313977d89b08766c878a2594b15d203e513acf952340wwang		result = read_capacity(srb, chip);
314077d89b08766c878a2594b15d203e513acf952340wwang		break;
314177d89b08766c878a2594b15d203e513acf952340wwang
314277d89b08766c878a2594b15d203e513acf952340wwang	case START_STOP:
314377d89b08766c878a2594b15d203e513acf952340wwang		result = start_stop_unit(srb, chip);
314477d89b08766c878a2594b15d203e513acf952340wwang		break;
314577d89b08766c878a2594b15d203e513acf952340wwang
314677d89b08766c878a2594b15d203e513acf952340wwang	case ALLOW_MEDIUM_REMOVAL:
314777d89b08766c878a2594b15d203e513acf952340wwang		result = allow_medium_removal(srb, chip);
314877d89b08766c878a2594b15d203e513acf952340wwang		break;
314977d89b08766c878a2594b15d203e513acf952340wwang
315077d89b08766c878a2594b15d203e513acf952340wwang	case REQUEST_SENSE:
315177d89b08766c878a2594b15d203e513acf952340wwang		result = request_sense(srb, chip);
315277d89b08766c878a2594b15d203e513acf952340wwang		break;
315377d89b08766c878a2594b15d203e513acf952340wwang
315477d89b08766c878a2594b15d203e513acf952340wwang	case MODE_SENSE:
315577d89b08766c878a2594b15d203e513acf952340wwang	case MODE_SENSE_10:
315677d89b08766c878a2594b15d203e513acf952340wwang		result = mode_sense(srb, chip);
315777d89b08766c878a2594b15d203e513acf952340wwang		break;
315877d89b08766c878a2594b15d203e513acf952340wwang
315977d89b08766c878a2594b15d203e513acf952340wwang	case 0x23:
316077d89b08766c878a2594b15d203e513acf952340wwang		result = read_format_capacity(srb, chip);
316177d89b08766c878a2594b15d203e513acf952340wwang		break;
316277d89b08766c878a2594b15d203e513acf952340wwang
316377d89b08766c878a2594b15d203e513acf952340wwang	case VENDOR_CMND:
316477d89b08766c878a2594b15d203e513acf952340wwang		result = vendor_cmnd(srb, chip);
316577d89b08766c878a2594b15d203e513acf952340wwang		break;
316677d89b08766c878a2594b15d203e513acf952340wwang
316777d89b08766c878a2594b15d203e513acf952340wwang	case MS_SP_CMND:
316877d89b08766c878a2594b15d203e513acf952340wwang		result = ms_sp_cmnd(srb, chip);
316977d89b08766c878a2594b15d203e513acf952340wwang		break;
317077d89b08766c878a2594b15d203e513acf952340wwang
317177d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_CPRM
317277d89b08766c878a2594b15d203e513acf952340wwang	case SD_PASS_THRU_MODE:
317377d89b08766c878a2594b15d203e513acf952340wwang	case SD_EXECUTE_NO_DATA:
317477d89b08766c878a2594b15d203e513acf952340wwang	case SD_EXECUTE_READ:
317577d89b08766c878a2594b15d203e513acf952340wwang	case SD_EXECUTE_WRITE:
317677d89b08766c878a2594b15d203e513acf952340wwang	case SD_GET_RSP:
317777d89b08766c878a2594b15d203e513acf952340wwang	case SD_HW_RST:
317877d89b08766c878a2594b15d203e513acf952340wwang		result = sd_extention_cmnd(srb, chip);
317977d89b08766c878a2594b15d203e513acf952340wwang		break;
318077d89b08766c878a2594b15d203e513acf952340wwang#endif
318177d89b08766c878a2594b15d203e513acf952340wwang
318277d89b08766c878a2594b15d203e513acf952340wwang#ifdef SUPPORT_MAGIC_GATE
318377d89b08766c878a2594b15d203e513acf952340wwang	case CMD_MSPRO_MG_RKEY:
318477d89b08766c878a2594b15d203e513acf952340wwang		result = mg_report_key(srb, chip);
318577d89b08766c878a2594b15d203e513acf952340wwang		break;
318677d89b08766c878a2594b15d203e513acf952340wwang
318777d89b08766c878a2594b15d203e513acf952340wwang	case CMD_MSPRO_MG_SKEY:
318877d89b08766c878a2594b15d203e513acf952340wwang		result = mg_send_key(srb, chip);
318977d89b08766c878a2594b15d203e513acf952340wwang		break;
319077d89b08766c878a2594b15d203e513acf952340wwang#endif
319177d89b08766c878a2594b15d203e513acf952340wwang
319277d89b08766c878a2594b15d203e513acf952340wwang	case FORMAT_UNIT:
319377d89b08766c878a2594b15d203e513acf952340wwang	case MODE_SELECT:
319477d89b08766c878a2594b15d203e513acf952340wwang	case VERIFY:
319577d89b08766c878a2594b15d203e513acf952340wwang		result = TRANSPORT_GOOD;
319677d89b08766c878a2594b15d203e513acf952340wwang		break;
319777d89b08766c878a2594b15d203e513acf952340wwang
319877d89b08766c878a2594b15d203e513acf952340wwang	default:
319977d89b08766c878a2594b15d203e513acf952340wwang		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
320077d89b08766c878a2594b15d203e513acf952340wwang		result = TRANSPORT_FAILED;
320177d89b08766c878a2594b15d203e513acf952340wwang	}
320277d89b08766c878a2594b15d203e513acf952340wwang
320377d89b08766c878a2594b15d203e513acf952340wwang	return result;
320477d89b08766c878a2594b15d203e513acf952340wwang}
3205