Release 4.7 drivers/staging/rts5208/rtsx_scsi.c
  
  
/* Driver for Realtek PCI-Express card reader
 *
 * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, see <http://www.gnu.org/licenses/>.
 *
 * Author:
 *   Wei WANG (wei_wang@realsil.com.cn)
 *   Micky Ching (micky_ching@realsil.com.cn)
 */
#include <linux/blkdev.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
#include "rtsx.h"
#include "sd.h"
#include "ms.h"
#include "spi.h"
void scsi_show_command(struct rtsx_chip *chip)
{
	struct scsi_cmnd *srb = chip->srb;
	char *what = NULL;
	bool unknown_cmd = false;
	int len;
	switch (srb->cmnd[0]) {
	case TEST_UNIT_READY:
		what = "TEST_UNIT_READY";
		break;
	case REZERO_UNIT:
		what = "REZERO_UNIT";
		break;
	case REQUEST_SENSE:
		what = "REQUEST_SENSE";
		break;
	case FORMAT_UNIT:
		what = "FORMAT_UNIT";
		break;
	case READ_BLOCK_LIMITS:
		what = "READ_BLOCK_LIMITS";
		break;
	case REASSIGN_BLOCKS:
		what = "REASSIGN_BLOCKS";
		break;
	case READ_6:
		what = "READ_6";
		break;
	case WRITE_6:
		what = "WRITE_6";
		break;
	case SEEK_6:
		what = "SEEK_6";
		break;
	case READ_REVERSE:
		what = "READ_REVERSE";
		break;
	case WRITE_FILEMARKS:
		what = "WRITE_FILEMARKS";
		break;
	case SPACE:
		what = "SPACE";
		break;
	case INQUIRY:
		what = "INQUIRY";
		break;
	case RECOVER_BUFFERED_DATA:
		what = "RECOVER_BUFFERED_DATA";
		break;
	case MODE_SELECT:
		what = "MODE_SELECT";
		break;
	case RESERVE:
		what = "RESERVE";
		break;
	case RELEASE:
		what = "RELEASE";
		break;
	case COPY:
		what = "COPY";
		break;
	case ERASE:
		what = "ERASE";
		break;
	case MODE_SENSE:
		what = "MODE_SENSE";
		break;
	case START_STOP:
		what = "START_STOP";
		break;
	case RECEIVE_DIAGNOSTIC:
		what = "RECEIVE_DIAGNOSTIC";
		break;
	case SEND_DIAGNOSTIC:
		what = "SEND_DIAGNOSTIC";
		break;
	case ALLOW_MEDIUM_REMOVAL:
		what = "ALLOW_MEDIUM_REMOVAL";
		break;
	case SET_WINDOW:
		what = "SET_WINDOW";
		break;
	case READ_CAPACITY:
		what = "READ_CAPACITY";
		break;
	case READ_10:
		what = "READ_10";
		break;
	case WRITE_10:
		what = "WRITE_10";
		break;
	case SEEK_10:
		what = "SEEK_10";
		break;
	case WRITE_VERIFY:
		what = "WRITE_VERIFY";
		break;
	case VERIFY:
		what = "VERIFY";
		break;
	case SEARCH_HIGH:
		what = "SEARCH_HIGH";
		break;
	case SEARCH_EQUAL:
		what = "SEARCH_EQUAL";
		break;
	case SEARCH_LOW:
		what = "SEARCH_LOW";
		break;
	case SET_LIMITS:
		what = "SET_LIMITS";
		break;
	case READ_POSITION:
		what = "READ_POSITION";
		break;
	case SYNCHRONIZE_CACHE:
		what = "SYNCHRONIZE_CACHE";
		break;
	case LOCK_UNLOCK_CACHE:
		what = "LOCK_UNLOCK_CACHE";
		break;
	case READ_DEFECT_DATA:
		what = "READ_DEFECT_DATA";
		break;
	case MEDIUM_SCAN:
		what = "MEDIUM_SCAN";
		break;
	case COMPARE:
		what = "COMPARE";
		break;
	case COPY_VERIFY:
		what = "COPY_VERIFY";
		break;
	case WRITE_BUFFER:
		what = "WRITE_BUFFER";
		break;
	case READ_BUFFER:
		what = "READ_BUFFER";
		break;
	case UPDATE_BLOCK:
		what = "UPDATE_BLOCK";
		break;
	case READ_LONG:
		what = "READ_LONG";
		break;
	case WRITE_LONG:
		what = "WRITE_LONG";
		break;
	case CHANGE_DEFINITION:
		what = "CHANGE_DEFINITION";
		break;
	case WRITE_SAME:
		what = "WRITE_SAME";
		break;
	case GPCMD_READ_SUBCHANNEL:
		what = "READ SUBCHANNEL";
		break;
	case READ_TOC:
		what = "READ_TOC";
		break;
	case GPCMD_READ_HEADER:
		what = "READ HEADER";
		break;
	case GPCMD_PLAY_AUDIO_10:
		what = "PLAY AUDIO (10)";
		break;
	case GPCMD_PLAY_AUDIO_MSF:
		what = "PLAY AUDIO MSF";
		break;
	case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
		what = "GET EVENT/STATUS NOTIFICATION";
		break;
	case GPCMD_PAUSE_RESUME:
		what = "PAUSE/RESUME";
		break;
	case LOG_SELECT:
		what = "LOG_SELECT";
		break;
	case LOG_SENSE:
		what = "LOG_SENSE";
		break;
	case GPCMD_STOP_PLAY_SCAN:
		what = "STOP PLAY/SCAN";
		break;
	case GPCMD_READ_DISC_INFO:
		what = "READ DISC INFORMATION";
		break;
	case GPCMD_READ_TRACK_RZONE_INFO:
		what = "READ TRACK INFORMATION";
		break;
	case GPCMD_RESERVE_RZONE_TRACK:
		what = "RESERVE TRACK";
		break;
	case GPCMD_SEND_OPC:
		what = "SEND OPC";
		break;
	case MODE_SELECT_10:
		what = "MODE_SELECT_10";
		break;
	case GPCMD_REPAIR_RZONE_TRACK:
		what = "REPAIR TRACK";
		break;
	case 0x59:
		what = "READ MASTER CUE";
		break;
	case MODE_SENSE_10:
		what = "MODE_SENSE_10";
		break;
	case GPCMD_CLOSE_TRACK:
		what = "CLOSE TRACK/SESSION";
		break;
	case 0x5C:
		what = "READ BUFFER CAPACITY";
		break;
	case 0x5D:
		what = "SEND CUE SHEET";
		break;
	case GPCMD_BLANK:
		what = "BLANK";
		break;
	case REPORT_LUNS:
		what = "REPORT LUNS";
		break;
	case MOVE_MEDIUM:
		what = "MOVE_MEDIUM or PLAY AUDIO (12)";
		break;
	case READ_12:
		what = "READ_12";
		break;
	case WRITE_12:
		what = "WRITE_12";
		break;
	case WRITE_VERIFY_12:
		what = "WRITE_VERIFY_12";
		break;
	case SEARCH_HIGH_12:
		what = "SEARCH_HIGH_12";
		break;
	case SEARCH_EQUAL_12:
		what = "SEARCH_EQUAL_12";
		break;
	case SEARCH_LOW_12:
		what = "SEARCH_LOW_12";
		break;
	case SEND_VOLUME_TAG:
		what = "SEND_VOLUME_TAG";
		break;
	case READ_ELEMENT_STATUS:
		what = "READ_ELEMENT_STATUS";
		break;
	case GPCMD_READ_CD_MSF:
		what = "READ CD MSF";
		break;
	case GPCMD_SCAN:
		what = "SCAN";
		break;
	case GPCMD_SET_SPEED:
		what = "SET CD SPEED";
		break;
	case GPCMD_MECHANISM_STATUS:
		what = "MECHANISM STATUS";
		break;
	case GPCMD_READ_CD:
		what = "READ CD";
		break;
	case 0xE1:
		what = "WRITE CONTINUE";
		break;
	case WRITE_LONG_2:
		what = "WRITE_LONG_2";
		break;
	case VENDOR_CMND:
		what = "Realtek's vendor command";
		break;
	default:
		what = "(unknown command)";
		unknown_cmd = true;
		break;
	}
	if (srb->cmnd[0] != TEST_UNIT_READY)
		dev_dbg(rtsx_dev(chip), "Command %s (%d bytes)\n",
			what, srb->cmd_len);
	if (unknown_cmd) {
		len = min_t(unsigned short, srb->cmd_len, 16);
		dev_dbg(rtsx_dev(chip), "%*ph\n", len, srb->cmnd);
	}
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 783 | 94.79% | 1 | 25.00% | 
| fabio falzoi | fabio falzoi | 38 | 4.60% | 2 | 50.00% | 
| quentin lambert | quentin lambert | 5 | 0.61% | 1 | 25.00% | 
 | Total | 826 | 100.00% | 4 | 100.00% | 
void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type)
{
	switch (sense_type) {
	case SENSE_TYPE_MEDIA_CHANGE:
		set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0);
		break;
	case SENSE_TYPE_MEDIA_NOT_PRESENT:
		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0);
		break;
	case SENSE_TYPE_MEDIA_LBA_OVER_RANGE:
		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0);
		break;
	case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT:
		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0);
		break;
	case SENSE_TYPE_MEDIA_WRITE_PROTECT:
		set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0);
		break;
	case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR:
		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0);
		break;
	case SENSE_TYPE_MEDIA_WRITE_ERR:
		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0);
		break;
	case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD:
		set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0,
				ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1);
		break;
	case SENSE_TYPE_FORMAT_IN_PROGRESS:
		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, 0, 0);
		break;
	case SENSE_TYPE_FORMAT_CMD_FAILED:
		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0);
		break;
#ifdef SUPPORT_MAGIC_GATE
	case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB:
		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0);
		break;
	case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN:
		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0);
		break;
	case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM:
		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0);
		break;
	case SENSE_TYPE_MG_WRITE_ERR:
		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0);
		break;
#endif
#ifdef SUPPORT_SD_LOCK
	case SENSE_TYPE_MEDIA_READ_FORBIDDEN:
		set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x11, 0x13, 0, 0);
		break;
#endif
	case SENSE_TYPE_NO_SENSE:
	default:
		set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0);
		break;
	}
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 434 | 100.00% | 1 | 100.00% | 
 | Total | 434 | 100.00% | 1 | 100.00% | 
