11dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong/* Driver for Realtek RTS51xx USB card reader
21dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong *
31dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
41dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong *
51dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * This program is free software; you can redistribute it and/or modify it
61dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * under the terms of the GNU General Public License as published by the
71dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * Free Software Foundation; either version 2, or (at your option) any
81dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * later version.
91dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong *
101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * This program is distributed in the hope that it will be useful, but
111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * WITHOUT ANY WARRANTY; without even the implied warranty of
121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * General Public License for more details.
141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong *
151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * You should have received a copy of the GNU General Public License along
161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * with this program; if not, see <http://www.gnu.org/licenses/>.
171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong *
181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * Author:
191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong *   wwang (wei_wang@realsil.com.cn)
201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * Maintainer:
221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong *   Edwin Rong (edwin_rong@realsil.com.cn)
231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong */
251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include <linux/blkdev.h>
271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include <linux/kthread.h>
281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include <linux/sched.h>
291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include <linux/slab.h>
301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "debug.h"
321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "trace.h"
331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "rts51x.h"
341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "rts51x_transport.h"
351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "rts51x_scsi.h"
361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "rts51x_card.h"
371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "rts51x_chip.h"
381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "sd.h"
391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_CPRM
411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic inline int get_rsp_type(u8 rsp_code, u8 *rsp_type, int *rsp_len)
431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!rsp_type || !rsp_len)
451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		return STATUS_FAIL;
461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	switch (rsp_code) {
481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	case 0x03:
491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		*rsp_type = SD_RSP_TYPE_R0; /* no response */
501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		*rsp_len = 0;
511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	case 0x04:
541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		*rsp_type = SD_RSP_TYPE_R1; /* R1,R6(,R4,R5) */
551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		*rsp_len = 6;
561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	case 0x05:
591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		*rsp_type = SD_RSP_TYPE_R1b;	/* R1b */
601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		*rsp_len = 6;
611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	case 0x06:
641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		*rsp_type = SD_RSP_TYPE_R2;	/* R2 */
651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		*rsp_len = 17;
661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	case 0x07:
691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		*rsp_type = SD_RSP_TYPE_R3;	/* R3 */
701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		*rsp_len = 6;
711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	default:
741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		return STATUS_FAIL;
751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint soft_reset_sd_card(struct rts51x_chip *chip)
811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return reset_sd(chip);
831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint ext_sd_send_cmd_get_rsp(struct rts51x_chip *chip, u8 cmd_idx,
861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    u32 arg, u8 rsp_type, u8 *rsp, int rsp_len,
871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    int special_check)
881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int timeout = 50;
911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u16 reg_addr;
921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 buf[17], stat;
931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int len = 2;
941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int rty_cnt = 0;
951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("EXT SD/MMC CMD %d\n", cmd_idx);
971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (rsp_type == SD_RSP_TYPE_R1b)
991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		timeout = 3000;
1001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongRTY_SEND_CMD:
1021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
1041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx);
1061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8) (arg >> 24));
1071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8) (arg >> 16));
1081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8) (arg >> 8));
1091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8) arg);
1101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type);
1121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
1131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       0x01, PINGPONG_BUFFER);
1141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER,
1151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
1161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END,
1171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       SD_TRANSFER_END);
1181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, READ_REG_CMD, SD_STAT1, 0, 0);
1201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (CHECK_USB(chip, USB_20)) {
1221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (rsp_type == SD_RSP_TYPE_R2) {
1231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			for (reg_addr = PPBUF_BASE2;
1241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			     reg_addr < PPBUF_BASE2 + 16; reg_addr++) {
1251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0,
1261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       0);
1271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
1281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			len = 19;
1291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else if (rsp_type != SD_RSP_TYPE_R0) {
1301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			/* Read data from SD_CMDx registers */
1311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			for (reg_addr = SD_CMD0; reg_addr <= SD_CMD4;
1321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			     reg_addr++) {
1331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0,
1341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       0);
1351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
1361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			len = 8;
1371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
1381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			len = 3;
1391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
1401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, READ_REG_CMD, SD_CMD5, 0, 0);
1411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else {
1421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		len = 2;
1431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
1441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CR, 100);
1461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
1471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
1481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, len, timeout);
1501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (CHECK_SD_TRANS_FAIL(chip, retval)) {
1521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_sd_error(chip);
1531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval == STATUS_TIMEDOUT) {
1551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (rsp_type & SD_WAIT_BUSY_END) {
1561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				retval = sd_check_data0_status(chip);
1571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (retval != STATUS_SUCCESS)
1581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					TRACE_RET(chip, retval);
1591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
1601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
1611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
1621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
1631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (rsp_type == SD_RSP_TYPE_R0)
1651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		return STATUS_SUCCESS;
1661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (CHECK_USB(chip, USB_20)) {
1681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_read_rsp_buf(chip, 2, buf, len - 2);
1691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else {
1701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (rsp_type == SD_RSP_TYPE_R2) {
1711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			reg_addr = PPBUF_BASE2;
1721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			len = 16;
1731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
1741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			reg_addr = SD_CMD0;
1751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			len = 5;
1761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
1771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval =
1781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    rts51x_seq_read_register(chip, reg_addr,
1791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						     (unsigned short)len, buf);
1801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
1811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
1821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_READ_REG(chip, SD_CMD5, buf + len);
1831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
1841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	stat = chip->rsp_buf[1];
1851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((buf[0] & 0xC0) != 0)
1871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
1881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!(rsp_type & SD_NO_CHECK_CRC7)) {
1901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (stat & SD_CRC7_ERR) {
1911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (cmd_idx == WRITE_MULTIPLE_BLOCK)
1921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, STATUS_FAIL);
1931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (rty_cnt < SD_MAX_RETRY_COUNT) {
1941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				wait_timeout(20);
1951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				rty_cnt++;
1961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				goto RTY_SEND_CMD;
1971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			} else {
1981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, STATUS_FAIL);
1991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
2001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
2011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
2021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((cmd_idx == SELECT_CARD) || (cmd_idx == APP_CMD) ||
2041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    (cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) {
2051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if ((cmd_idx != STOP_TRANSMISSION) && (special_check == 0)) {
2061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (buf[1] & 0x80)
2071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, STATUS_FAIL);
2081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
2091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
2101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (buf[1] & 0x7D) {
2111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#else
2121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (buf[1] & 0x7F) {
2131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
2141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
2151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
2161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (buf[2] & 0xF8)
2171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
2181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (cmd_idx == SELECT_CARD) {
2201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (rsp_type == SD_RSP_TYPE_R2) {
2211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if ((buf[3] & 0x1E) != 0x04)
2221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					TRACE_RET(chip, STATUS_FAIL);
2231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			} else if (rsp_type == SD_RSP_TYPE_R2) {
2241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if ((buf[3] & 0x1E) != 0x03)
2251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					TRACE_RET(chip, STATUS_FAIL);
2261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
2271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
2281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
2291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (rsp && rsp_len)
2311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		memcpy(rsp, buf, rsp_len);
2321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
2341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
2351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
236aa2f92ae6b986934ff220eda6b5c91f4ee294b35Márton Némethint ext_sd_get_rsp(struct rts51x_chip *chip, int len, u8 *rsp, u8 rsp_type)
2371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
2381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval, rsp_len;
2391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u16 reg_addr;
2401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (rsp_type == SD_RSP_TYPE_R0)
2421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		return STATUS_SUCCESS;
2431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
2451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (rsp_type == SD_RSP_TYPE_R2) {
2471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16;
2481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		     reg_addr++) {
2491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
2501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
2511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rsp_len = 17;
2521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else if (rsp_type != SD_RSP_TYPE_R0) {
2531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		for (reg_addr = SD_CMD0; reg_addr <= SD_CMD4; reg_addr++)
2541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
2551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rsp_len = 6;
2561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
2571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, READ_REG_CMD, SD_CMD5, 0xFF, 0);
2581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CR, 100);
2601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
2611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
2621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, rsp_len, 100);
2641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
2661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
2671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (rsp) {
2691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		int min_len = (rsp_len < len) ? rsp_len : len;
2701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		memcpy(rsp, rts51x_get_rsp_data(chip), min_len);
2721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("min_len = %d\n", min_len);
2741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("Response in cmd buf: 0x%x 0x%x 0x%x 0x%x\n",
2751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       rsp[0], rsp[1], rsp[2], rsp[3]);
2761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
2771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
2791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
2801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
2821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			   u8 cmd_idx, u8 standby, u8 acmd, u8 rsp_code,
2831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			   u32 arg)
2841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
2851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct sd_info *sd_card = &(chip->sd_card);
2861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval, rsp_len;
2871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 rsp_type;
2881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = sd_switch_clock(chip);
2901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
2911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
2921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (sd_card->pre_cmd_err) {
2941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		sd_card->pre_cmd_err = 0;
2951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
2961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
2971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
2981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len);
2991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
3001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
3011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
3021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
3031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	sd_card->last_rsp_type = rsp_type;
3041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = sd_switch_clock(chip);
3061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
3071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
3081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
3091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
3101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (CHK_MMC_8BIT(sd_card)) {
3111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval =
3121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    rts51x_write_register(chip, SD_CFG1, 0x03,
3131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						  SD_BUS_WIDTH_8);
3141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS)
3151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, TRANSPORT_FAILED);
3161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
3171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval =
3181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    rts51x_write_register(chip, SD_CFG1, 0x03,
3191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						  SD_BUS_WIDTH_4);
3201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS)
3211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, TRANSPORT_FAILED);
3221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
3231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
3241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#else
3251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	/* Set H/W SD/MMC Bus Width */
3261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_write_register(chip, SD_CFG1, 0x03, SD_BUS_WIDTH_4);
3271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
3281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (standby) {
3301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = sd_select_card(chip, 0);
3311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
3321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
3331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
3341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (acmd) {
3361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval =
3371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
3381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					    SD_RSP_TYPE_R1, NULL, 0, 0);
3391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
3401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
3411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
3421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
3441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					 sd_card->rsp, rsp_len, 0);
3451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
3461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
3471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (standby) {
3491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = sd_select_card(chip, 1);
3501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
3511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
3521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
3531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
3541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	/* Get SD lock status */
3551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = sd_update_lock_status(chip);
3561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
3571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
3581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
3591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return TRANSPORT_GOOD;
3611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongSD_Execute_Cmd_Failed:
3631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	sd_card->pre_cmd_err = 1;
3641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
3651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	release_sd_card(chip);
3661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	do_reset_sd_card(chip);
3671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!(chip->card_ready & SD_CARD))
3681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
3691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	TRACE_RET(chip, TRANSPORT_FAILED);
3711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
3721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
3741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			     u8 cmd_idx, u8 cmd12, u8 standby,
3751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			     u8 acmd, u8 rsp_code, u32 arg, u32 data_len,
3761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			     void *data_buf, unsigned int buf_len, int use_sg)
3771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
3781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct sd_info *sd_card = &(chip->sd_card);
3791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval, rsp_len, i;
3801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int cmd13_checkbit = 0, read_err = 0;
3811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 rsp_type, bus_width;
3821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (sd_card->pre_cmd_err) {
3841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		sd_card->pre_cmd_err = 0;
3851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
3861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
3871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
3881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = sd_switch_clock(chip);
3901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
3911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
3921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len);
3931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
3941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
3951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
3961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
3971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	sd_card->last_rsp_type = rsp_type;
3981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = sd_switch_clock(chip);
4001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
4011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
4021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
4031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
4041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (CHK_MMC_8BIT(sd_card))
4051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			bus_width = SD_BUS_WIDTH_8;
4061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card))
4071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			bus_width = SD_BUS_WIDTH_4;
4081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		else
4091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			bus_width = SD_BUS_WIDTH_1;
4101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else {
4111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		bus_width = SD_BUS_WIDTH_4;
4121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
4131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("bus_width = %d\n", bus_width);
4141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#else
4151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	bus_width = SD_BUS_WIDTH_4;
4161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
4171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (data_len < 512) {
4191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
4201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						 SD_RSP_TYPE_R1, NULL, 0, 0);
4211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
4221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
4231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
4241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (standby) {
4261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = sd_select_card(chip, 0);
4271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
4281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
4291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
4301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (acmd) {
4321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval =
4331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
4341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					    SD_RSP_TYPE_R1, NULL, 0, 0);
4351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
4361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
4371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
4381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (data_len <= 512) {
4401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		int min_len;
4411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		u8 *buf;
4421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		u16 byte_cnt, blk_cnt;
4431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		u8 cmd[5];
4441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		unsigned int offset = 0;
4451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		void *sg = NULL;
4461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		byte_cnt = (u16) (data_len & 0x3FF);
4481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		blk_cnt = 1;
4491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		cmd[0] = 0x40 | cmd_idx;
4511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		cmd[1] = (u8) (arg >> 24);
4521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		cmd[2] = (u8) (arg >> 16);
4531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		cmd[3] = (u8) (arg >> 8);
4541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		cmd[4] = (u8) arg;
4551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		buf = kmalloc(data_len, GFP_KERNEL);
4571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (buf == NULL)
4581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, TRANSPORT_ERROR);
4591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt,
4611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				      blk_cnt, bus_width, buf, data_len, 2000);
4621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
4631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			read_err = 1;
4641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			kfree(buf);
4651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_write_register(chip, CARD_STOP,
4661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					      SD_STOP | SD_CLR_ERR,
4671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					      SD_STOP | SD_CLR_ERR);
4681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
4691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
4701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		min_len = min(data_len, buf_len);
4721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (use_sg)
4731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_access_sglist(buf, min_len, (void *)data_buf,
4741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					     &sg, &offset, TO_XFER_BUF);
4751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		else
4761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			memcpy(data_buf, buf, min_len);
4771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		kfree(buf);
4791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else if (!(data_len & 0x1FF)) {
4801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_init_cmd(chip);
4811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02);
4821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00);
4831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H,
4841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       0xFF, (u8) (data_len >> 17));
4851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L,
4861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       0xFF, (u8) ((data_len & 0x0001FE00) >> 9));
4871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD0, 0xFF,
4881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       0x40 | cmd_idx);
4891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD1, 0xFF,
4901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (u8) (arg >> 24));
4911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD2, 0xFF,
4921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (u8) (arg >> 16));
4931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD3, 0xFF,
4941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (u8) (arg >> 8));
4951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8) arg);
4961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x03, bus_width);
4971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type);
4981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512);
4991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
5001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
5011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER,
5021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       SD_TRANSFER_END, SD_TRANSFER_END);
5031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_send_cmd(chip, MODE_CDIR, 100);
5041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
5051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			read_err = 1;
5061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_ep0_write_register(chip, CARD_STOP,
5071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						  SD_STOP | SD_CLR_ERR,
5081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						  SD_STOP | SD_CLR_ERR);
5091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
5101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
5111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval =
5131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    rts51x_transfer_data_rcc(chip, RCV_BULK_PIPE(chip),
5141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					     data_buf, buf_len, use_sg, NULL,
5151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					     10000, STAGE_DI);
5161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
5171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			read_err = 1;
5181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_ep0_write_register(chip, CARD_STOP,
5191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						  SD_STOP | SD_CLR_ERR,
5201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						  SD_STOP | SD_CLR_ERR);
5211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
5221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
5231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_get_rsp(chip, 1, 500);
5241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (CHECK_SD_TRANS_FAIL(chip, retval)) {
5251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			read_err = 1;
5261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_ep0_write_register(chip, CARD_STOP,
5271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						  SD_STOP | SD_CLR_ERR,
5281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						  SD_STOP | SD_CLR_ERR);
5291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
5301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
5311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else {
5321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
5331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
5341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type);
5361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
5371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
5381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (standby) {
5401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = sd_select_card(chip, 1);
5411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
5421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
5431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
5441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (cmd12) {
5461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
5471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						 0, SD_RSP_TYPE_R1b, NULL, 0,
5481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						 0);
5491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
5501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
5511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
5521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (data_len < 512) {
5541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
5551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						 SD_RSP_TYPE_R1, NULL, 0, 0);
5561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
5571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
5581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
5601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
5611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
5621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (standby || cmd12)
5641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		cmd13_checkbit = 1;
5651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = 0; i < 3; i++) {
5671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval =
5681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
5691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					    SD_RSP_TYPE_R1, NULL, 0,
5701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					    cmd13_checkbit);
5711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval == STATUS_SUCCESS)
5721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
5731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
5741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
5751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
5761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return TRANSPORT_GOOD;
5781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongSD_Execute_Read_Cmd_Failed:
5801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	sd_card->pre_cmd_err = 1;
5811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
5821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (read_err)
5831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
5841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	release_sd_card(chip);
5851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	do_reset_sd_card(chip);
5861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!(chip->card_ready & SD_CARD))
5871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
5881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	TRACE_RET(chip, TRANSPORT_FAILED);
5901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
5911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
5931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			      u8 cmd_idx, u8 cmd12, u8 standby, u8 acmd,
5941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			      u8 rsp_code, u32 arg, u32 data_len,
5951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			      void *data_buf, unsigned int buf_len, int use_sg)
5961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
5971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct sd_info *sd_card = &(chip->sd_card);
5981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval, rsp_len;
5991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int cmd13_checkbit = 0, write_err = 0;
6001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 rsp_type;
6011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 i;
6021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
6031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int lock_cmd_fail = 0;
6041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 sd_lock_state = 0;
6051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 lock_cmd_type = 0;
6061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
6071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (sd_card->pre_cmd_err) {
6091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		sd_card->pre_cmd_err = 0;
6101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
6111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
6121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
6131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = sd_switch_clock(chip);
6151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
6161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
6171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
6181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (cmd_idx == LOCK_UNLOCK) {
6191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		sd_lock_state = sd_card->sd_lock_status;
6201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		sd_lock_state &= SD_LOCKED;
6211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
6221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
6231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len);
6251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
6261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
6271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
6281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
6291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	sd_card->last_rsp_type = rsp_type;
6301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = sd_switch_clock(chip);
6321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
6331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
6341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
6351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
6361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (CHK_MMC_8BIT(sd_card)) {
6371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval =
6381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    rts51x_write_register(chip, SD_CFG1, 0x03,
6391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						  SD_BUS_WIDTH_8);
6401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS)
6411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, TRANSPORT_FAILED);
6421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
6431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval =
6441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    rts51x_write_register(chip, SD_CFG1, 0x03,
6451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						  SD_BUS_WIDTH_4);
6461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS)
6471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, TRANSPORT_FAILED);
6481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
6491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
6501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#else
6511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_write_register(chip, SD_CFG1, 0x03, SD_BUS_WIDTH_4);
6521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
6531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (data_len < 512) {
6551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
6561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						 SD_RSP_TYPE_R1, NULL, 0, 0);
6571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
6581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
6591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
6601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (standby) {
6621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = sd_select_card(chip, 0);
6631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
6641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
6651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
6661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (acmd) {
6681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval =
6691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
6701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					    SD_RSP_TYPE_R1, NULL, 0, 0);
6711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
6721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
6731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
6741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
6761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					 sd_card->rsp, rsp_len, 0);
6771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
6781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
6791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (data_len <= 512) {
6811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		u8 *buf;
6821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		unsigned int offset = 0;
6831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		void *sg = NULL;
6841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		buf = kmalloc(data_len, GFP_KERNEL);
6861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (buf == NULL)
6871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, TRANSPORT_ERROR);
6881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (use_sg)
6901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_access_sglist(buf, data_len, (void *)data_buf,
6911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					     &sg, &offset, FROM_XFER_BUF);
6921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		else
6931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			memcpy(buf, data_buf, data_len);
6941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
6961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (cmd_idx == LOCK_UNLOCK)
6971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			lock_cmd_type = buf[0] & 0x0F;
6981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
6991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (data_len > 256) {
7011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_init_cmd(chip);
7021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			for (i = 0; i < 256; i++) {
7031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				rts51x_add_cmd(chip, WRITE_REG_CMD,
7041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       (u16) (PPBUF_BASE2 + i), 0xFF,
7051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       buf[i]);
7061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
7071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = rts51x_send_cmd(chip, MODE_C, 250);
7081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS) {
7091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				kfree(buf);
7101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
7111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
7121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_init_cmd(chip);
7141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			for (i = 256; i < data_len; i++) {
7151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				rts51x_add_cmd(chip, WRITE_REG_CMD,
7161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       (u16) (PPBUF_BASE2 + i), 0xFF,
7171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       buf[i]);
7181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
7191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = rts51x_send_cmd(chip, MODE_C, 250);
7201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS) {
7211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				kfree(buf);
7221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
7231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
7241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
7251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_init_cmd(chip);
7261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			for (i = 0; i < data_len; i++) {
7271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				rts51x_add_cmd(chip, WRITE_REG_CMD,
7281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       (u16) (PPBUF_BASE2 + i), 0xFF,
7291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       buf[i]);
7301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
7311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = rts51x_send_cmd(chip, MODE_C, 250);
7321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS) {
7331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				kfree(buf);
7341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
7351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
7361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
7371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		kfree(buf);
7391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_init_cmd(chip);
7411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF,
7431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (u8) ((data_len >> 8) & 0x03));
7441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF,
7451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (u8) data_len);
7461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0x00);
7471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 0x01);
7481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
7491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       PINGPONG_BUFFER);
7501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
7521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
7531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER,
7541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       SD_TRANSFER_END, SD_TRANSFER_END);
7551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_send_cmd(chip, MODE_CR, 100);
7571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
7581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
7591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_get_rsp(chip, 1, 250);
7611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (CHECK_SD_TRANS_FAIL(chip, retval))
7621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
7631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else if (!(data_len & 0x1FF)) {
7641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_init_cmd(chip);
7651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02);
7671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00);
7681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H,
7691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       0xFF, (u8) (data_len >> 17));
7701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L,
7711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       0xFF, (u8) ((data_len & 0x0001FE00) >> 9));
7721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512);
7741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
7761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
7771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER,
7781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       SD_TRANSFER_END, SD_TRANSFER_END);
7791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_send_cmd(chip, MODE_CDOR, 100);
7811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
7821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
7831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval =
7851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    rts51x_transfer_data_rcc(chip, SND_BULK_PIPE(chip),
7861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					     data_buf, buf_len, use_sg, NULL,
7871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					     10000, STAGE_DO);
7881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
7891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
7901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_get_rsp(chip, 1, 10000);
7921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (CHECK_SD_TRANS_FAIL(chip, retval))
7931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
7941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else {
7961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
7971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
7981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval < 0) {
8001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		write_err = 1;
8011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
8021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				      SD_STOP | SD_CLR_ERR);
8031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
8041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
8051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
8061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (cmd_idx == LOCK_UNLOCK) {
8071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (lock_cmd_type == SD_ERASE) {
8081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			sd_card->sd_erase_status = SD_UNDER_ERASING;
8091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			scsi_set_resid(srb, 0);
8101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			return TRANSPORT_GOOD;
8111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
8121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_init_cmd(chip);
8141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, CHECK_REG_CMD, SD_BUS_STAT, SD_DAT0_STATUS,
8151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       SD_DAT0_STATUS);
8161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_send_cmd(chip, MODE_CR, 250);
8171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
8181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
8191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_get_rsp(chip, 1, 200); /* Don't care return value */
8201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = sd_update_lock_status(chip);
8221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
8231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_DEBUGP("Lock command fail!\n");
8241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			lock_cmd_fail = 1;
8251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
8261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
8271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif /* SUPPORT_SD_LOCK */
8281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (standby) {
8301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = sd_select_card(chip, 1);
8311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
8321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
8331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
8341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (cmd12) {
8361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
8371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						 0, SD_RSP_TYPE_R1b, NULL, 0,
8381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						 0);
8391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
8401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
8411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
8421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (data_len < 512) {
8441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
8451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						 SD_RSP_TYPE_R1, NULL, 0, 0);
8461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
8471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
8481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
8501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
8511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
8521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (cmd12 || standby) {
8541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		/* There is CMD7 or CMD12 sent before CMD13 */
8551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		cmd13_checkbit = 1;
8561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
8571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = 0; i < 3; i++) {
8591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval =
8601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
8611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					    SD_RSP_TYPE_R1, NULL, 0,
8621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					    cmd13_checkbit);
8631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval == STATUS_SUCCESS)
8641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
8651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
8661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
8671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
8681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
8691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (cmd_idx == LOCK_UNLOCK) {
8701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (!lock_cmd_fail) {
8711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_DEBUGP("lock_cmd_type = 0x%x\n",
8721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				       lock_cmd_type);
8731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (lock_cmd_type & SD_CLR_PWD)
8741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				sd_card->sd_lock_status &= ~SD_PWD_EXIST;
8751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (lock_cmd_type & SD_SET_PWD)
8761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				sd_card->sd_lock_status |= SD_PWD_EXIST;
8771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
8781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("sd_lock_state = 0x%x,"
8801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				"sd_card->sd_lock_status = 0x%x\n",
8811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				sd_lock_state, sd_card->sd_lock_status);
8821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (sd_lock_state ^ (sd_card->sd_lock_status & SD_LOCKED)) {
8831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			sd_card->sd_lock_notify = 1;
8841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (sd_lock_state) {
8851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (sd_card->sd_lock_status &
8861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						SD_LOCK_1BIT_MODE) {
8871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					sd_card->sd_lock_status |=
8881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					    (SD_UNLOCK_POW_ON | SD_SDR_RST);
8891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					if (CHK_SD(sd_card)) {
8901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						retval = reset_sd(chip);
8911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						if (retval != STATUS_SUCCESS) {
8921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong							sd_card->sd_lock_status
8931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong							&= ~(SD_UNLOCK_POW_ON |
8941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong							      SD_SDR_RST);
8951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong							TRACE_GOTO(chip,
8961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong								   SD_Execute_Write_Cmd_Failed);
8971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						}
8981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					}
8991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					sd_card->sd_lock_status &=
9011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					    ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
9021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				}
9031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
9041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
9051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
9061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (lock_cmd_fail) {
9081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		scsi_set_resid(srb, 0);
9091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
9101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
9111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
9121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif /* SUPPORT_SD_LOCK */
9131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return TRANSPORT_GOOD;
9151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongSD_Execute_Write_Cmd_Failed:
9171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	sd_card->pre_cmd_err = 1;
9181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
9191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (write_err)
9201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
9211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	release_sd_card(chip);
9221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	do_reset_sd_card(chip);
9231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!(chip->card_ready & SD_CARD))
9241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
9251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	TRACE_RET(chip, TRANSPORT_FAILED);
9271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
9281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
9301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
9311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct sd_info *sd_card = &(chip->sd_card);
9321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	unsigned int lun = SCSI_LUN(srb);
9331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int len;
9341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 buf[18] = {
9351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x00,
9361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x00,
9371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x00,
9381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x0E,
9391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x00,		/* Version Number */
9401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x00,		/* WP | Media Type */
9411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x00,		/* RCA (Low byte) */
9421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x00,		/* RCA (High byte) */
9431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x53,		/* 'S' */
9441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x44,		/* 'D' */
9451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x20,		/* ' ' */
9461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x43,		/* 'C' */
9471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x61,		/* 'a' */
9481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x72,		/* 'r' */
9491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x64,		/* 'd' */
9501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x00,		/* Max LUN Number */
9511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x00,
9521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		0x00,
9531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	};
9541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	sd_card->pre_cmd_err = 0;
9561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!(CHK_BIT(chip->lun_mc, lun))) {
9581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		SET_BIT(chip->lun_mc, lun);
9591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
9601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
9611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
9621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3])
9641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    || (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5])
9651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    || (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7])
9661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    || (0x64 != srb->cmnd[8])) {
9671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
9681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
9691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
9701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	switch (srb->cmnd[1] & 0x0F) {
9721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	case 0:
9731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		sd_card->sd_pass_thru_en = 0;
9741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
9751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	case 1:
9771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		sd_card->sd_pass_thru_en = 1;
9781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
9791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	default:
9811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
9821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
9831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
9841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	/* 0x01:SD Memory Card; 0x02:Other Media; 0x03:Illegal Media; */
9861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	buf[5] = (1 == CHK_SD(sd_card)) ? 0x01 : 0x02;
9871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (chip->card_wp & SD_CARD)
9881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		buf[5] |= 0x80;
9891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	buf[6] = (u8) (sd_card->sd_addr >> 16);
9911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	buf[7] = (u8) (sd_card->sd_addr >> 24);
9921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	buf[15] = chip->max_lun;
9941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	len = min(18, (int)scsi_bufflen(srb));
9961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_set_xfer_buf(buf, len, srb);
9971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return TRANSPORT_GOOD;
9991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
10001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
10021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
10031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct sd_info *sd_card = &(chip->sd_card);
10041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	unsigned int lun = SCSI_LUN(srb);
10051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
10061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 cmd_idx, rsp_code;
10071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 standby = 0, acmd = 0;
10081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 arg;
10091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!sd_card->sd_pass_thru_en) {
10111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
10121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
10131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
10141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	cmd_idx = srb->cmnd[2] & 0x3F;
10161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (srb->cmnd[1] & 0x02)
10171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		standby = 1;
10181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (srb->cmnd[1] & 0x01)
10191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		acmd = 1;
10201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	arg = ((u32) srb->cmnd[3] << 24) | ((u32) srb->cmnd[4] << 16) |
10221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    ((u32) srb->cmnd[5] << 8) | srb->cmnd[6];
10231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rsp_code = srb->cmnd[10];
10251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval =
10271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    ext_sd_execute_no_data(chip, lun, cmd_idx, standby, acmd, rsp_code,
10281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				   arg);
10291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	scsi_set_resid(srb, 0);
10301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return retval;
10311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
10321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
10341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
10351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct sd_info *sd_card = &(chip->sd_card);
10361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
10371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	unsigned int lun = SCSI_LUN(srb);
10381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 cmd_idx, rsp_code, send_cmd12 = 0, standby = 0, acmd = 0;
10391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 arg, data_len;
10401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!sd_card->sd_pass_thru_en) {
10421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
10431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
10441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
10451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	cmd_idx = srb->cmnd[2] & 0x3F;
10471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (srb->cmnd[1] & 0x04)
10481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		send_cmd12 = 1;
10491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (srb->cmnd[1] & 0x02)
10501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		standby = 1;
10511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (srb->cmnd[1] & 0x01)
10521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		acmd = 1;
10531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	arg = ((u32) srb->cmnd[3] << 24) | ((u32) srb->cmnd[4] << 16) |
10551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    ((u32) srb->cmnd[5] << 8) | srb->cmnd[6];
10561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	data_len =
10581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    ((u32) srb->cmnd[7] << 16) | ((u32) srb->cmnd[8] << 8) |
10591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    srb->cmnd[9];
10601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rsp_code = srb->cmnd[10];
10611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval =
10631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    ext_sd_execute_read_data(chip, lun, cmd_idx, send_cmd12, standby,
10641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				     acmd, rsp_code, arg, data_len,
10651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				     scsi_sglist(srb), scsi_bufflen(srb),
10661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				     scsi_sg_count(srb));
10671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	scsi_set_resid(srb, 0);
10681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return retval;
10691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
10701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
10721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
10731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct sd_info *sd_card = &(chip->sd_card);
10741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
10751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	unsigned int lun = SCSI_LUN(srb);
10761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 cmd_idx, rsp_code, send_cmd12 = 0, standby = 0, acmd = 0;
10771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 data_len, arg;
10781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!sd_card->sd_pass_thru_en) {
10801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
10811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
10821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
10831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	cmd_idx = srb->cmnd[2] & 0x3F;
10851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (srb->cmnd[1] & 0x04)
10861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		send_cmd12 = 1;
10871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (srb->cmnd[1] & 0x02)
10881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		standby = 1;
10891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (srb->cmnd[1] & 0x01)
10901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		acmd = 1;
10911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	data_len =
10931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    ((u32) srb->cmnd[7] << 16) | ((u32) srb->cmnd[8] << 8) |
10941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    srb->cmnd[9];
10951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	arg =
10961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    ((u32) srb->cmnd[3] << 24) | ((u32) srb->cmnd[4] << 16) |
10971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    ((u32) srb->cmnd[5] << 8) | srb->cmnd[6];
10981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rsp_code = srb->cmnd[10];
10991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval =
11011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    ext_sd_execute_write_data(chip, lun, cmd_idx, send_cmd12, standby,
11021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				      acmd, rsp_code, arg, data_len,
11031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				      scsi_sglist(srb), scsi_bufflen(srb),
11041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				      scsi_sg_count(srb));
11051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	scsi_set_resid(srb, 0);
11061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return retval;
11071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
11081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
11101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
11111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct sd_info *sd_card = &(chip->sd_card);
11121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	unsigned int lun = SCSI_LUN(srb);
11131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int count;
11141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u16 data_len;
11151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!sd_card->sd_pass_thru_en) {
11171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
11181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
11191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
11201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (sd_card->pre_cmd_err) {
11221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		sd_card->pre_cmd_err = 0;
11231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
11241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
11251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
11261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	data_len = ((u16) srb->cmnd[7] << 8) | srb->cmnd[8];
11281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) {
11301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
11311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
11321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) {
11331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		count = (data_len < 17) ? data_len : 17;
11341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else {
11351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		count = (data_len < 6) ? data_len : 6;
11361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
11371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_set_xfer_buf(sd_card->rsp, count, srb);
11381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("Response length: %d\n", data_len);
11401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n",
11411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       sd_card->rsp[0], sd_card->rsp[1], sd_card->rsp[2],
11421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       sd_card->rsp[3]);
11431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	scsi_set_resid(srb, 0);
11451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return TRANSPORT_GOOD;
11461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
11471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip)
11491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
11501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct sd_info *sd_card = &(chip->sd_card);
11511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	unsigned int lun = SCSI_LUN(srb);
11521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
11531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!sd_card->sd_pass_thru_en) {
11551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
11561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
11571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
11581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (sd_card->pre_cmd_err) {
11601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		sd_card->pre_cmd_err = 0;
11611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
11621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
11631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
11641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3])
11661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    || (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5])
11671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    || (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7])
11681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    || (0x64 != srb->cmnd[8])) {
11691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
11701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
11711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
11721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	switch (srb->cmnd[1] & 0x0F) {
11741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	case 0:
11751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		/* SD Card Power Off -> ON and Initialization */
11761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
11771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (0x64 == srb->cmnd[9]) {
11781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			/* Command Mode */
11791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			sd_card->sd_lock_status |= SD_SDR_RST;
11801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
11811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif /* SUPPORT_SD_LOCK */
11821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = reset_sd_card(chip);
11831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
11841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
11851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			sd_card->sd_lock_status &= ~SD_SDR_RST;
11861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
11871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
11881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			sd_card->pre_cmd_err = 1;
11891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, TRANSPORT_FAILED);
11901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
11911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_SD_LOCK
11921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		sd_card->sd_lock_status &= ~SD_SDR_RST;
11931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
11941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
11951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	case 1:
11971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		/* reset CMD(CMD0) and Initialization
11981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		 * (without SD Card Power Off -> ON) */
11991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = soft_reset_sd_card(chip);
12001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
12011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
12021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			sd_card->pre_cmd_err = 1;
12031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, TRANSPORT_FAILED);
12041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
12051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
12061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	default:
12081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
12091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, TRANSPORT_FAILED);
12101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
12111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	scsi_set_resid(srb, 0);
12131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return TRANSPORT_GOOD;
12141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
12151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
1216