void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code,
		u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0,
		u16 sns_key_info1)
{
	struct sense_data_t *sense = &(chip->sense_buffer[lun]);
	sense->err_code = err_code;
	sense->sense_key = sense_key;
	sense->info[0] = (u8)(info >> 24);
	sense->info[1] = (u8)(info >> 16);
	sense->info[2] = (u8)(info >> 8);
	sense->info[3] = (u8)info;
	sense->ad_sense_len = sizeof(struct sense_data_t) - 8;
	sense->asc = asc;
	sense->ascq = ascq;
	if (sns_key_info0 != 0) {
		sense->sns_key_info[0] = SKSV | sns_key_info0;
		sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 8;
		sense->sns_key_info[2] = sns_key_info1 & 0x0f;
	}
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 191 | 100.00% | 1 | 100.00% | 
 | Total | 191 | 100.00% | 1 | 100.00% | 
static int test_unit_ready(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned int lun = SCSI_LUN(srb);
	if (!check_card_ready(chip, lun)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		return TRANSPORT_FAILED;
	}
	if (!(CHK_BIT(chip->lun_mc, lun))) {
		SET_BIT(chip->lun_mc, lun);
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
		return TRANSPORT_FAILED;
	}
#ifdef SUPPORT_SD_LOCK
	if (get_lun_card(chip, SCSI_LUN(srb)) == SD_CARD) {
		struct sd_info *sd_card = &(chip->sd_card);
		if (sd_card->sd_lock_notify) {
			sd_card->sd_lock_notify = 0;
			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
			return TRANSPORT_FAILED;
		} else if (sd_card->sd_lock_status & SD_LOCKED) {
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_READ_FORBIDDEN);
			return TRANSPORT_FAILED;
		}
	}
#endif
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 171 | 100.00% | 1 | 100.00% | 
 | Total | 171 | 100.00% | 1 | 100.00% | 
static unsigned char formatter_inquiry_str[20] = {
	'M', 'E', 'M', 'O', 'R', 'Y', 'S', 'T', 'I', 'C', 'K',
#ifdef SUPPORT_MAGIC_GATE
	'-', 'M', 'G', /* Byte[47:49] */
#else
	0x20, 0x20, 0x20,  /* Byte[47:49] */
#endif
#ifdef SUPPORT_MAGIC_GATE
	0x0B,  /* Byte[50]: MG, MS, MSPro, MSXC */
#else
	0x09,  /* Byte[50]: MS, MSPro, MSXC */
#endif
	0x00,  /* Byte[51]: Category Specific Commands */
	0x00,  /* Byte[52]: Access Control and feature */
	0x20, 0x20, 0x20, /* Byte[53:55] */
};
static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned int lun = SCSI_LUN(srb);
	char *inquiry_default = (char *)"Generic-xD/SD/M.S.      1.00 ";
	char *inquiry_sdms =    (char *)"Generic-SD/MemoryStick  1.00 ";
	char *inquiry_sd =      (char *)"Generic-SD/MMC          1.00 ";
	char *inquiry_ms =      (char *)"Generic-MemoryStick     1.00 ";
	char *inquiry_string;
	unsigned char sendbytes;
	unsigned char *buf;
	u8 card = get_lun_card(chip, lun);
	bool pro_formatter_flag = false;
	unsigned char inquiry_buf[] = {
		QULIFIRE|DRCT_ACCESS_DEV,
		RMB_DISC|0x0D,
		0x00,
		0x01,
		0x1f,
		0x02,
		0,
		REL_ADR|WBUS_32|WBUS_16|SYNC|LINKED|CMD_QUE|SFT_RE,
        };
	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
		if (chip->lun2card[lun] == SD_CARD)
			inquiry_string = inquiry_sd;
		else
			inquiry_string = inquiry_ms;
	} else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) {
		inquiry_string = inquiry_sdms;
	} else {
		inquiry_string = inquiry_default;
	}
	buf = vmalloc(scsi_bufflen(srb));
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
#ifdef SUPPORT_MAGIC_GATE
	if ((chip->mspro_formatter_enable) &&
			(chip->lun2card[lun] & MS_CARD))
#else
	if (chip->mspro_formatter_enable)
#endif
		if (!card || (card == MS_CARD))
			pro_formatter_flag = true;
	if (pro_formatter_flag) {
		if (scsi_bufflen(srb) < 56)
			sendbytes = (unsigned char)(scsi_bufflen(srb));
		else
			sendbytes = 56;
	} else {
		if (scsi_bufflen(srb) < 36)
			sendbytes = (unsigned char)(scsi_bufflen(srb));
		else
			sendbytes = 36;
	}
	if (sendbytes > 8) {
		memcpy(buf, inquiry_buf, 8);
		memcpy(buf + 8, inquiry_string,	sendbytes - 8);
		if (pro_formatter_flag) {
			/* Additional Length */
			buf[4] = 0x33;
		}
	} else {
		memcpy(buf, inquiry_buf, sendbytes);
	}
	if (pro_formatter_flag) {
		if (sendbytes > 36)
			memcpy(buf + 36, formatter_inquiry_str, sendbytes - 36);
	}
	scsi_set_resid(srb, 0);
	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
	vfree(buf);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 419 | 97.67% | 1 | 25.00% | 
| joe perches | joe perches | 6 | 1.40% | 1 | 25.00% | 
| quentin lambert | quentin lambert | 3 | 0.70% | 1 | 25.00% | 
| eva rachel retuya | eva rachel retuya | 1 | 0.23% | 1 | 25.00% | 
 | Total | 429 | 100.00% | 4 | 100.00% | 
static int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned int lun = SCSI_LUN(srb);
	scsi_set_resid(srb, scsi_bufflen(srb));
	if (srb->cmnd[1] == 1)
		return TRANSPORT_GOOD;
	switch (srb->cmnd[0x4]) {
	case STOP_MEDIUM:
		/* Media disabled */
		return TRANSPORT_GOOD;
	case UNLOAD_MEDIUM:
		/* Media shall be unload */
		if (check_card_ready(chip, lun))
			eject_card(chip, lun);
		return TRANSPORT_GOOD;
	case MAKE_MEDIUM_READY:
	case LOAD_MEDIUM:
		if (check_card_ready(chip, lun))
			return TRANSPORT_GOOD;
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
		break;
	}
	rtsx_trace(chip);
	return TRANSPORT_ERROR;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 126 | 94.03% | 1 | 50.00% | 
| joe perches | joe perches | 8 | 5.97% | 1 | 50.00% | 
 | Total | 134 | 100.00% | 2 | 100.00% | 
static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	int prevent;
	prevent = srb->cmnd[4] & 0x1;
	scsi_set_resid(srb, 0);
	if (prevent) {
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 62 | 93.94% | 1 | 50.00% | 
| joe perches | joe perches | 4 | 6.06% | 1 | 50.00% | 
 | Total | 66 | 100.00% | 2 | 100.00% | 
static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	struct sense_data_t *sense;
	unsigned int lun = SCSI_LUN(srb);
	struct ms_info *ms_card = &(chip->ms_card);
	unsigned char *tmp, *buf;
	sense = &(chip->sense_buffer[lun]);
	if ((get_lun_card(chip, lun) == MS_CARD) &&
		ms_card->pro_under_formatting) {
		if (ms_card->format_status == FORMAT_SUCCESS) {
			set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
			ms_card->pro_under_formatting = 0;
			ms_card->progress = 0;
		} else if (ms_card->format_status == FORMAT_IN_PROGRESS) {
			/* Logical Unit Not Ready Format in Progress */
			set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
					0, (u16)(ms_card->progress));
		} else {
			/* Format Command Failed */
			set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
			ms_card->pro_under_formatting = 0;
			ms_card->progress = 0;
		}
		rtsx_set_stat(chip, RTSX_STAT_RUN);
	}
	buf = vmalloc(scsi_bufflen(srb));
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	tmp = (unsigned char *)sense;
	memcpy(buf, tmp, scsi_bufflen(srb));
	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
	vfree(buf);
	scsi_set_resid(srb, 0);
	/* Reset Sense Data */
	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 260 | 97.38% | 1 | 33.33% | 
| joe perches | joe perches | 6 | 2.25% | 1 | 33.33% | 
| eva rachel retuya | eva rachel retuya | 1 | 0.37% | 1 | 33.33% | 
 | Total | 267 | 100.00% | 3 | 100.00% | 
static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd,
		int lun, u8 *buf, int buf_len)
{
	struct ms_info *ms_card = &(chip->ms_card);
	int sys_info_offset;
	int data_size = buf_len;
	bool support_format = false;
	int i = 0;
	if (cmd == MODE_SENSE) {
		sys_info_offset = 8;
		if (data_size > 0x68)
			data_size = 0x68;
		buf[i++] = 0x67;  /* Mode Data Length */
	} else {
		sys_info_offset = 12;
		if (data_size > 0x6C)
			data_size = 0x6C;
		buf[i++] = 0x00;  /* Mode Data Length (MSB) */
		buf[i++] = 0x6A;  /* Mode Data Length (LSB) */
	}
	/* Medium Type Code */
	if (check_card_ready(chip, lun)) {
		if (CHK_MSXC(ms_card)) {
			support_format = true;
			buf[i++] = 0x40;
		} else if (CHK_MSPRO(ms_card)) {
			support_format = true;
			buf[i++] = 0x20;
		} else {
			buf[i++] = 0x10;
		}
		/* WP */
		if (check_card_wp(chip, lun))
			buf[i++] = 0x80;
		else
			buf[i++] = 0x00;
	} else {
		buf[i++] = 0x00;	/* MediaType */
		buf[i++] = 0x00;	/* WP */
	}
	buf[i++] = 0x00;		/* Reserved */
	if (cmd == MODE_SENSE_10) {
		buf[i++] = 0x00;  /* Reserved */
		buf[i++] = 0x00;  /* Block descriptor length(MSB) */
		buf[i++] = 0x00;  /* Block descriptor length(LSB) */
		/* The Following Data is the content of "Page 0x20" */
		if (data_size >= 9)
			buf[i++] = 0x20;		/* Page Code */
		if (data_size >= 10)
			buf[i++] = 0x62;		/* Page Length */
		if (data_size >= 11)
			buf[i++] = 0x00;		/* No Access Control */
		if (data_size >= 12) {
			if (support_format)
				buf[i++] = 0xC0;	/* SF, SGM */
			else
				buf[i++] = 0x00;
		}
	} else {
		/* The Following Data is the content of "Page 0x20" */
		if (data_size >= 5)
			buf[i++] = 0x20;		/* Page Code */
		if (data_size >= 6)
			buf[i++] = 0x62;		/* Page Length */
		if (data_size >= 7)
			buf[i++] = 0x00;		/* No Access Control */
		if (data_size >= 8) {
			if (support_format)
				buf[i++] = 0xC0;	/* SF, SGM */
			else
				buf[i++] = 0x00;
		}
	}
	if (data_size > sys_info_offset) {
		/* 96 Bytes Attribute Data */
		int len = data_size - sys_info_offset;
		len = (len < 96) ? len : 96;
		memcpy(buf + sys_info_offset, ms_card->raw_sys_info, len);
	}
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 470 | 99.16% | 1 | 50.00% | 
| quentin lambert | quentin lambert | 4 | 0.84% | 1 | 50.00% | 
 | Total | 474 | 100.00% | 2 | 100.00% | 
static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned int lun = SCSI_LUN(srb);
	unsigned int dataSize;
	int status;
	bool pro_formatter_flag;
	unsigned char pageCode, *buf;
	u8 card = get_lun_card(chip, lun);
#ifndef SUPPORT_MAGIC_GATE
	if (!check_card_ready(chip, lun)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		scsi_set_resid(srb, scsi_bufflen(srb));
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
#endif
	pro_formatter_flag = false;
	dataSize = 8;
#ifdef SUPPORT_MAGIC_GATE
	if ((chip->lun2card[lun] & MS_CARD)) {
		if (!card || (card == MS_CARD)) {
			dataSize = 108;
			if (chip->mspro_formatter_enable)
				pro_formatter_flag = true;
		}
	}
#else
	if (card == MS_CARD) {
		if (chip->mspro_formatter_enable) {
			pro_formatter_flag = true;
			dataSize = 108;
		}
	}
#endif
	buf = kmalloc(dataSize, GFP_KERNEL);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	pageCode = srb->cmnd[2] & 0x3f;
	if ((pageCode == 0x3F) || (pageCode == 0x1C) ||
		(pageCode == 0x00) ||
		(pro_formatter_flag && (pageCode == 0x20))) {
		if (srb->cmnd[0] == MODE_SENSE) {
			if ((pageCode == 0x3F) || (pageCode == 0x20)) {
				ms_mode_sense(chip, srb->cmnd[0],
					      lun, buf, dataSize);
			} else {
				dataSize = 4;
				buf[0] = 0x03;
				buf[1] = 0x00;
				if (check_card_wp(chip, lun))
					buf[2] = 0x80;
				else
					buf[2] = 0x00;
				buf[3] = 0x00;
			}
		} else {
			if ((pageCode == 0x3F) || (pageCode == 0x20)) {
				ms_mode_sense(chip, srb->cmnd[0],
					      lun, buf, dataSize);
			} else {
				dataSize = 8;
				buf[0] = 0x00;
				buf[1] = 0x06;
				buf[2] = 0x00;
				if (check_card_wp(chip, lun))
					buf[3] = 0x80;
				else
					buf[3] = 0x00;
				buf[4] = 0x00;
				buf[5] = 0x00;
				buf[6] = 0x00;
				buf[7] = 0x00;
			}
		}
		status = TRANSPORT_GOOD;
	} else {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		scsi_set_resid(srb, scsi_bufflen(srb));
		status = TRANSPORT_FAILED;
	}
	if (status == TRANSPORT_GOOD) {
		unsigned int len = min_t(unsigned int, scsi_bufflen(srb),
					dataSize);
		rtsx_stor_set_xfer_buf(buf, len, srb);
		scsi_set_resid(srb, scsi_bufflen(srb) - len);
	}
	kfree(buf);
	return status;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 525 | 97.22% | 1 | 25.00% | 
| joe perches | joe perches | 10 | 1.85% | 1 | 25.00% | 
| quentin lambert | quentin lambert | 4 | 0.74% | 1 | 25.00% | 
| eva rachel retuya | eva rachel retuya | 1 | 0.19% | 1 | 25.00% | 
 | Total | 540 | 100.00% | 4 | 100.00% | 
static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
#ifdef SUPPORT_SD_LOCK
	struct sd_info *sd_card = &(chip->sd_card);
#endif
	unsigned int lun = SCSI_LUN(srb);
	int retval;
	u32 start_sec;
	u16 sec_cnt;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	if (!check_card_ready(chip, lun) || (get_card_size(chip, lun) == 0)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (!(CHK_BIT(chip->lun_mc, lun))) {
		SET_BIT(chip->lun_mc, lun);
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
		return TRANSPORT_FAILED;
	}
#ifdef SUPPORT_SD_LOCK
	if (sd_card->sd_erase_status) {
		/* Accessing to any card is forbidden
                 * until the erase procedure of SD is completed
                 */
		dev_dbg(rtsx_dev(chip), "SD card being erased!\n");
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (get_lun_card(chip, lun) == SD_CARD) {
		if (sd_card->sd_lock_status & SD_LOCKED) {
			dev_dbg(rtsx_dev(chip), "SD card locked!\n");
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_READ_FORBIDDEN);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
#endif
	if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) {
		start_sec = ((u32)srb->cmnd[2] << 24) |
			((u32)srb->cmnd[3] << 16) |
			((u32)srb->cmnd[4] << 8) | ((u32)srb->cmnd[5]);
		sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
	} else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) {
		start_sec = ((u32)(srb->cmnd[1] & 0x1F) << 16) |
			((u32)srb->cmnd[2] << 8) | ((u32)srb->cmnd[3]);
		sec_cnt = srb->cmnd[4];
		if (sec_cnt == 0)
			sec_cnt = 256;
	} else if ((srb->cmnd[0] == VENDOR_CMND) &&
		(srb->cmnd[1] == SCSI_APP_CMD) &&
		((srb->cmnd[2] == PP_READ10) || (srb->cmnd[2] == PP_WRITE10))) {
		start_sec = ((u32)srb->cmnd[4] << 24) |
			((u32)srb->cmnd[5] << 16) |
			((u32)srb->cmnd[6] << 8) | ((u32)srb->cmnd[7]);
		sec_cnt = ((u16)(srb->cmnd[9]) << 8) | srb->cmnd[10];
	} else {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	/* In some test, we will receive a start_sec like 0xFFFFFFFF.
         * In this situation, start_sec + sec_cnt will overflow, so we
         * need to judge start_sec at first
         */
	if ((start_sec > get_card_size(chip, lun)) ||
			((start_sec + sec_cnt) > get_card_size(chip, lun))) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (sec_cnt == 0) {
		scsi_set_resid(srb, 0);
		return TRANSPORT_GOOD;
	}
	if (chip->rw_fail_cnt[lun] == 3) {
		dev_dbg(rtsx_dev(chip), "read/write fail three times in succession\n");
		if (srb->sc_data_direction == DMA_FROM_DEVICE)
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
		else
			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (srb->sc_data_direction == DMA_TO_DEVICE) {
		if (check_card_wp(chip, lun)) {
			dev_dbg(rtsx_dev(chip), "Write protected card!\n");
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_WRITE_PROTECT);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
	retval = card_rw(srb, chip, start_sec, sec_cnt);
	if (retval != STATUS_SUCCESS) {
		if (chip->need_release & chip->lun2card[lun]) {
			chip->rw_fail_cnt[lun] = 0;
			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		} else {
			chip->rw_fail_cnt[lun]++;
			if (srb->sc_data_direction == DMA_FROM_DEVICE)
				set_sense_type(chip, lun,
					SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
			else
				set_sense_type(chip, lun,
					SENSE_TYPE_MEDIA_WRITE_ERR);
		}
		retval = TRANSPORT_FAILED;
		rtsx_trace(chip);
		goto Exit;
	} else {
		chip->rw_fail_cnt[lun] = 0;
		retval = TRANSPORT_GOOD;
	}
	scsi_set_resid(srb, 0);
Exit:
	return retval;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 847 | 92.77% | 1 | 25.00% | 
| joe perches | joe perches | 32 | 3.50% | 1 | 25.00% | 
| fabio falzoi | fabio falzoi | 24 | 2.63% | 1 | 25.00% | 
| akinobu mita | akinobu mita | 10 | 1.10% | 1 | 25.00% | 
 | Total | 913 | 100.00% | 4 | 100.00% | 
static int read_format_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned char *buf;
	unsigned int lun = SCSI_LUN(srb);
	unsigned int buf_len;
	u8 card = get_lun_card(chip, lun);
	u32 card_size;
	int desc_cnt;
	int i = 0;
	if (!check_card_ready(chip, lun)) {
		if (!chip->mspro_formatter_enable) {
			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
	buf_len = (scsi_bufflen(srb) > 12) ? 0x14 : 12;
	buf = kmalloc(buf_len, GFP_KERNEL);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	buf[i++] = 0;
	buf[i++] = 0;
	buf[i++] = 0;
	/* Capacity List Length */
	if ((buf_len > 12) && chip->mspro_formatter_enable &&
			(chip->lun2card[lun] & MS_CARD) &&
			(!card || (card == MS_CARD))) {
		buf[i++] = 0x10;
		desc_cnt = 2;
	} else {
		buf[i++] = 0x08;
		desc_cnt = 1;
	}
	while (desc_cnt) {
		if (check_card_ready(chip, lun)) {
			card_size = get_card_size(chip, lun);
			buf[i++] = (unsigned char)(card_size >> 24);
			buf[i++] = (unsigned char)(card_size >> 16);
			buf[i++] = (unsigned char)(card_size >> 8);
			buf[i++] = (unsigned char)card_size;
			if (desc_cnt == 2)
				buf[i++] = 2;
			else
				buf[i++] = 0;
		} else {
			buf[i++] = 0xFF;
			buf[i++] = 0xFF;
			buf[i++] = 0xFF;
			buf[i++] = 0xFF;
			if (desc_cnt == 2)
				buf[i++] = 3;
			else
				buf[i++] = 0;
		}
		buf[i++] = 0x00;
		buf[i++] = 0x02;
		buf[i++] = 0x00;
		desc_cnt--;
	}
	buf_len = min_t(unsigned int, scsi_bufflen(srb), buf_len);
	rtsx_stor_set_xfer_buf(buf, buf_len, srb);
	kfree(buf);
	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 443 | 97.58% | 1 | 33.33% | 
| joe perches | joe perches | 10 | 2.20% | 1 | 33.33% | 
| eva rachel retuya | eva rachel retuya | 1 | 0.22% | 1 | 33.33% | 
 | Total | 454 | 100.00% | 3 | 100.00% | 
static int read_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned char *buf;
	unsigned int lun = SCSI_LUN(srb);
	u32 card_size;
	if (!check_card_ready(chip, lun)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (!(CHK_BIT(chip->lun_mc, lun))) {
		SET_BIT(chip->lun_mc, lun);
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
		return TRANSPORT_FAILED;
	}
	buf = kmalloc(8, GFP_KERNEL);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	card_size = get_card_size(chip, lun);
	buf[0] = (unsigned char)((card_size - 1) >> 24);
	buf[1] = (unsigned char)((card_size - 1) >> 16);
	buf[2] = (unsigned char)((card_size - 1) >> 8);
	buf[3] = (unsigned char)(card_size - 1);
	buf[4] = 0x00;
	buf[5] = 0x00;
	buf[6] = 0x02;
	buf[7] = 0x00;
	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
	kfree(buf);
	scsi_set_resid(srb, 0);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 248 | 95.75% | 1 | 33.33% | 
| joe perches | joe perches | 10 | 3.86% | 1 | 33.33% | 
| eva rachel retuya | eva rachel retuya | 1 | 0.39% | 1 | 33.33% | 
 | Total | 259 | 100.00% | 3 | 100.00% | 
static int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned short len, i;
	int retval;
	u8 *buf;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
	buf = vmalloc(len);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	retval = rtsx_force_power_on(chip, SSC_PDCTL);
	if (retval != STATUS_SUCCESS) {
		vfree(buf);
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	for (i = 0; i < len; i++) {
		retval = spi_read_eeprom(chip, i, buf + i);
		if (retval != STATUS_SUCCESS) {
			vfree(buf);
			set_sense_type(chip, SCSI_LUN(srb),
				SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
	len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
	rtsx_stor_set_xfer_buf(buf, len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - len);
	vfree(buf);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 246 | 94.62% | 1 | 50.00% | 
| joe perches | joe perches | 14 | 5.38% | 1 | 50.00% | 
 | Total | 260 | 100.00% | 2 | 100.00% | 
static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned short len, i;
	int retval;
	u8 *buf;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
	retval = rtsx_force_power_on(chip, SSC_PDCTL);
	if (retval != STATUS_SUCCESS) {
		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (len == 511) {
		retval = spi_erase_eeprom_chip(chip);
		if (retval != STATUS_SUCCESS) {
			set_sense_type(chip, SCSI_LUN(srb),
				SENSE_TYPE_MEDIA_WRITE_ERR);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	} else {
		len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb),
					len);
		buf = vmalloc(len);
		if (!buf) {
			rtsx_trace(chip);
			return TRANSPORT_ERROR;
		}
		rtsx_stor_get_xfer_buf(buf, len, srb);
		scsi_set_resid(srb, scsi_bufflen(srb) - len);
		for (i = 0; i < len; i++) {
			retval = spi_write_eeprom(chip, i, buf[i]);
			if (retval != STATUS_SUCCESS) {
				vfree(buf);
				set_sense_type(chip, SCSI_LUN(srb),
					SENSE_TYPE_MEDIA_WRITE_ERR);
				rtsx_trace(chip);
				return TRANSPORT_FAILED;
			}
		}
		vfree(buf);
	}
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 283 | 93.71% | 1 | 33.33% | 
| joe perches | joe perches | 18 | 5.96% | 1 | 33.33% | 
| eva rachel retuya | eva rachel retuya | 1 | 0.33% | 1 | 33.33% | 
 | Total | 302 | 100.00% | 3 | 100.00% | 
static int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned short addr, len, i;
	int retval;
	u8 *buf;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3];
	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
	if (addr < 0xFC00) {
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	buf = vmalloc(len);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	retval = rtsx_force_power_on(chip, SSC_PDCTL);
	if (retval != STATUS_SUCCESS) {
		vfree(buf);
		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	for (i = 0; i < len; i++) {
		retval = rtsx_read_register(chip, addr + i, buf + i);
		if (retval != STATUS_SUCCESS) {
			vfree(buf);
			set_sense_type(chip, SCSI_LUN(srb),
				SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
	len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
	rtsx_stor_set_xfer_buf(buf, len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - len);
	vfree(buf);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 297 | 94.29% | 1 | 50.00% | 
| joe perches | joe perches | 18 | 5.71% | 1 | 50.00% | 
 | Total | 315 | 100.00% | 2 | 100.00% | 
static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned short addr, len, i;
	int retval;
	u8 *buf;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3];
	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
	if (addr < 0xFC00) {
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
	buf = vmalloc(len);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	rtsx_stor_get_xfer_buf(buf, len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - len);
	retval = rtsx_force_power_on(chip, SSC_PDCTL);
	if (retval != STATUS_SUCCESS) {
		vfree(buf);
		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	for (i = 0; i < len; i++) {
		retval = rtsx_write_register(chip, addr + i, 0xFF, buf[i]);
		if (retval != STATUS_SUCCESS) {
			vfree(buf);
			set_sense_type(chip, SCSI_LUN(srb),
				SENSE_TYPE_MEDIA_WRITE_ERR);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
	vfree(buf);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 299 | 94.03% | 1 | 33.33% | 
| joe perches | joe perches | 18 | 5.66% | 1 | 33.33% | 
| eva rachel retuya | eva rachel retuya | 1 | 0.31% | 1 | 33.33% | 
 | Total | 318 | 100.00% | 3 | 100.00% | 
static int get_sd_csd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	struct sd_info *sd_card = &(chip->sd_card);
	unsigned int lun = SCSI_LUN(srb);
	if (!check_card_ready(chip, lun)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (get_lun_card(chip, lun) != SD_CARD) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	scsi_set_resid(srb, 0);
	rtsx_stor_set_xfer_buf(sd_card->raw_csd, scsi_bufflen(srb), srb);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 112 | 93.33% | 1 | 50.00% | 
| joe perches | joe perches | 8 | 6.67% | 1 | 50.00% | 
 | Total | 120 | 100.00% | 2 | 100.00% | 
static int toggle_gpio_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	u8 gpio = srb->cmnd[2];
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	if (gpio > 3)
		gpio = 1;
	toggle_gpio(chip, gpio);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 85 | 100.00% | 1 | 100.00% | 
 | Total | 85 | 100.00% | 1 | 100.00% | 
#ifdef _MSG_TRACE
static int trace_msg_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned char *ptr, *buf = NULL;
	int i, msg_cnt;
	u8 clear;
	unsigned int buf_len;
	buf_len = 4 + ((2 + MSG_FUNC_LEN + MSG_FILE_LEN + TIME_VAL_LEN) *
		TRACE_ITEM_CNT);
	if ((scsi_bufflen(srb) < buf_len) || (scsi_sglist(srb) == NULL)) {
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	clear = srb->cmnd[2];
	buf = vmalloc(scsi_bufflen(srb));
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	ptr = buf;
	if (chip->trace_msg[chip->msg_idx].valid)
		msg_cnt = TRACE_ITEM_CNT;
	else
		msg_cnt = chip->msg_idx;
	*(ptr++) = (u8)(msg_cnt >> 24);
	*(ptr++) = (u8)(msg_cnt >> 16);
	*(ptr++) = (u8)(msg_cnt >> 8);
	*(ptr++) = (u8)msg_cnt;
	dev_dbg(rtsx_dev(chip), "Trace message count is %d\n", msg_cnt);
	for (i = 1; i <= msg_cnt; i++) {
		int j, idx;
		idx = chip->msg_idx - i;
		if (idx < 0)
			idx += TRACE_ITEM_CNT;
		*(ptr++) = (u8)(chip->trace_msg[idx].line >> 8);
		*(ptr++) = (u8)(chip->trace_msg[idx].line);
		for (j = 0; j < MSG_FUNC_LEN; j++)
			*(ptr++) = chip->trace_msg[idx].func[j];
		for (j = 0; j < MSG_FILE_LEN; j++)
			*(ptr++) = chip->trace_msg[idx].file[j];
		for (j = 0; j < TIME_VAL_LEN; j++)
			*(ptr++) = chip->trace_msg[idx].timeval_buf[j];
	}
	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
	vfree(buf);
	if (clear) {
		chip->msg_idx = 0;
		for (i = 0; i < TRACE_ITEM_CNT; i++)
			chip->trace_msg[i].valid = 0;
	}
	scsi_set_resid(srb, 0);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 447 | 96.34% | 1 | 25.00% | 
| joe perches | joe perches | 10 | 2.16% | 1 | 25.00% | 
| fabio falzoi | fabio falzoi | 6 | 1.29% | 1 | 25.00% | 
| eva rachel retuya | eva rachel retuya | 1 | 0.22% | 1 | 25.00% | 
 | Total | 464 | 100.00% | 4 | 100.00% | 
#endif
static int read_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	u8 addr, buf[4];
	u32 val;
	unsigned int len;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	addr = srb->cmnd[4];
	val = rtsx_readl(chip, addr);
	dev_dbg(rtsx_dev(chip), "Host register (0x%x): 0x%x\n", addr, val);
	buf[0] = (u8)(val >> 24);
	buf[1] = (u8)(val >> 16);
	buf[2] = (u8)(val >> 8);
	buf[3] = (u8)val;
	len = min_t(unsigned int, scsi_bufflen(srb), 4);
	rtsx_stor_set_xfer_buf(buf, len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - len);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 183 | 96.83% | 1 | 50.00% | 
| fabio falzoi | fabio falzoi | 6 | 3.17% | 1 | 50.00% | 
 | Total | 189 | 100.00% | 2 | 100.00% | 
static int write_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	u8 addr, buf[4];
	u32 val;
	unsigned int len;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	addr = srb->cmnd[4];
	len = min_t(unsigned int, scsi_bufflen(srb), 4);
	rtsx_stor_get_xfer_buf(buf, len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - len);
	val = ((u32)buf[0] << 24) | ((u32)buf[1] << 16) | ((u32)buf[2]
							<< 8) | buf[3];
	rtsx_writel(chip, addr, val);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 166 | 100.00% | 1 | 100.00% | 
 | Total | 166 | 100.00% | 1 | 100.00% | 
static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned lun = SCSI_LUN(srb);
	if (srb->cmnd[3] == 1) {
		/* Variable Clock */
		struct xd_info *xd_card = &(chip->xd_card);
		struct sd_info *sd_card = &(chip->sd_card);
		struct ms_info *ms_card = &(chip->ms_card);
		switch (srb->cmnd[4]) {
		case XD_CARD:
			xd_card->xd_clock = srb->cmnd[5];
			break;
		case SD_CARD:
			sd_card->sd_clock = srb->cmnd[5];
			break;
		case MS_CARD:
			ms_card->ms_clock = srb->cmnd[5];
			break;
		default:
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	} else if (srb->cmnd[3] == 2) {
		if (srb->cmnd[4]) {
			chip->blink_led = 1;
		} else {
			int retval;
			chip->blink_led = 0;
			rtsx_disable_aspm(chip);
			if (chip->ss_en &&
				(rtsx_get_stat(chip) == RTSX_STAT_SS)) {
				rtsx_exit_ss(chip);
				wait_timeout(100);
			}
			rtsx_set_stat(chip, RTSX_STAT_RUN);
			retval = rtsx_force_power_on(chip, SSC_PDCTL);
			if (retval != STATUS_SUCCESS) {
				set_sense_type(chip, SCSI_LUN(srb),
					SENSE_TYPE_MEDIA_WRITE_ERR);
				rtsx_trace(chip);
				return TRANSPORT_FAILED;
			}
			turn_off_led(chip, LED_GPIO);
		}
	} else {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 285 | 95.96% | 1 | 50.00% | 
| joe perches | joe perches | 12 | 4.04% | 1 | 50.00% | 
 | Total | 297 | 100.00% | 2 | 100.00% | 
static int get_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned int lun = SCSI_LUN(srb);
	if (srb->cmnd[3] == 1) {
		struct xd_info *xd_card = &(chip->xd_card);
		struct sd_info *sd_card = &(chip->sd_card);
		struct ms_info *ms_card = &(chip->ms_card);
		u8 tmp;
		switch (srb->cmnd[4]) {
		case XD_CARD:
			tmp = (u8)(xd_card->xd_clock);
			break;
		case SD_CARD:
			tmp = (u8)(sd_card->sd_clock);
			break;
		case MS_CARD:
			tmp = (u8)(ms_card->ms_clock);
			break;
		default:
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		rtsx_stor_set_xfer_buf(&tmp, 1, srb);
	} else if (srb->cmnd[3] == 2) {
		u8 tmp = chip->blink_led;
		rtsx_stor_set_xfer_buf(&tmp, 1, srb);
	} else {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 207 | 96.28% | 1 | 50.00% | 
| joe perches | joe perches | 8 | 3.72% | 1 | 50.00% | 
 | Total | 215 | 100.00% | 2 | 100.00% | 
static int dma_access_ring_buffer(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	int retval;
	unsigned int lun = SCSI_LUN(srb);
	u16 len;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	len = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
	len = min_t(u16, len, scsi_bufflen(srb));
	if (srb->sc_data_direction == DMA_FROM_DEVICE)
		dev_dbg(rtsx_dev(chip), "Read from device\n");
	else
		dev_dbg(rtsx_dev(chip), "Write to device\n");
	retval = rtsx_transfer_data(chip, 0, scsi_sglist(srb), len,
			scsi_sg_count(srb), srb->sc_data_direction, 1000);
	if (retval < 0) {
		if (srb->sc_data_direction == DMA_FROM_DEVICE)
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
		else
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_WRITE_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	scsi_set_resid(srb, 0);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 201 | 92.20% | 1 | 33.33% | 
| fabio falzoi | fabio falzoi | 12 | 5.50% | 1 | 33.33% | 
| joe perches | joe perches | 5 | 2.29% | 1 | 33.33% | 
 | Total | 218 | 100.00% | 3 | 100.00% | 
static int get_dev_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	struct sd_info *sd_card = &(chip->sd_card);
	struct ms_info *ms_card = &(chip->ms_card);
	int buf_len;
	unsigned int lun = SCSI_LUN(srb);
	u8 card = get_lun_card(chip, lun);
	u8 status[32];
#ifdef SUPPORT_OCP
	u8 oc_now_mask = 0, oc_ever_mask = 0;
#endif
	memset(status, 0, 32);
	status[0] = (u8)(chip->product_id);
	status[1] = chip->ic_version;
	if (chip->auto_delink_en)
		status[2] = 0x10;
	else
		status[2] = 0x00;
	status[3] = 20;
	status[4] = 10;
	status[5] = 05;
	status[6] = 21;
	if (chip->card_wp)
		status[7] = 0x20;
	else
		status[7] = 0x00;
#ifdef SUPPORT_OCP
	status[8] = 0;
	if (CHECK_LUN_MODE(chip,
		SD_MS_2LUN) && (chip->lun2card[lun] == MS_CARD)) {
		oc_now_mask = MS_OC_NOW;
		oc_ever_mask = MS_OC_EVER;
	} else {
		oc_now_mask = SD_OC_NOW;
		oc_ever_mask = SD_OC_EVER;
	}
	if (chip->ocp_stat & oc_now_mask)
		status[8] |= 0x02;
	if (chip->ocp_stat & oc_ever_mask)
		status[8] |= 0x01;
#endif
	if (card == SD_CARD) {
		if (CHK_SD(sd_card)) {
			if (CHK_SD_HCXC(sd_card)) {
				if (sd_card->capacity > 0x4000000)
					status[0x0E] = 0x02;
				else
					status[0x0E] = 0x01;
			} else {
				status[0x0E] = 0x00;
			}
			if (CHK_SD_SDR104(sd_card))
				status[0x0F] = 0x03;
			else if (CHK_SD_DDR50(sd_card))
				status[0x0F] = 0x04;
			else if (CHK_SD_SDR50(sd_card))
				status[0x0F] = 0x02;
			else if (CHK_SD_HS(sd_card))
				status[0x0F] = 0x01;
			else
				status[0x0F] = 0x00;
		} else {
			if (CHK_MMC_SECTOR_MODE(sd_card))
				status[0x0E] = 0x01;
			else
				status[0x0E] = 0x00;
			if (CHK_MMC_DDR52(sd_card))
				status[0x0F] = 0x03;
			else if (CHK_MMC_52M(sd_card))
				status[0x0F] = 0x02;
			else if (CHK_MMC_26M(sd_card))
				status[0x0F] = 0x01;
			else
				status[0x0F] = 0x00;
		}
	} else if (card == MS_CARD) {
		if (CHK_MSPRO(ms_card)) {
			if (CHK_MSXC(ms_card))
				status[0x0E] = 0x01;
			else
				status[0x0E] = 0x00;
			if (CHK_HG8BIT(ms_card))
				status[0x0F] = 0x01;
			else
				status[0x0F] = 0x00;
		}
	}
#ifdef SUPPORT_SD_LOCK
	if (card == SD_CARD) {
		status[0x17] = 0x80;
		if (sd_card->sd_erase_status)
			status[0x17] |= 0x01;
		if (sd_card->sd_lock_status & SD_LOCKED) {
			status[0x17] |= 0x02;
			status[0x07] |= 0x40;
		}
		if (sd_card->sd_lock_status & SD_PWD_EXIST)
			status[0x17] |= 0x04;
	} else {
		status[0x17] = 0x00;
	}
	dev_dbg(rtsx_dev(chip), "status[0x17] = 0x%x\n", status[0x17]);
#endif
	status[0x18] = 0x8A;
	status[0x1A] = 0x28;
#ifdef SUPPORT_SD_LOCK
	status[0x1F] = 0x01;
#endif
	buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(status));
	rtsx_stor_set_xfer_buf(status, buf_len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 684 | 99.13% | 1 | 50.00% | 
| fabio falzoi | fabio falzoi | 6 | 0.87% | 1 | 50.00% | 
 | Total | 690 | 100.00% | 2 | 100.00% | 
static int set_chip_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	int phy_debug_mode;
	int retval;
	u16 reg;
	if (!CHECK_PID(chip, 0x5208)) {
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	phy_debug_mode = (int)(srb->cmnd[3]);
	if (phy_debug_mode) {
		chip->phy_debug_mode = 1;
		retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0);
		if (retval != STATUS_SUCCESS) {
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		rtsx_disable_bus_int(chip);
		retval = rtsx_read_phy_register(chip, 0x1C, ®);
		if (retval != STATUS_SUCCESS) {
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		reg |= 0x0001;
		retval = rtsx_write_phy_register(chip, 0x1C, reg);
		if (retval != STATUS_SUCCESS) {
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	} else {
		chip->phy_debug_mode = 0;
		retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0x77);
		if (retval != STATUS_SUCCESS) {
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		rtsx_enable_bus_int(chip);
		retval = rtsx_read_phy_register(chip, 0x1C, ®);
		if (retval != STATUS_SUCCESS) {
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		reg &= 0xFFFE;
		retval = rtsx_write_phy_register(chip, 0x1C, reg);
		if (retval != STATUS_SUCCESS) {
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 241 | 85.77% | 1 | 50.00% | 
| joe perches | joe perches | 40 | 14.23% | 1 | 50.00% | 
 | Total | 281 | 100.00% | 2 | 100.00% | 
static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	int retval =  STATUS_SUCCESS;
	unsigned int lun = SCSI_LUN(srb);
	u8 cmd_type, mask, value, idx;
	u16 addr;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	switch (srb->cmnd[3]) {
	case INIT_BATCHCMD:
		rtsx_init_cmd(chip);
		break;
	case ADD_BATCHCMD:
		cmd_type = srb->cmnd[4];
		if (cmd_type > 2) {
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		addr = (srb->cmnd[5] << 8) | srb->cmnd[6];
		mask = srb->cmnd[7];
		value = srb->cmnd[8];
		rtsx_add_cmd(chip, cmd_type, addr, mask, value);
		break;
	case SEND_BATCHCMD:
		retval = rtsx_send_cmd(chip, 0, 1000);
		break;
	case GET_BATCHRSP:
		idx = srb->cmnd[4];
		value = *(rtsx_get_cmd_data(chip) + idx);
		if (scsi_bufflen(srb) < 1) {
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		rtsx_stor_set_xfer_buf(&value, 1, srb);
		scsi_set_resid(srb, 0);
		break;
	default:
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (retval != STATUS_SUCCESS) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 305 | 95.02% | 1 | 50.00% | 
| joe perches | joe perches | 16 | 4.98% | 1 | 50.00% | 
 | Total | 321 | 100.00% | 2 | 100.00% | 
static int suit_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	switch (srb->cmnd[3]) {
	case INIT_BATCHCMD:
	case ADD_BATCHCMD:
	case SEND_BATCHCMD:
	case GET_BATCHRSP:
		return rw_mem_cmd_buf(srb, chip);
	default:
		return TRANSPORT_ERROR;
	}
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 47 | 92.16% | 1 | 50.00% | 
| bhaktipriya shridhar | bhaktipriya shridhar | 4 | 7.84% | 1 | 50.00% | 
 | Total | 51 | 100.00% | 2 | 100.00% | 
static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned short addr, len, i;
	int retval;
	u8 *buf;
	u16 val;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
	if (len % 2)
		len -= len % 2;
	if (len) {
		buf = vmalloc(len);
		if (!buf) {
			rtsx_trace(chip);
			return TRANSPORT_ERROR;
		}
		retval = rtsx_force_power_on(chip, SSC_PDCTL);
		if (retval != STATUS_SUCCESS) {
			vfree(buf);
			set_sense_type(chip, SCSI_LUN(srb),
				SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		for (i = 0; i < len / 2; i++) {
			retval = rtsx_read_phy_register(chip, addr + i, &val);
			if (retval != STATUS_SUCCESS) {
				vfree(buf);
				set_sense_type(chip, SCSI_LUN(srb),
					SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
				rtsx_trace(chip);
				return TRANSPORT_FAILED;
			}
			buf[2*i] = (u8)(val >> 8);
			buf[2*i+1] = (u8)val;
		}
		len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb),
					len);
		rtsx_stor_set_xfer_buf(buf, len, srb);
		scsi_set_resid(srb, scsi_bufflen(srb) - len);
		vfree(buf);
	}
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 325 | 95.87% | 1 | 50.00% | 
| joe perches | joe perches | 14 | 4.13% | 1 | 50.00% | 
 | Total | 339 | 100.00% | 2 | 100.00% | 
static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned short addr, len, i;
	int retval;
	u8 *buf;
	u16 val;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
	if (len % 2)
		len -= len % 2;
	if (len) {
		len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb),
					len);
		buf = vmalloc(len);
		if (!buf) {
			rtsx_trace(chip);
			return TRANSPORT_ERROR;
		}
		rtsx_stor_get_xfer_buf(buf, len, srb);
		scsi_set_resid(srb, scsi_bufflen(srb) - len);
		retval = rtsx_force_power_on(chip, SSC_PDCTL);
		if (retval != STATUS_SUCCESS) {
			vfree(buf);
			set_sense_type(chip, SCSI_LUN(srb),
				SENSE_TYPE_MEDIA_WRITE_ERR);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		for (i = 0; i < len / 2; i++) {
			val = ((u16)buf[2*i] << 8) | buf[2*i+1];
			retval = rtsx_write_phy_register(chip, addr + i, val);
			if (retval != STATUS_SUCCESS) {
				vfree(buf);
				set_sense_type(chip, SCSI_LUN(srb),
					SENSE_TYPE_MEDIA_WRITE_ERR);
				rtsx_trace(chip);
				return TRANSPORT_FAILED;
			}
		}
		vfree(buf);
	}
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 318 | 95.50% | 1 | 33.33% | 
| joe perches | joe perches | 14 | 4.20% | 1 | 33.33% | 
| eva rachel retuya | eva rachel retuya | 1 | 0.30% | 1 | 33.33% | 
 | Total | 333 | 100.00% | 3 | 100.00% | 
static int erase_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned short addr;
	int retval;
	u8 mode;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	retval = rtsx_force_power_on(chip, SSC_PDCTL);
	if (retval != STATUS_SUCCESS) {
		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	mode = srb->cmnd[3];
	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
	if (mode == 0) {
		retval = spi_erase_eeprom_chip(chip);
		if (retval != STATUS_SUCCESS) {
			set_sense_type(chip, SCSI_LUN(srb),
				SENSE_TYPE_MEDIA_WRITE_ERR);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	} else if (mode == 1) {
		retval = spi_erase_eeprom_byte(chip, addr);
		if (retval != STATUS_SUCCESS) {
			set_sense_type(chip, SCSI_LUN(srb),
				SENSE_TYPE_MEDIA_WRITE_ERR);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	} else {
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 233 | 93.57% | 1 | 50.00% | 
| joe perches | joe perches | 16 | 6.43% | 1 | 50.00% | 
 | Total | 249 | 100.00% | 2 | 100.00% | 
static int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned short addr, len, i;
	int retval;
	u8 *buf;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
	buf = vmalloc(len);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	retval = rtsx_force_power_on(chip, SSC_PDCTL);
	if (retval != STATUS_SUCCESS) {
		vfree(buf);
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	for (i = 0; i < len; i++) {
		retval = spi_read_eeprom(chip, addr + i, buf + i);
		if (retval != STATUS_SUCCESS) {
			vfree(buf);
			set_sense_type(chip, SCSI_LUN(srb),
				SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
	len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
	rtsx_stor_set_xfer_buf(buf, len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - len);
	vfree(buf);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 273 | 95.12% | 1 | 50.00% | 
| joe perches | joe perches | 14 | 4.88% | 1 | 50.00% | 
 | Total | 287 | 100.00% | 2 | 100.00% | 
static int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned short addr, len, i;
	int retval;
	u8 *buf;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
	len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
	buf = vmalloc(len);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	rtsx_stor_get_xfer_buf(buf, len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - len);
	retval = rtsx_force_power_on(chip, SSC_PDCTL);
	if (retval != STATUS_SUCCESS) {
		vfree(buf);
		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	for (i = 0; i < len; i++) {
		retval = spi_write_eeprom(chip, addr + i, buf[i]);
		if (retval != STATUS_SUCCESS) {
			vfree(buf);
			set_sense_type(chip, SCSI_LUN(srb),
				SENSE_TYPE_MEDIA_WRITE_ERR);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
	vfree(buf);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 273 | 94.79% | 1 | 33.33% | 
| joe perches | joe perches | 14 | 4.86% | 1 | 33.33% | 
| eva rachel retuya | eva rachel retuya | 1 | 0.35% | 1 | 33.33% | 
 | Total | 288 | 100.00% | 3 | 100.00% | 
static int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	int retval;
	u8 addr, len, i;
	u8 *buf;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	addr = srb->cmnd[4];
	len = srb->cmnd[5];
	buf = vmalloc(len);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	retval = rtsx_force_power_on(chip, SSC_PDCTL);
	if (retval != STATUS_SUCCESS) {
		vfree(buf);
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	for (i = 0; i < len; i++) {
		retval = rtsx_read_efuse(chip, addr + i, buf + i);
		if (retval != STATUS_SUCCESS) {
			vfree(buf);
			set_sense_type(chip, SCSI_LUN(srb),
				SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
	len = (u8)min_t(unsigned int, scsi_bufflen(srb), len);
	rtsx_stor_set_xfer_buf(buf, len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - len);
	vfree(buf);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 243 | 94.55% | 1 | 50.00% | 
| joe perches | joe perches | 14 | 5.45% | 1 | 50.00% | 
 | Total | 257 | 100.00% | 2 | 100.00% | 
static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	int retval, result = TRANSPORT_GOOD;
	u16 val;
	u8 addr, len, i;
	u8 *buf;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	addr = srb->cmnd[4];
	len = srb->cmnd[5];
	len = (u8)min_t(unsigned int, scsi_bufflen(srb), len);
	buf = vmalloc(len);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	rtsx_stor_get_xfer_buf(buf, len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - len);
	retval = rtsx_force_power_on(chip, SSC_PDCTL);
	if (retval != STATUS_SUCCESS) {
		vfree(buf);
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	if (chip->asic_code) {
		retval = rtsx_read_phy_register(chip, 0x08, &val);
		if (retval != STATUS_SUCCESS) {
			vfree(buf);
			rtsx_trace(chip);
			return TRANSPORT_ERROR;
		}
		retval = rtsx_write_register(chip, PWR_GATE_CTRL,
					LDO3318_PWR_MASK, LDO_OFF);
		if (retval != STATUS_SUCCESS) {
			vfree(buf);
			rtsx_trace(chip);
			return TRANSPORT_ERROR;
		}
		wait_timeout(600);
		retval = rtsx_write_phy_register(chip, 0x08,
						0x4C00 | chip->phy_voltage);
		if (retval != STATUS_SUCCESS) {
			vfree(buf);
			rtsx_trace(chip);
			return TRANSPORT_ERROR;
		}
		retval = rtsx_write_register(chip, PWR_GATE_CTRL,
					LDO3318_PWR_MASK, LDO_ON);
		if (retval != STATUS_SUCCESS) {
			vfree(buf);
			rtsx_trace(chip);
			return TRANSPORT_ERROR;
		}
		wait_timeout(600);
	}
	retval = card_power_on(chip, SPI_CARD);
	if (retval != STATUS_SUCCESS) {
		vfree(buf);
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	wait_timeout(50);
	for (i = 0; i < len; i++) {
		retval = rtsx_write_efuse(chip, addr + i, buf[i]);
		if (retval != STATUS_SUCCESS) {
			set_sense_type(chip, SCSI_LUN(srb),
				SENSE_TYPE_MEDIA_WRITE_ERR);
			result = TRANSPORT_FAILED;
			rtsx_trace(chip);
			goto Exit;
		}
	}
Exit:
	vfree(buf);
	retval = card_power_off(chip, SPI_CARD);
	if (retval != STATUS_SUCCESS) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	if (chip->asic_code) {
		retval = rtsx_write_register(chip, PWR_GATE_CTRL,
					LDO3318_PWR_MASK, LDO_OFF);
		if (retval != STATUS_SUCCESS) {
			rtsx_trace(chip);
			return TRANSPORT_ERROR;
		}
		wait_timeout(600);
		retval = rtsx_write_phy_register(chip, 0x08, val);
		if (retval != STATUS_SUCCESS) {
			rtsx_trace(chip);
			return TRANSPORT_ERROR;
		}
		retval = rtsx_write_register(chip, PWR_GATE_CTRL,
					LDO3318_PWR_MASK, LDO_ON);
		if (retval != STATUS_SUCCESS) {
			rtsx_trace(chip);
			return TRANSPORT_ERROR;
		}
	}
	return result;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 508 | 89.59% | 1 | 33.33% | 
| joe perches | joe perches | 58 | 10.23% | 1 | 33.33% | 
| eva rachel retuya | eva rachel retuya | 1 | 0.18% | 1 | 33.33% | 
 | Total | 567 | 100.00% | 3 | 100.00% | 
static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	int retval;
	bool func_max;
	u8 func;
	u16 addr, len;
	u8 *buf;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	func = srb->cmnd[3];
	addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
	len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7];
	dev_dbg(rtsx_dev(chip), "%s: func = %d, addr = 0x%x, len = %d\n",
		__func__, func, addr, len);
	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
		func_max = true;
	else
		func_max = false;
	if (func > func_max) {
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	buf = vmalloc(len);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	retval = rtsx_read_cfg_seq(chip, func, addr, buf, len);
	if (retval != STATUS_SUCCESS) {
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
		vfree(buf);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	len = (u16)min_t(unsigned int, scsi_bufflen(srb), len);
	rtsx_stor_set_xfer_buf(buf, len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - len);
	vfree(buf);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 288 | 92.01% | 1 | 25.00% | 
| joe perches | joe perches | 14 | 4.47% | 1 | 25.00% | 
| fabio falzoi | fabio falzoi | 6 | 1.92% | 1 | 25.00% | 
| quentin lambert | quentin lambert | 5 | 1.60% | 1 | 25.00% | 
 | Total | 313 | 100.00% | 4 | 100.00% | 
static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	int retval;
	bool func_max;
	u8 func;
	u16 addr, len;
	u8 *buf;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	func = srb->cmnd[3];
	addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
	len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7];
	dev_dbg(rtsx_dev(chip), "%s: func = %d, addr = 0x%x\n",
		__func__, func, addr);
	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
		func_max = true;
	else
		func_max = false;
	if (func > func_max) {
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
	buf = vmalloc(len);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	rtsx_stor_get_xfer_buf(buf, len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - len);
	retval = rtsx_write_cfg_seq(chip, func, addr, buf, len);
	if (retval != STATUS_SUCCESS) {
		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
		vfree(buf);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	vfree(buf);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 287 | 91.99% | 1 | 25.00% | 
| joe perches | joe perches | 14 | 4.49% | 1 | 25.00% | 
| fabio falzoi | fabio falzoi | 6 | 1.92% | 1 | 25.00% | 
| quentin lambert | quentin lambert | 5 | 1.60% | 1 | 25.00% | 
 | Total | 312 | 100.00% | 4 | 100.00% | 
static int app_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	int result;
	switch (srb->cmnd[2]) {
	case PP_READ10:
	case PP_WRITE10:
		result = read_write(srb, chip);
		break;
	case READ_HOST_REG:
		result = read_host_reg(srb, chip);
		break;
	case WRITE_HOST_REG:
		result = write_host_reg(srb, chip);
		break;
	case GET_VAR:
		result = get_variable(srb, chip);
		break;
	case SET_VAR:
		result = set_variable(srb, chip);
		break;
	case DMA_READ:
	case DMA_WRITE:
		result = dma_access_ring_buffer(srb, chip);
		break;
	case READ_PHY:
		result = read_phy_register(srb, chip);
		break;
	case WRITE_PHY:
		result = write_phy_register(srb, chip);
		break;
	case ERASE_EEPROM2:
		result = erase_eeprom2(srb, chip);
		break;
	case READ_EEPROM2:
		result = read_eeprom2(srb, chip);
		break;
	case WRITE_EEPROM2:
		result = write_eeprom2(srb, chip);
		break;
	case READ_EFUSE:
		result = read_efuse(srb, chip);
		break;
	case WRITE_EFUSE:
		result = write_efuse(srb, chip);
		break;
	case READ_CFG:
		result = read_cfg_byte(srb, chip);
		break;
	case WRITE_CFG:
		result = write_cfg_byte(srb, chip);
		break;
	case SET_CHIP_MODE:
		result = set_chip_mode(srb, chip);
		break;
	case SUIT_CMD:
		result = suit_cmd(srb, chip);
		break;
	case GET_DEV_STATUS:
		result = get_dev_status(srb, chip);
		break;
	default:
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	return result;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 290 | 98.64% | 1 | 50.00% | 
| joe perches | joe perches | 4 | 1.36% | 1 | 50.00% | 
 | Total | 294 | 100.00% | 2 | 100.00% | 
static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	u8 rtsx_status[16];
	int buf_len;
	unsigned int lun = SCSI_LUN(srb);
	rtsx_status[0] = (u8)(chip->vendor_id >> 8);
	rtsx_status[1] = (u8)(chip->vendor_id);
	rtsx_status[2] = (u8)(chip->product_id >> 8);
	rtsx_status[3] = (u8)(chip->product_id);
	rtsx_status[4] = (u8)lun;
	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
		if (chip->lun2card[lun] == SD_CARD)
			rtsx_status[5] = 2;
		else
			rtsx_status[5] = 3;
	} else {
		if (chip->card_exist) {
			if (chip->card_exist & XD_CARD)
				rtsx_status[5] = 4;
			else if (chip->card_exist & SD_CARD)
				rtsx_status[5] = 2;
			else if (chip->card_exist & MS_CARD)
				rtsx_status[5] = 3;
			else
				rtsx_status[5] = 7;
		} else {
			rtsx_status[5] = 7;
		}
	}
	if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
		rtsx_status[6] = 2;
	else
		rtsx_status[6] = 1;
	rtsx_status[7] = (u8)(chip->product_id);
	rtsx_status[8] = chip->ic_version;
	if (check_card_exist(chip, lun))
		rtsx_status[9] = 1;
	else
		rtsx_status[9] = 0;
	if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
		rtsx_status[10] = 0;
	else
		rtsx_status[10] = 1;
	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
		if (chip->lun2card[lun] == SD_CARD)
			rtsx_status[11] = SD_CARD;
		else
			rtsx_status[11] = MS_CARD;
	} else {
		rtsx_status[11] = XD_CARD | SD_CARD | MS_CARD;
	}
	if (check_card_ready(chip, lun))
		rtsx_status[12] = 1;
	else
		rtsx_status[12] = 0;
	if (get_lun_card(chip, lun) == XD_CARD) {
		rtsx_status[13] = 0x40;
	} else if (get_lun_card(chip, lun) == SD_CARD) {
		struct sd_info *sd_card = &(chip->sd_card);
		rtsx_status[13] = 0x20;
		if (CHK_SD(sd_card)) {
			if (CHK_SD_HCXC(sd_card))
				rtsx_status[13] |= 0x04;
			if (CHK_SD_HS(sd_card))
				rtsx_status[13] |= 0x02;
		} else {
			rtsx_status[13] |= 0x08;
			if (CHK_MMC_52M(sd_card))
				rtsx_status[13] |= 0x02;
			if (CHK_MMC_SECTOR_MODE(sd_card))
				rtsx_status[13] |= 0x04;
		}
	} else if (get_lun_card(chip, lun) == MS_CARD) {
		struct ms_info *ms_card = &(chip->ms_card);
		if (CHK_MSPRO(ms_card)) {
			rtsx_status[13] = 0x38;
			if (CHK_HG8BIT(ms_card))
				rtsx_status[13] |= 0x04;
#ifdef SUPPORT_MSXC
			if (CHK_MSXC(ms_card))
				rtsx_status[13] |= 0x01;
#endif
		} else {
			rtsx_status[13] = 0x30;
		}
	} else {
		if (CHECK_LUN_MODE(chip, DEFAULT_SINGLE)) {
#ifdef SUPPORT_SDIO
			if (chip->sd_io && chip->sd_int)
				rtsx_status[13] = 0x60;
			else
				rtsx_status[13] = 0x70;
#else
			rtsx_status[13] = 0x70;
#endif
		} else {
			if (chip->lun2card[lun] == SD_CARD)
				rtsx_status[13] = 0x20;
			else
				rtsx_status[13] = 0x30;
		}
	}
	rtsx_status[14] = 0x78;
	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
		rtsx_status[15] = 0x83;
	else
		rtsx_status[15] = 0x82;
	buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(rtsx_status));
	rtsx_stor_set_xfer_buf(rtsx_status, buf_len, srb);
	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 752 | 100.00% | 1 | 100.00% | 
 | Total | 752 | 100.00% | 1 | 100.00% | 
static int get_card_bus_width(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned int lun = SCSI_LUN(srb);
	u8 card, bus_width;
	if (!check_card_ready(chip, lun)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	card = get_lun_card(chip, lun);
	if ((card == SD_CARD) || (card == MS_CARD)) {
		bus_width = chip->card_bus_width[lun];
	} else {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	scsi_set_resid(srb, 0);
	rtsx_stor_set_xfer_buf(&bus_width, scsi_bufflen(srb), srb);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 128 | 94.12% | 1 | 50.00% | 
| joe perches | joe perches | 8 | 5.88% | 1 | 50.00% | 
 | Total | 136 | 100.00% | 2 | 100.00% | 
static int spi_vendor_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	int result;
	unsigned int lun = SCSI_LUN(srb);
	u8 gpio_dir;
	if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	rtsx_force_power_on(chip, SSC_PDCTL);
	rtsx_read_register(chip, CARD_GPIO_DIR, &gpio_dir);
	rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir & 0x06);
	switch (srb->cmnd[2]) {
	case SCSI_SPI_GETSTATUS:
		result = spi_get_status(srb, chip);
		break;
	case SCSI_SPI_SETPARAMETER:
		result = spi_set_parameter(srb, chip);
		break;
	case SCSI_SPI_READFALSHID:
		result = spi_read_flash_id(srb, chip);
		break;
	case SCSI_SPI_READFLASH:
		result = spi_read_flash(srb, chip);
		break;
	case SCSI_SPI_WRITEFLASH:
		result = spi_write_flash(srb, chip);
		break;
	case SCSI_SPI_WRITEFLASHSTATUS:
		result = spi_write_flash_status(srb, chip);
		break;
	case SCSI_SPI_ERASEFLASH:
		result = spi_erase_flash(srb, chip);
		break;
	default:
		rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
	if (result != STATUS_SUCCESS) {
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 282 | 95.27% | 1 | 50.00% | 
| joe perches | joe perches | 14 | 4.73% | 1 | 50.00% | 
 | Total | 296 | 100.00% | 2 | 100.00% | 
static int vendor_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	int result;
	switch (srb->cmnd[1]) {
	case READ_STATUS:
		result = read_status(srb, chip);
		break;
	case READ_MEM:
		result = read_mem(srb, chip);
		break;
	case WRITE_MEM:
		result = write_mem(srb, chip);
		break;
	case READ_EEPROM:
		result = read_eeprom(srb, chip);
		break;
	case WRITE_EEPROM:
		result = write_eeprom(srb, chip);
		break;
	case TOGGLE_GPIO:
		result = toggle_gpio_cmd(srb, chip);
		break;
	case GET_SD_CSD:
		result = get_sd_csd(srb, chip);
		break;
	case GET_BUS_WIDTH:
		result = get_card_bus_width(srb, chip);
		break;
#ifdef _MSG_TRACE
	case TRACE_MSG:
		result = trace_msg_cmd(srb, chip);
		break;
#endif
	case SCSI_APP_CMD:
		result = app_cmd(srb, chip);
		break;
	case SPI_VENDOR_COMMAND:
		result = spi_vendor_cmd(srb, chip);
		break;
	default:
		set_sense_type(chip, SCSI_LUN(srb),
			SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	return result;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 198 | 98.02% | 1 | 50.00% | 
| joe perches | joe perches | 4 | 1.98% | 1 | 50.00% | 
 | Total | 202 | 100.00% | 2 | 100.00% | 
#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK)
void led_shine(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned int lun = SCSI_LUN(srb);
	u16 sec_cnt;
	if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10))
		sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
	else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) {
		sec_cnt = srb->cmnd[4];
		if (sec_cnt == 0)
			sec_cnt = 256;
	} else
		return;
	if (chip->rw_cap[lun] >= GPIO_TOGGLE_THRESHOLD) {
		toggle_gpio(chip, LED_GPIO);
		chip->rw_cap[lun] = 0;
	} else {
		chip->rw_cap[lun] += sec_cnt;
	}
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 153 | 92.73% | 1 | 50.00% | 
| akinobu mita | akinobu mita | 12 | 7.27% | 1 | 50.00% | 
 | Total | 165 | 100.00% | 2 | 100.00% | 
#endif
static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	struct ms_info *ms_card = &(chip->ms_card);
	unsigned int lun = SCSI_LUN(srb);
	bool quick_format;
	int retval;
	if (get_lun_card(chip, lun) != MS_CARD) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if ((srb->cmnd[3] != 0x4D) || (srb->cmnd[4] != 0x47) ||
		(srb->cmnd[5] != 0x66) || (srb->cmnd[6] != 0x6D) ||
		(srb->cmnd[7] != 0x74)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
		if (!check_card_ready(chip, lun) ||
				(get_card_size(chip, lun) == 0)) {
			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	if (srb->cmnd[8] & 0x01)
		quick_format = false;
	else
		quick_format = true;
	if (!(chip->card_ready & MS_CARD)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (chip->card_wp & MS_CARD) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (!CHK_MSPRO(ms_card)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	retval = mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format);
	if (retval != STATUS_SUCCESS) {
		set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	scsi_set_resid(srb, 0);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 347 | 91.32% | 1 | 33.33% | 
| joe perches | joe perches | 28 | 7.37% | 1 | 33.33% | 
| quentin lambert | quentin lambert | 5 | 1.32% | 1 | 33.33% | 
 | Total | 380 | 100.00% | 3 | 100.00% | 
#ifdef SUPPORT_PCGL_1P18
static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	struct ms_info *ms_card = &(chip->ms_card);
	unsigned int lun = SCSI_LUN(srb);
	u8 dev_info_id, data_len;
	u8 *buf;
	unsigned int buf_len;
	int i;
	if (!check_card_ready(chip, lun)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (get_lun_card(chip, lun) != MS_CARD) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if ((srb->cmnd[2] != 0xB0) || (srb->cmnd[4] != 0x4D) ||
		(srb->cmnd[5] != 0x53) || (srb->cmnd[6] != 0x49) ||
		(srb->cmnd[7] != 0x44)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	dev_info_id = srb->cmnd[3];
	if ((CHK_MSXC(ms_card) && (dev_info_id == 0x10)) ||
			(!CHK_MSXC(ms_card) && (dev_info_id == 0x13)) ||
			!CHK_MSPRO(ms_card)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (dev_info_id == 0x15)
		buf_len = data_len = 0x3A;
	else
		buf_len = data_len = 0x6A;
	buf = kmalloc(buf_len, GFP_KERNEL);
	if (!buf) {
		rtsx_trace(chip);
		return TRANSPORT_ERROR;
	}
	i = 0;
	/*  GET Memory Stick Media Information Response Header */
	buf[i++] = 0x00;		/* Data length MSB */
	buf[i++] = data_len;		/* Data length LSB */
	/* Device Information Type Code */
	if (CHK_MSXC(ms_card))
		buf[i++] = 0x03;
	else
		buf[i++] = 0x02;
	/* SGM bit */
	buf[i++] = 0x01;
	/* Reserved */
	buf[i++] = 0x00;
	buf[i++] = 0x00;
	buf[i++] = 0x00;
	/* Number of Device Information */
	buf[i++] = 0x01;
	/*  Device Information Body */
	/* Device Information ID Number */
	buf[i++] = dev_info_id;
	/* Device Information Length */
	if (dev_info_id == 0x15)
		data_len = 0x31;
	else
		data_len = 0x61;
	buf[i++] = 0x00;		/* Data length MSB */
	buf[i++] = data_len;		/* Data length LSB */
	/* Valid Bit */
	buf[i++] = 0x80;
	if ((dev_info_id == 0x10) || (dev_info_id == 0x13)) {
		/* System Information */
		memcpy(buf+i, ms_card->raw_sys_info, 96);
	} else {
		/* Model Name */
		memcpy(buf+i, ms_card->raw_model_name, 48);
	}
	rtsx_stor_set_xfer_buf(buf, buf_len, srb);
	if (dev_info_id == 0x15)
		scsi_set_resid(srb, scsi_bufflen(srb)-0x3C);
	else
		scsi_set_resid(srb, scsi_bufflen(srb)-0x6C);
	kfree(buf);
	return STATUS_SUCCESS;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 511 | 95.87% | 1 | 50.00% | 
| joe perches | joe perches | 22 | 4.13% | 1 | 50.00% | 
 | Total | 533 | 100.00% | 2 | 100.00% | 
#endif
static int ms_sp_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	int retval = TRANSPORT_ERROR;
	if (srb->cmnd[2] == MS_FORMAT)
		retval = ms_format_cmnd(srb, chip);
#ifdef SUPPORT_PCGL_1P18
	else if (srb->cmnd[2] == GET_MS_INFORMATION)
		retval = get_ms_information(srb, chip);
#endif
	return retval;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 70 | 100.00% | 1 | 100.00% | 
 | Total | 70 | 100.00% | 1 | 100.00% | 
#ifdef SUPPORT_CPRM
static int sd_extention_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	unsigned int lun = SCSI_LUN(srb);
	int result;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	sd_cleanup_work(chip);
	if (!check_card_ready(chip, lun)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (get_lun_card(chip, lun) != SD_CARD) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	switch (srb->cmnd[0]) {
	case SD_PASS_THRU_MODE:
		result = sd_pass_thru_mode(srb, chip);
		break;
	case SD_EXECUTE_NO_DATA:
		result = sd_execute_no_data(srb, chip);
		break;
	case SD_EXECUTE_READ:
		result = sd_execute_read_data(srb, chip);
		break;
	case SD_EXECUTE_WRITE:
		result = sd_execute_write_data(srb, chip);
		break;
	case SD_GET_RSP:
		result = sd_get_cmd_rsp(srb, chip);
		break;
	case SD_HW_RST:
		result = sd_hw_rst(srb, chip);
		break;
	default:
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	return result;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 229 | 95.02% | 1 | 50.00% | 
| joe perches | joe perches | 12 | 4.98% | 1 | 50.00% | 
 | Total | 241 | 100.00% | 2 | 100.00% | 
#endif
#ifdef SUPPORT_MAGIC_GATE
static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	struct ms_info *ms_card = &(chip->ms_card);
	unsigned int lun = SCSI_LUN(srb);
	int retval;
	u8 key_format;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	ms_cleanup_work(chip);
	if (!check_card_ready(chip, lun)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (get_lun_card(chip, lun) != MS_CARD) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (srb->cmnd[7] != KC_MG_R_PRO) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (!CHK_MSPRO(ms_card)) {
		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	key_format = srb->cmnd[10] & 0x3F;
	dev_dbg(rtsx_dev(chip), "key_format = 0x%x\n", key_format);
	switch (key_format) {
	case KF_GET_LOC_EKB:
		if ((scsi_bufflen(srb) == 0x41C) &&
			(srb->cmnd[8] == 0x04) &&
			(srb->cmnd[9] == 0x1C)) {
			retval = mg_get_local_EKB(srb, chip);
			if (retval != STATUS_SUCCESS) {
				rtsx_trace(chip);
				return TRANSPORT_FAILED;
			}
		} else {
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		break;
	case KF_RSP_CHG:
		if ((scsi_bufflen(srb) == 0x24) &&
			(srb->cmnd[8] == 0x00) &&
			(srb->cmnd[9] == 0x24)) {
			retval = mg_get_rsp_chg(srb, chip);
			if (retval != STATUS_SUCCESS) {
				rtsx_trace(chip);
				return TRANSPORT_FAILED;
			}
		} else {
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		break;
	case KF_GET_ICV:
		ms_card->mg_entry_num = srb->cmnd[5];
		if ((scsi_bufflen(srb) == 0x404) &&
			(srb->cmnd[8] == 0x04) &&
			(srb->cmnd[9] == 0x04) &&
			(srb->cmnd[2] == 0x00) &&
			(srb->cmnd[3] == 0x00) &&
			(srb->cmnd[4] == 0x00) &&
			(srb->cmnd[5] < 32)) {
			retval = mg_get_ICV(srb, chip);
			if (retval != STATUS_SUCCESS) {
				rtsx_trace(chip);
				return TRANSPORT_FAILED;
			}
		} else {
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		break;
	default:
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	scsi_set_resid(srb, 0);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 511 | 90.12% | 1 | 33.33% | 
| joe perches | joe perches | 50 | 8.82% | 1 | 33.33% | 
| fabio falzoi | fabio falzoi | 6 | 1.06% | 1 | 33.33% | 
 | Total | 567 | 100.00% | 3 | 100.00% | 
static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
	struct ms_info *ms_card = &(chip->ms_card);
	unsigned int lun = SCSI_LUN(srb);
	int retval;
	u8 key_format;
	rtsx_disable_aspm(chip);
	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
		rtsx_exit_ss(chip);
		wait_timeout(100);
	}
	rtsx_set_stat(chip, RTSX_STAT_RUN);
	ms_cleanup_work(chip);
	if (!check_card_ready(chip, lun)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (check_card_wp(chip, lun)) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (get_lun_card(chip, lun) != MS_CARD) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (srb->cmnd[7] != KC_MG_R_PRO) {
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	if (!CHK_MSPRO(ms_card)) {
		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	key_format = srb->cmnd[10] & 0x3F;
	dev_dbg(rtsx_dev(chip), "key_format = 0x%x\n", key_format);
	switch (key_format) {
	case KF_SET_LEAF_ID:
		if ((scsi_bufflen(srb) == 0x0C) &&
			(srb->cmnd[8] == 0x00) &&
			(srb->cmnd[9] == 0x0C)) {
			retval = mg_set_leaf_id(srb, chip);
			if (retval != STATUS_SUCCESS) {
				rtsx_trace(chip);
				return TRANSPORT_FAILED;
			}
		} else {
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		break;
	case KF_CHG_HOST:
		if ((scsi_bufflen(srb) == 0x0C) &&
			(srb->cmnd[8] == 0x00) &&
			(srb->cmnd[9] == 0x0C)) {
			retval = mg_chg(srb, chip);
			if (retval != STATUS_SUCCESS) {
				rtsx_trace(chip);
				return TRANSPORT_FAILED;
			}
		} else {
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		break;
	case KF_RSP_HOST:
		if ((scsi_bufflen(srb) == 0x0C) &&
			(srb->cmnd[8] == 0x00) &&
			(srb->cmnd[9] == 0x0C)) {
			retval = mg_rsp(srb, chip);
			if (retval != STATUS_SUCCESS) {
				rtsx_trace(chip);
				return TRANSPORT_FAILED;
			}
		} else {
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		break;
	case KF_SET_ICV:
		ms_card->mg_entry_num = srb->cmnd[5];
		if ((scsi_bufflen(srb) == 0x404) &&
			(srb->cmnd[8] == 0x04) &&
			(srb->cmnd[9] == 0x04) &&
			(srb->cmnd[2] == 0x00) &&
			(srb->cmnd[3] == 0x00) &&
			(srb->cmnd[4] == 0x00) &&
			(srb->cmnd[5] < 32)) {
			retval = mg_set_ICV(srb, chip);
			if (retval != STATUS_SUCCESS) {
				rtsx_trace(chip);
				return TRANSPORT_FAILED;
			}
		} else {
			set_sense_type(chip, lun,
				SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
		break;
	default:
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		rtsx_trace(chip);
		return TRANSPORT_FAILED;
	}
	scsi_set_resid(srb, 0);
	return TRANSPORT_GOOD;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 609 | 89.69% | 1 | 33.33% | 
| joe perches | joe perches | 64 | 9.43% | 1 | 33.33% | 
| fabio falzoi | fabio falzoi | 6 | 0.88% | 1 | 33.33% | 
 | Total | 679 | 100.00% | 3 | 100.00% | 
#endif
int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
#ifdef SUPPORT_SD_LOCK
	struct sd_info *sd_card = &(chip->sd_card);
#endif
	struct ms_info *ms_card = &(chip->ms_card);
	unsigned int lun = SCSI_LUN(srb);
	int result;
#ifdef SUPPORT_SD_LOCK
	if (sd_card->sd_erase_status) {
		/* Block all SCSI command except for
                 * REQUEST_SENSE and rs_ppstatus
                 */
		if (!((srb->cmnd[0] == VENDOR_CMND) &&
				(srb->cmnd[1] == SCSI_APP_CMD) &&
				(srb->cmnd[2] == GET_DEV_STATUS)) &&
				(srb->cmnd[0] != REQUEST_SENSE)) {
			/* Logical Unit Not Ready Format in Progress */
			set_sense_data(chip, lun, CUR_ERR,
				       0x02, 0, 0x04, 0x04, 0, 0);
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
#endif
	if ((get_lun_card(chip, lun) == MS_CARD) &&
			(ms_card->format_status == FORMAT_IN_PROGRESS)) {
		if ((srb->cmnd[0] != REQUEST_SENSE) &&
			(srb->cmnd[0] != INQUIRY)) {
			/* Logical Unit Not Ready Format in Progress */
			set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
					0, (u16)(ms_card->progress));
			rtsx_trace(chip);
			return TRANSPORT_FAILED;
		}
	}
	switch (srb->cmnd[0]) {
	case READ_10:
	case WRITE_10:
	case READ_6:
	case WRITE_6:
		result = read_write(srb, chip);
#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK)
		led_shine(srb, chip);
#endif
		break;
	case TEST_UNIT_READY:
		result = test_unit_ready(srb, chip);
		break;
	case INQUIRY:
		result = inquiry(srb, chip);
		break;
	case READ_CAPACITY:
		result = read_capacity(srb, chip);
		break;
	case START_STOP:
		result = start_stop_unit(srb, chip);
		break;
	case ALLOW_MEDIUM_REMOVAL:
		result = allow_medium_removal(srb, chip);
		break;
	case REQUEST_SENSE:
		result = request_sense(srb, chip);
		break;
	case MODE_SENSE:
	case MODE_SENSE_10:
		result = mode_sense(srb, chip);
		break;
	case 0x23:
		result = read_format_capacity(srb, chip);
		break;
	case VENDOR_CMND:
		result = vendor_cmnd(srb, chip);
		break;
	case MS_SP_CMND:
		result = ms_sp_cmnd(srb, chip);
		break;
#ifdef SUPPORT_CPRM
	case SD_PASS_THRU_MODE:
	case SD_EXECUTE_NO_DATA:
	case SD_EXECUTE_READ:
	case SD_EXECUTE_WRITE:
	case SD_GET_RSP:
	case SD_HW_RST:
		result = sd_extention_cmnd(srb, chip);
		break;
#endif
#ifdef SUPPORT_MAGIC_GATE
	case CMD_MSPRO_MG_RKEY:
		result = mg_report_key(srb, chip);
		break;
	case CMD_MSPRO_MG_SKEY:
		result = mg_send_key(srb, chip);
		break;
#endif
	case FORMAT_UNIT:
	case MODE_SELECT:
	case VERIFY:
		result = TRANSPORT_GOOD;
		break;
	default:
		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
		result = TRANSPORT_FAILED;
	}
	return result;
}
Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 512 | 98.46% | 1 | 50.00% | 
| joe perches | joe perches | 8 | 1.54% | 1 | 50.00% | 
 | Total | 520 | 100.00% | 2 | 100.00% | 
Overall Contributors
 | Person | Tokens | Prop | Commits | CommitProp | 
| micky ching | micky ching | 16547 | 95.26% | 1 | 11.11% | 
| joe perches | joe perches | 639 | 3.68% | 1 | 11.11% | 
| fabio falzoi | fabio falzoi | 116 | 0.67% | 2 | 22.22% | 
| quentin lambert | quentin lambert | 31 | 0.18% | 2 | 22.22% | 
| akinobu mita | akinobu mita | 22 | 0.13% | 1 | 11.11% | 
| eva rachel retuya | eva rachel retuya | 11 | 0.06% | 1 | 11.11% | 
| bhaktipriya shridhar | bhaktipriya shridhar | 4 | 0.02% | 1 | 11.11% | 
 | Total | 17370 | 100.00% | 9 | 100.00% | 
  
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.