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>
29eae5bcc278655182a1469d2702c0bfdf09ba6f94Greg Kroah-Hartman#include <linux/vmalloc.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 "xd.h"
381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_build_l2p_tbl(struct rts51x_chip *chip, int zone_no);
401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_init_page(struct rts51x_chip *chip, u32 phy_blk, u16 logoff,
411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			u8 start_page, u8 end_page);
421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic inline void xd_set_err_code(struct rts51x_chip *chip, u8 err_code)
441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_card->err_code = err_code;
481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic inline int xd_check_err_code(struct rts51x_chip *chip, u8 err_code)
511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return (xd_card->err_code == err_code);
551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_set_init_para(struct rts51x_chip *chip)
581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (chip->asic_code)
631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->xd_clock = 47;
641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	else
651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->xd_clock = CLK_50;
661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = switch_clock(chip, xd_card->xd_clock);
681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_switch_clock(struct rts51x_chip *chip)
751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_select_card(chip, XD_CARD);
801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = switch_clock(chip, xd_card->xd_clock);
841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_read_id(struct rts51x_chip *chip, u8 id_cmd, u8 *id_buf,
911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		      u8 buf_len)
921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval, i;
941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, id_cmd);
981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_START | XD_READ_ID);
1001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
1011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_END);
1021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = 0; i < 4; i++) {
1041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, READ_REG_CMD, (u16) (XD_ADDRESS1 + i), 0,
1051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       0);
1061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
1071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CR, 20);
1091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
1101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
1111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, 5, 20);
1131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
1151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
1161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
1171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
1181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (id_buf && buf_len) {
1201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (buf_len > 4)
1211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			buf_len = 4;
1221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_read_rsp_buf(chip, 1, id_buf, buf_len);
1231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
1241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
1261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
1271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic void xd_assign_phy_addr(struct rts51x_chip *chip, u32 addr, u8 mode)
1291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
1301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
1311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	switch (mode) {
1331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	case XD_RW_ADDR:
1341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, 0);
1351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF,
1361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (u8) addr);
1371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, 0xFF,
1381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (u8) (addr >> 8));
1391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS3, 0xFF,
1401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (u8) (addr >> 16));
1411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF,
1421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       xd_card->addr_cycle | XD_CALC_ECC |
1431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       XD_BA_NO_TRANSFORM);
1441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
1451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	case XD_ERASE_ADDR:
1471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF,
1481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (u8) addr);
1491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF,
1501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (u8) (addr >> 8));
1511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, 0xFF,
1521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (u8) (addr >> 16));
1531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF,
1541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (xd_card->addr_cycle - 1) |
1551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       XD_CALC_ECC | XD_BA_NO_TRANSFORM);
1561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
1571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	default:
1591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
1601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
1611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
1621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_read_redundant(struct rts51x_chip *chip, u32 page_addr, u8 *buf,
1641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			     int buf_len)
1651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
1661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval, i;
1671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
1691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
1711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
1731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_START | XD_READ_REDUNDANT);
1741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
1751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_END);
1761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = 0; i < 6; i++) {
1781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, READ_REG_CMD, (u16) (XD_PAGE_STATUS + i),
1791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       0, 0);
1801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
1811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = 0; i < 4; i++) {
1821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, READ_REG_CMD, (u16) (XD_RESERVED0 + i), 0,
1831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       0);
1841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
1851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, READ_REG_CMD, XD_PARITY, 0, 0);
1861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CR, 100);
1881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
1891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
1901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, 11, 500);
1921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
1941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
1951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
1961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
1971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
1981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (buf && buf_len) {
1991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (buf_len > 11)
2001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			buf_len = 11;
2011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_read_rsp_buf(chip, 1, buf, buf_len);
2021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
2031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
2051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
2061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_read_data_from_ppb(struct rts51x_chip *chip, int offset, u8 *buf,
2081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				 int buf_len)
2091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
2101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval, i;
2111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!buf || (buf_len <= 0))
2131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
2141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
2161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = 0; i < buf_len; i++) {
2181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + offset + i, 0,
2191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       0);
2201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
2211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CR, 100);
2231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
2241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
2251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, buf_len, 200);
2271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
2281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
2291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_read_rsp_buf(chip, 0, buf, buf_len);
2311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
2331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
2341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_read_cis(struct rts51x_chip *chip, u32 page_addr, u8 *buf,
2361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       int buf_len)
2371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
2381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
2391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 reg;
2401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!buf || (buf_len < 10))
2421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
2431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
2451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
2471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
2491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       PINGPONG_BUFFER);
2501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
2511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
2521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS);
2531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
2551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_START | XD_READ_PAGES);
2561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
2571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_END | XD_PPB_EMPTY,
2581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_END | XD_PPB_EMPTY);
2591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CR, 100);
2611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
2621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
2631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, 1, 500);
2651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval == STATUS_TIMEDOUT) {
2661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
2671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
2681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
2691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_READ_REG(chip, XD_PAGE_STATUS, &reg);
2711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (reg != XD_GPG) {
2721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
2731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
2741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
2751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_READ_REG(chip, XD_CTL, &reg);
2771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!(reg & XD_ECC1_ERROR) || !(reg & XD_ECC1_UNCORRECTABLE)) {
2791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_read_data_from_ppb(chip, 0, buf, buf_len);
2801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
2811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
2821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (reg & XD_ECC1_ERROR) {	/* correctable error */
2831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			u8 ecc_bit, ecc_byte;
2841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_READ_REG(chip, XD_ECC_BIT1, &ecc_bit);
2861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_READ_REG(chip, XD_ECC_BYTE1, &ecc_byte);
2871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
2881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_DEBUGP("ECC_BIT1 = 0x%x, ECC_BYTE1 = 0x%x\n",
2891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				       ecc_bit, ecc_byte);
2901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (ecc_byte < buf_len) {
2911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				RTS51X_DEBUGP("Before correct: 0x%x\n",
2921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       buf[ecc_byte]);
2931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				buf[ecc_byte] ^= (1 << ecc_bit);
2941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				RTS51X_DEBUGP("After correct: 0x%x\n",
2951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       buf[ecc_byte]);
2961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
2971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
2981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else if (!(reg & XD_ECC2_ERROR) || !(reg & XD_ECC2_UNCORRECTABLE)) {
2991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_WRITE_REG(chip, CARD_STOP, XD_STOP | XD_CLR_ERR,
3001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				 XD_STOP | XD_CLR_ERR);
3011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_read_data_from_ppb(chip, 256, buf, buf_len);
3031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
3041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
3051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (reg & XD_ECC2_ERROR) {
3061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			u8 ecc_bit, ecc_byte;
3071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_READ_REG(chip, XD_ECC_BIT2, &ecc_bit);
3091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_READ_REG(chip, XD_ECC_BYTE2, &ecc_byte);
3101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_DEBUGP("ECC_BIT2 = 0x%x, ECC_BYTE2 = 0x%x\n",
3121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				       ecc_bit, ecc_byte);
3131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (ecc_byte < buf_len) {
3141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				RTS51X_DEBUGP("Before correct: 0x%x\n",
3151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       buf[ecc_byte]);
3161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				buf[ecc_byte] ^= (1 << ecc_bit);
3171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				RTS51X_DEBUGP("After correct: 0x%x\n",
3181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       buf[ecc_byte]);
3191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
3201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
3211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else {
3221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
3231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
3241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
3251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
3271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
3281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic void xd_pull_ctl_disable(struct rts51x_chip *chip)
3301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
3311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (CHECK_PKG(chip, LQFP48)) {
3321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
3331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
3341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
3351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
3361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
3371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5);
3381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else {
3391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65);
3401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
3411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
3421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
3431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56);
3441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59);
3451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
3461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
3471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic void xd_pull_ctl_enable(struct rts51x_chip *chip)
3491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
3501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (CHECK_PKG(chip, LQFP48)) {
3511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA);
3521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
3531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
3541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
3551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
3561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5);
3571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else {
3581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA5);
3591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x59);
3601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
3611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
3621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
3631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59);
3641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
3651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
3661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int reset_xd(struct rts51x_chip *chip)
3681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
3691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
3701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval, i, j;
3711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 id_buf[4], redunt[11];
3721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_select_card(chip, XD_CARD);
3741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
3751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
3761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
3781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 0xFF,
3801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_PGSTS_NOT_FF);
3811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (chip->asic_code)
3821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_pull_ctl_disable(chip);
3831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	else
3841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
3851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN3));
3861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
3871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!chip->option.FT2_fast_mode) {
3881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_INIT, XD_NO_AUTO_PWR_OFF,
3891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       0);
3901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (CHECK_PKG(chip, LQFP48) ||
3911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				chip->option.rts5129_D3318_off_enable) {
3921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL,
3931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				       DV3318_AUTO_PWR_OFF,
3941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				       DV3318_AUTO_PWR_OFF);
3951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
3961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
3971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0);
3981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!chip->option.FT2_fast_mode) {
3991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK,
4001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       POWER_OFF);
4011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
4021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_C, 100);
4041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
4051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
4061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!chip->option.FT2_fast_mode) {
4071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SD_XD_IO_FOLLOW_PWR
4081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (CHECK_PKG(chip, LQFP48)
4091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    || chip->option.rts5129_D3318_off_enable) {
4101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_write_register(chip, CARD_PWR_CTL,
4111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					LDO_OFF, LDO_OFF);
4121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
4131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
4141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		wait_timeout(250);
4161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SD_XD_IO_FOLLOW_PWR
4181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (CHECK_PKG(chip, LQFP48)
4191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    || chip->option.rts5129_D3318_off_enable) {
4201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_init_cmd(chip);
4211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (chip->asic_code) {
4221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_pull_ctl_enable(chip);
4231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			} else {
4241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				rts51x_add_cmd(chip, WRITE_REG_CMD,
4251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					FPGA_PULL_CTL, 0xFF,
4261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					(FPGA_XD_PULL_CTL_EN1 &
4271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						FPGA_XD_PULL_CTL_EN2));
4281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
4291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = rts51x_send_cmd(chip, MODE_C, 100);
4301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS)
4311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, STATUS_FAIL);
4321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
4331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
4341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = card_power_on(chip, XD_CARD);
4361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
4371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
4381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_OCP
4391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		wait_timeout(50);
4401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_get_card_status(chip, &(chip->card_status));
4411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		chip->ocp_stat = (chip->card_status >> 4) & 0x03;
4421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (chip->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) {
4441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_DEBUGP("Over current, OCPSTAT is 0x%x\n",
4451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				       chip->ocp_stat);
4461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
4471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
4481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
4491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
4501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
4521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (chip->asic_code)
4541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_pull_ctl_enable(chip);
4551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	else
4561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
4571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN2));
4581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN,
4591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_OUTPUT_EN);
4601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CTL, XD_CE_DISEN, XD_CE_DISEN);
4611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_C, 100);
4631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
4641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
4651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!chip->option.FT2_fast_mode)
4671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		wait_timeout(200);
4681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = xd_set_init_para(chip);
4701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
4711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
4721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	/* Read ID to check if the timing setting is right */
4731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = 0; i < 4; i++) {
4741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		u8 xd_dat, xd_ctl;
4751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST)
4771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
4781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_init_cmd(chip);
4801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_DTCTL, 0xFF,
4811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP *
4821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			(2 + i + chip->option.xd_rw_step)
4831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			+ XD_TIME_RWN_STEP * (i + chip->option.xd_rwn_step));
4841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CATCTL, 0xFF,
4851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * (4 +
4861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			i) + XD_TIME_RWN_STEP * (3 + i));
4871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
4891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       XD_TRANSFER_START | XD_RESET);
4901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
4911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       XD_TRANSFER_END, XD_TRANSFER_END);
4921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
4941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0);
4951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
4961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_send_cmd(chip, MODE_CR, 100);
4971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
4981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_clear_xd_error(chip);
4991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
5001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
5011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_get_rsp(chip, 3, 100);
5031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
5041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_clear_xd_error(chip);
5051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
5061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
5071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_dat = chip->rsp_buf[1];
5091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_ctl = chip->rsp_buf[2];
5101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("XD_DAT: 0x%x, XD_CTL: 0x%x\n", xd_dat, xd_ctl);
5111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (((xd_dat & READY_FLAG) != READY_STATE)
5131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    || !(xd_ctl & XD_RDY))
5141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			continue;
5151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_read_id(chip, READ_ID, id_buf, 4);
5171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
5181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
5191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("READ_ID: 0x%x 0x%x 0x%x 0x%x\n",
5211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
5221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->device_code = id_buf[1];
5241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		switch (xd_card->device_code) {
5261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		case XD_4M_X8_512_1:
5271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		case XD_4M_X8_512_2:
5281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->block_shift = 4;	/* 16 pages per block */
5291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->page_off = 0x0F;
5301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->addr_cycle = 3;
5311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->zone_cnt = 1;
5321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->capacity = 8000;	/* 500 * 2 ^ 4 */
5331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_SET_4MB(xd_card);
5341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
5351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		case XD_8M_X8_512:
5361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->block_shift = 4;
5371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->page_off = 0x0F;
5381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->addr_cycle = 3;
5391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->zone_cnt = 1;
5401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->capacity = 16000;	/* 1000 * 2 ^ 4 */
5411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
5421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		case XD_16M_X8_512:
5431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_PAGE_512(xd_card);	/* 32 pages per block */
5441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->addr_cycle = 3;
5451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->zone_cnt = 1;
5461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->capacity = 32000;	/* 1000 * 2 ^ 5 */
5471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
5481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		case XD_32M_X8_512:
5491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_PAGE_512(xd_card);
5501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->addr_cycle = 3;
5511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->zone_cnt = 2;
5521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->capacity = 64000;	/* 2000 * 2 ^ 5 */
5531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
5541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		case XD_64M_X8_512:
5551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_PAGE_512(xd_card);
5561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->addr_cycle = 4;
5571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->zone_cnt = 4;
5581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->capacity = 128000;	/* 4000 * 2 ^ 5 */
5591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
5601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		case XD_128M_X8_512:
5611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_PAGE_512(xd_card);
5621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->addr_cycle = 4;
5631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->zone_cnt = 8;
5641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->capacity = 256000;	/* 8000 * 2 ^ 5 */
5651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
5661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		case XD_256M_X8_512:
5671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_PAGE_512(xd_card);
5681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->addr_cycle = 4;
5691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->zone_cnt = 16;
5701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->capacity = 512000;	/* 16000 * 2 ^ 5 */
5711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
5721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		case XD_512M_X8:
5731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_PAGE_512(xd_card);
5741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->addr_cycle = 4;
5751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->zone_cnt = 32;
5761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->capacity = 1024000;	/* 32000 * 2 ^ 5 */
5771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
5781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		case xD_1G_X8_512:
5791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_PAGE_512(xd_card);
5801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->addr_cycle = 4;
5811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->zone_cnt = 64;
5821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->capacity = 2048000;	/* 64000 * 2 ^ 5 */
5831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
5841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		case xD_2G_X8_512:
5851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_PAGE_512(xd_card);
5861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->addr_cycle = 4;
5871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->zone_cnt = 128;
5881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_card->capacity = 4096000;	/* 128000 * 2 ^ 5 */
5891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
5901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		default:
5911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			continue;
5921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
5931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
5941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		/* Confirm timing setting */
5951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		for (j = 0; j < 10; j++) {
5961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = xd_read_id(chip, READ_ID, id_buf, 4);
5971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS)
5981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, retval);
5991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (id_buf[1] != xd_card->device_code)
6011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				break;
6021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
6031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		/* Current timing pass */
6051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (j == 10)
6061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
6071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
6081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (i == 4) {
6101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->block_shift = 0;
6111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->page_off = 0;
6121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->addr_cycle = 0;
6131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->capacity = 0;
6141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
6161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
6171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = xd_read_id(chip, READ_xD_ID, id_buf, 4);
6191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
6201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
6211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("READ_xD_ID: 0x%x 0x%x 0x%x 0x%x\n",
6221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
6231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (id_buf[2] != XD_ID_CODE)
6241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
6251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	/* Search CIS block */
6271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = 0; i < 24; i++) {
6281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		u32 page_addr;
6291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST)
6311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
6321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		page_addr = (u32) i << xd_card->block_shift;
6341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		for (j = 0; j < 3; j++) {
6361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = xd_read_redundant(chip, page_addr, redunt, 11);
6371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval == STATUS_SUCCESS)
6381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				break;
6391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
6401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (j == 3)
6411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			continue;
6421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (redunt[BLOCK_STATUS] != XD_GBLK)
6441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			continue;
6451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		j = 0;
6471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		/* Check page status */
6481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (redunt[PAGE_STATUS] != XD_GPG) {
6491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			for (j = 1; j <= 8; j++) {
6501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				retval =
6511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				    xd_read_redundant(chip, page_addr + j,
6521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						      redunt, 11);
6531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (retval == STATUS_SUCCESS) {
6541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					if (redunt[PAGE_STATUS] == XD_GPG)
6551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						break;
6561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				}
6571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
6581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (j == 9)
6601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				break;
6611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
6621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if ((redunt[BLOCK_STATUS] == XD_GBLK)
6641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    && (redunt[PARITY] & XD_BA1_ALL0)) {
6651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			u8 buf[10];
6661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			page_addr += j;
6681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = xd_read_cis(chip, page_addr, buf, 10);
6701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS)
6711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, retval);
6721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if ((buf[0] == 0x01) && (buf[1] == 0x03)
6741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    && (buf[2] == 0xD9)
6751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    && (buf[3] == 0x01) && (buf[4] == 0xFF)
6761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    && (buf[5] == 0x18) && (buf[6] == 0x02)
6771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    && (buf[7] == 0xDF) && (buf[8] == 0x01)
6781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    && (buf[9] == 0x20)) {
6791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_card->cis_block = (u16) i;
6801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
6811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
6821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		break;
6841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
6851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("CIS block: 0x%x\n", xd_card->cis_block);
6871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (xd_card->cis_block == 0xFFFF)
6881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
6891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	chip->capacity[chip->card2lun[XD_CARD]] = xd_card->capacity;
6911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
6931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
6941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_check_data_blank(u8 *redunt)
6961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
6971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int i;
6981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
6991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = 0; i < 6; i++) {
7001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (redunt[PAGE_STATUS + i] != 0xFF)
7011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			return 0;
7021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
7031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((redunt[PARITY] & (XD_ECC1_ALL1 | XD_ECC2_ALL1)) !=
7051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    (XD_ECC1_ALL1 | XD_ECC2_ALL1))
7061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		return 0;
7071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = 0; i < 4; i++) {
7091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (redunt[RESERVED0 + i] != 0xFF)
7101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			return 0;
7111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
7121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return 1;
7141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
7151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic u16 xd_load_log_block_addr(u8 *redunt)
7171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
7181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u16 addr = 0xFFFF;
7191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (redunt[PARITY] & XD_BA1_BA2_EQL)
7211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		addr =
7221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    ((u16) redunt[BLOCK_ADDR1_H] << 8) | redunt[BLOCK_ADDR1_L];
7231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	else if (redunt[PARITY] & XD_BA1_VALID)
7241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		addr =
7251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    ((u16) redunt[BLOCK_ADDR1_H] << 8) | redunt[BLOCK_ADDR1_L];
7261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	else if (redunt[PARITY] & XD_BA2_VALID)
7271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		addr =
7281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    ((u16) redunt[BLOCK_ADDR2_H] << 8) | redunt[BLOCK_ADDR2_L];
7291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return addr;
7311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
7321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_init_l2p_tbl(struct rts51x_chip *chip)
7341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
7351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
7361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int size, i;
7371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("xd_init_l2p_tbl: zone_cnt = %d\n", xd_card->zone_cnt);
7391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (xd_card->zone_cnt < 1)
7411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
7421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	size = xd_card->zone_cnt * sizeof(struct zone_entry);
7441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("Buffer size for l2p table is %d\n", size);
7451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_card->zone = vmalloc(size);
7471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!xd_card->zone)
7481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_NOMEM);
7491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = 0; i < xd_card->zone_cnt; i++) {
7511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->zone[i].build_flag = 0;
7521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->zone[i].l2p_table = NULL;
7531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->zone[i].free_table = NULL;
7541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->zone[i].get_index = 0;
7551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->zone[i].set_index = 0;
7561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->zone[i].unused_blk_cnt = 0;
7571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
7581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
7601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
7611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic inline void free_zone(struct zone_entry *zone)
7631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
7641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("free_zone\n");
7651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!zone)
7661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		return;
7671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone->build_flag = 0;
7681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone->set_index = 0;
7691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone->get_index = 0;
7701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone->unused_blk_cnt = 0;
7711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone->l2p_table) {
7721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		vfree(zone->l2p_table);
7731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		zone->l2p_table = NULL;
7741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
7751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone->free_table) {
7761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		vfree(zone->free_table);
7771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		zone->free_table = NULL;
7781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
7791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
7801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic void xd_set_unused_block(struct rts51x_chip *chip, u32 phy_blk)
7821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
7831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
7841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct zone_entry *zone;
7851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int zone_no;
7861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone_no = (int)phy_blk >> 10;
7881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone_no >= xd_card->zone_cnt) {
7891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("Set unused block to invalid zone"
7901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					"(zone_no = %d, zone_cnt = %d)\n",
7911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					zone_no, xd_card->zone_cnt);
7921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		return;
7931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
7941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone = &(xd_card->zone[zone_no]);
7951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
7961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone->free_table == NULL) {
7971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (xd_build_l2p_tbl(chip, zone_no) != STATUS_SUCCESS)
7981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			return;
7991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
8001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((zone->set_index >= XD_FREE_TABLE_CNT)
8021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    || (zone->set_index < 0)) {
8031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		free_zone(zone);
8041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("Set unused block fail, invalid set_index\n");
8051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		return;
8061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
8071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("Set unused block to index %d\n", zone->set_index);
8091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone->free_table[zone->set_index++] = (u16) (phy_blk & 0x3ff);
8111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone->set_index >= XD_FREE_TABLE_CNT)
8121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		zone->set_index = 0;
8131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone->unused_blk_cnt++;
8141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
8151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic u32 xd_get_unused_block(struct rts51x_chip *chip, int zone_no)
8171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
8181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
8191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct zone_entry *zone;
8201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 phy_blk;
8211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone_no >= xd_card->zone_cnt) {
8231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("Get unused block from invalid zone"
8241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					"(zone_no = %d, zone_cnt = %d)\n",
8251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					zone_no, xd_card->zone_cnt);
8261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, BLK_NOT_FOUND);
8271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
8281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone = &(xd_card->zone[zone_no]);
8291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((zone->unused_blk_cnt == 0) ||
8311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			(zone->set_index == zone->get_index)) {
8321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		free_zone(zone);
8331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("Get unused block fail,"
8341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					"no unused block available\n");
8351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, BLK_NOT_FOUND);
8361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
8371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((zone->get_index >= XD_FREE_TABLE_CNT) || (zone->get_index < 0)) {
8381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		free_zone(zone);
8391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("Get unused block fail, invalid get_index\n");
8401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, BLK_NOT_FOUND);
8411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
8421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("Get unused block from index %d\n", zone->get_index);
8441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	phy_blk = zone->free_table[zone->get_index];
8461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone->free_table[zone->get_index++] = 0xFFFF;
8471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone->get_index >= XD_FREE_TABLE_CNT)
8481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		zone->get_index = 0;
8491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone->unused_blk_cnt--;
8501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	phy_blk += ((u32) (zone_no) << 10);
8521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return phy_blk;
8531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
8541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic void xd_set_l2p_tbl(struct rts51x_chip *chip, int zone_no, u16 log_off,
8561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			   u16 phy_off)
8571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
8581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
8591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct zone_entry *zone;
8601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone = &(xd_card->zone[zone_no]);
8621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone->l2p_table[log_off] = phy_off;
8631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
8641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic u32 xd_get_l2p_tbl(struct rts51x_chip *chip, int zone_no, u16 log_off)
8661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
8671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
8681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct zone_entry *zone;
8691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
8701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone = &(xd_card->zone[zone_no]);
8721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone->l2p_table[log_off] == 0xFFFF) {
8731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		u32 phy_blk = 0;
8741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		int i;
8751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_delay_write(chip);
8771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
8781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_DEBUGP("In xd_get_l2p_tbl,"
8791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						"delay write fail!\n");
8801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, BLK_NOT_FOUND);
8811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
8821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (zone->unused_blk_cnt <= 0) {
8841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_DEBUGP("No unused block!\n");
8851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, BLK_NOT_FOUND);
8861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
8871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		for (i = 0; i < zone->unused_blk_cnt; i++) {
8891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			phy_blk = xd_get_unused_block(chip, zone_no);
8901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (phy_blk == BLK_NOT_FOUND) {
8911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				RTS51X_DEBUGP("No unused block available!\n");
8921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, BLK_NOT_FOUND);
8931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
8941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
8951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval =
8961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    xd_init_page(chip, phy_blk, log_off, 0,
8971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					 xd_card->page_off + 1);
8981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval == STATUS_SUCCESS)
8991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				break;
9001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
9011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (i >= zone->unused_blk_cnt) {
9021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_DEBUGP("No good unused block available!\n");
9031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, BLK_NOT_FOUND);
9041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
9051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_set_l2p_tbl(chip, zone_no, log_off, (u16) (phy_blk & 0x3FF));
9071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		return phy_blk;
9081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
9091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return (u32) zone->l2p_table[log_off] + ((u32) (zone_no) << 10);
9111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
9121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint reset_xd_card(struct rts51x_chip *chip)
9141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
9151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
9161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
9171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	memset(xd_card, 0, sizeof(struct xd_info));
9191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_card->block_shift = 0;
9211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_card->page_off = 0;
9221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_card->addr_cycle = 0;
9231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_card->capacity = 0;
9241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_card->zone_cnt = 0;
9251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_card->cis_block = 0xFFFF;
9261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_card->delay_write.delay_write_flag = 0;
9271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	enable_card_clock(chip, XD_CARD);
9291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = reset_xd(chip);
9311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
9321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (chip->option.reset_or_rw_fail_set_pad_drive) {
9331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_write_register(chip, CARD_DRIVE_SEL,
9341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					      SD20_DRIVE_MASK, DRIVE_8mA);
9351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
9361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
9371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
9381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = xd_init_l2p_tbl(chip);
9401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
9411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
9421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
9441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
9451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_mark_bad_block(struct rts51x_chip *chip, u32 phy_blk)
9471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
9481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
9491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
9501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 page_addr;
9511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 reg = 0;
9521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("mark block 0x%x as bad block\n", phy_blk);
9541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (phy_blk == BLK_NOT_FOUND)
9561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
9571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
9591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG);
9611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF,
9621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_LATER_BBLK);
9631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, 0xFF);
9641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, 0xFF);
9651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_H, 0xFF, 0xFF);
9661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_L, 0xFF, 0xFF);
9671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED0, 0xFF, 0xFF);
9681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED1, 0xFF, 0xFF);
9691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED2, 0xFF, 0xFF);
9701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED3, 0xFF, 0xFF);
9711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	page_addr = phy_blk << xd_card->block_shift;
9731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
9751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	/* Specify page count */
9771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF,
9781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       xd_card->page_off + 1);
9791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
9811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_START | XD_WRITE_REDUNDANT);
9821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
9831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_END);
9841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CR, 100);
9861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
9871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
9881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, 1, 100);
9901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
9911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
9921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
9931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_ep0_read_register(chip, XD_DAT, &reg);
9941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (reg & PROGRAM_ERROR)
9951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_err_code(chip, XD_PRG_ERROR);
9961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		else
9971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_err_code(chip, XD_TO_ERROR);
9981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
9991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
10001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
10021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
10031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_init_page(struct rts51x_chip *chip, u32 phy_blk, u16 logoff,
10051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			u8 start_page, u8 end_page)
10061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
10071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
10081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
10091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 page_addr;
10101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 reg = 0;
10111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("Init block 0x%x\n", phy_blk);
10131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (start_page > end_page)
10151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
10161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (phy_blk == BLK_NOT_FOUND)
10171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
10181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
10201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, 0xFF);
10221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, 0xFF);
10231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF,
10241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       (u8) (logoff >> 8));
10251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF,
10261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       (u8) logoff);
10271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	page_addr = (phy_blk << xd_card->block_shift) + start_page;
10291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
10311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM,
10331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_BA_TRANSFORM);
10341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF,
10361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       (end_page - start_page));
10371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
10391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_START | XD_WRITE_REDUNDANT);
10401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
10411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_END);
10421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CR, 100);
10441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
10451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
10461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, 1, 500);
10481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
10501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
10511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_ep0_read_register(chip, XD_DAT, &reg);
10521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (reg & PROGRAM_ERROR) {
10531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_mark_bad_block(chip, phy_blk);
10541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_err_code(chip, XD_PRG_ERROR);
10551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
10561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_err_code(chip, XD_TO_ERROR);
10571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
10581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
10591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
10601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
10621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
10631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_copy_page(struct rts51x_chip *chip,
10651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			u32 old_blk, u32 new_blk, u8 start_page, u8 end_page)
10661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
10671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
10681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 old_page, new_page;
10691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 i, reg = 0;
10701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
10711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("Copy page from block 0x%x to block 0x%x\n", old_blk,
10731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       new_blk);
10741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (start_page > end_page)
10761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
10771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND))
10791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
10801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	old_page = (old_blk << xd_card->block_shift) + start_page;
10821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	new_page = (new_blk << xd_card->block_shift) + start_page;
10831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	XD_CLR_BAD_NEWBLK(xd_card);
10851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_WRITE_REG(chip, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
10871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = start_page; i < end_page; i++) {
10891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) {
10901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_WRITE_REG(chip, CARD_STOP, XD_STOP | XD_CLR_ERR,
10911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					 XD_STOP | XD_CLR_ERR);
10921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_err_code(chip, XD_NO_CARD);
10931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
10941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
10951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_init_cmd(chip);
10971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
10981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_assign_phy_addr(chip, old_page, XD_RW_ADDR);
10991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		/* Single page read */
11011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
11021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
11031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       XD_AUTO_CHK_DATA_STATUS, 0);
11041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
11051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       XD_TRANSFER_START | XD_READ_PAGES);
11061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
11071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       XD_TRANSFER_END, XD_TRANSFER_END);
11081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_send_cmd(chip, MODE_CR | STAGE_XD_STATUS, 100);
11101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
11111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
11121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_get_rsp(chip, 4, 500);
11141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if ((retval != STATUS_SUCCESS) ||
11151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    (chip->rsp_buf[2] & (XD_ECC1_ERROR | XD_ECC2_ERROR))) {
11161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_clear_xd_error(chip);
11171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			reg = 0;
11181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_ep0_read_register(chip, XD_CTL, &reg);
11191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (reg & (XD_ECC1_ERROR | XD_ECC2_ERROR)) {
11201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				wait_timeout(100);
11211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (monitor_card_cd(chip, XD_CARD) ==
11231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				    CD_NOT_EXIST) {
11241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					xd_set_err_code(chip, XD_NO_CARD);
11251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					TRACE_RET(chip, STATUS_FAIL);
11261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				}
11271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (((reg &
11291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				      (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE))
11301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				     == (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE))
11311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				    || ((reg & (XD_ECC2_ERROR |
11321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					XD_ECC2_UNCORRECTABLE)) ==
11331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				     (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) {
11341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					RTS51X_WRITE_REG(chip, XD_PAGE_STATUS,
11351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong							 0xFF, XD_BPG);
11361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					RTS51X_WRITE_REG(chip, XD_BLOCK_STATUS,
11371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong							 0xFF, XD_GBLK);
11381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					XD_SET_BAD_OLDBLK(xd_card);
11391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					RTS51X_DEBUGP("old block 0x%x"
11401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						"ecc error\n", old_blk);
11411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				}
11421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			} else {
11431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_set_err_code(chip, XD_TO_ERROR);
11441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, STATUS_FAIL);
11451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
11461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
11471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (XD_CHK_BAD_OLDBLK(xd_card))
11481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_clear_xd_error(chip);
11491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_init_cmd(chip);
11511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_assign_phy_addr(chip, new_page, XD_RW_ADDR);
11531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
11541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
11551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       XD_TRANSFER_START | XD_WRITE_PAGES);
11561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
11571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       XD_TRANSFER_END, XD_TRANSFER_END);
11581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_send_cmd(chip, MODE_CR, 100);
11601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
11611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
11621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_get_rsp(chip, 1, 300);
11641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
11651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_clear_xd_error(chip);
11661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			reg = 0;
11671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_ep0_read_register(chip, XD_DAT, &reg);
11681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (reg & PROGRAM_ERROR) {
11691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_mark_bad_block(chip, new_blk);
11701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_set_err_code(chip, XD_PRG_ERROR);
11711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				XD_SET_BAD_NEWBLK(xd_card);
11721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			} else {
11731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_set_err_code(chip, XD_TO_ERROR);
11741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
11751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
11761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
11771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		old_page++;
11791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		new_page++;
11801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
11811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
11831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
11841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef XD_SPEEDUP
11861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_auto_copy_page(struct rts51x_chip *chip,
11871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			     u32 old_blk, u32 new_blk,
11881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			     u8 start_page, u8 end_page)
11891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
11901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
11911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 old_page, new_page;
11921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
11931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 page_count;
11941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("Auto copy page from block 0x%x to block 0x%x\n",
11961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       old_blk, new_blk);
11971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
11981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (start_page > end_page)
11991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
12001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	page_count = end_page - start_page;
12021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND))
12041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
12051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	old_page = (old_blk << xd_card->block_shift) + start_page;
12071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	new_page = (new_blk << xd_card->block_shift) + start_page;
12081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	XD_CLR_BAD_NEWBLK(xd_card);
12101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
12121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WAITTIME, 0x03, WAIT_FF);
12141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_PAGELEN, 0xFF, page_count);
12151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR0, 0xFF, 0);
12171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR1, 0xFF,
12181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       (u8) old_page);
12191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR2, 0xFF,
12201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       (u8) (old_page >> 8));
12211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR3, 0xFF,
12221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       (u8) (old_page >> 16));
12231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR4, 0xFF, 0);
12241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR0, 0xFF, 0);
12261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR1, 0xFF,
12271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       (u8) new_page);
12281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR2, 0xFF,
12291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       (u8) (new_page >> 8));
12301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR3, 0xFF,
12311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       (u8) (new_page >> 16));
12321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR4, 0xFF, 0);
12331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
12351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       PINGPONG_BUFFER);
12361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG,
12381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_BA_TRANSFORM | XD_ADDR_MASK, 0 | xd_card->addr_cycle);
12391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
12411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_AUTO_CHK_DATA_STATUS, 0);
12421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
12431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_START | XD_COPY_PAGES);
12441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
12451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_END);
12461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CR, 100);
12481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
12491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
12501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_GOTO(chip, Copy_Fail);
12511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
12521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, 1, 800);
12541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
12551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
12561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_GOTO(chip, Copy_Fail);
12571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
12581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
12601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongCopy_Fail:
12621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = xd_copy_page(chip, old_blk, new_blk, start_page, end_page);
12631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
12641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
12651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
12671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
12681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
12691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_reset_cmd(struct rts51x_chip *chip)
12711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
12721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
12731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 xd_dat, xd_ctl;
12741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
12761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
12781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_START | XD_RESET);
12791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
12801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_END);
12811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
12821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0);
12831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CR, 100);
12851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
12861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
12871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, 3, 100);
12891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
12901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
12911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
12921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
12931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_dat = chip->rsp_buf[1];
12951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_ctl = chip->rsp_buf[2];
12961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (((xd_dat & READY_FLAG) == READY_STATE) && (xd_ctl & XD_RDY))
12971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		return STATUS_SUCCESS;
12981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
12991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	TRACE_RET(chip, STATUS_FAIL);
13001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
13011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_erase_block(struct rts51x_chip *chip, u32 phy_blk)
13031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
13041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
13051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 page_addr;
13061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 reg = 0, xd_dat;
13071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int i, retval;
13081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (phy_blk == BLK_NOT_FOUND)
13101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
13111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	page_addr = phy_blk << xd_card->block_shift;
13131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = 0; i < 3; i++) {
13151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_init_cmd(chip);
13161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_assign_phy_addr(chip, page_addr, XD_ERASE_ADDR);
13181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
13201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       XD_TRANSFER_START | XD_ERASE);
13211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
13221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       XD_TRANSFER_END, XD_TRANSFER_END);
13231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
13241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_send_cmd(chip, MODE_CR, 100);
13261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
13271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
13281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = rts51x_get_rsp(chip, 2, 300);
13301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
13311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_clear_xd_error(chip);
13321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_ep0_read_register(chip, XD_DAT, &reg);
13331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (reg & PROGRAM_ERROR) {
13341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_mark_bad_block(chip, phy_blk);
13351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_set_err_code(chip, XD_PRG_ERROR);
13361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, STATUS_FAIL);
13371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			} else {
13381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_set_err_code(chip, XD_ERASE_FAIL);
13391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
13401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = xd_reset_cmd(chip);
13411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS)
13421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, retval);
13431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			continue;
13441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
13451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_dat = chip->rsp_buf[1];
13461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (xd_dat & PROGRAM_ERROR) {
13471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_mark_bad_block(chip, phy_blk);
13481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_err_code(chip, XD_PRG_ERROR);
13491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
13501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
13511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		return STATUS_SUCCESS;
13531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
13541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_mark_bad_block(chip, phy_blk);
13561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_set_err_code(chip, XD_ERASE_FAIL);
13571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	TRACE_RET(chip, STATUS_FAIL);
13581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
13591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_build_l2p_tbl(struct rts51x_chip *chip, int zone_no)
13611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
13621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
13631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct zone_entry *zone;
13641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
13651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 start, end, i;
13661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u16 max_logoff, cur_fst_page_logoff, cur_lst_page_logoff,
13671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    ent_lst_page_logoff;
13681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 redunt[11];
13691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("xd_build_l2p_tbl: %d\n", zone_no);
13711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (xd_card->zone == NULL) {
13731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_init_l2p_tbl(chip);
13741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
13751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
13761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
13771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (xd_card->zone[zone_no].build_flag) {
13791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("l2p table of zone %d has been built\n",
13801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       zone_no);
13811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		return STATUS_SUCCESS;
13821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
13831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone = &(xd_card->zone[zone_no]);
13851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone->l2p_table == NULL) {
13871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		zone->l2p_table = vmalloc(2000);
13881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (zone->l2p_table == NULL)
13891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, Build_Fail);
13901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
13911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	memset((u8 *) (zone->l2p_table), 0xff, 2000);
13921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
13931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone->free_table == NULL) {
13941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		zone->free_table = vmalloc(XD_FREE_TABLE_CNT * 2);
13951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (zone->free_table == NULL)
13961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, Build_Fail);
13971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
13981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	memset((u8 *) (zone->free_table), 0xff, XD_FREE_TABLE_CNT * 2);
13991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone_no == 0) {
14011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (xd_card->cis_block == 0xFFFF)
14021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			start = 0;
14031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		else
14041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			start = xd_card->cis_block + 1;
14051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (XD_CHK_4MB(xd_card)) {
14061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			end = 0x200;
14071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			max_logoff = 499;
14081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
14091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			end = 0x400;
14101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			max_logoff = 999;
14111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
14121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else {
14131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		start = (u32) (zone_no) << 10;
14141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		end = (u32) (zone_no + 1) << 10;
14151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		max_logoff = 999;
14161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
14171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("start block 0x%x, end block 0x%x\n", start, end);
14191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone->set_index = zone->get_index = 0;
14211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone->unused_blk_cnt = 0;
14221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (i = start; i < end; i++) {
14241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		u32 page_addr = i << xd_card->block_shift;
14251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		u32 phy_block;
14261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_read_redundant(chip, page_addr, redunt, 11);
14281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
14291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			continue;
14301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (redunt[BLOCK_STATUS] != 0xFF) {
14321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_DEBUGP("bad block\n");
14331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			continue;
14341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
14351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (xd_check_data_blank(redunt)) {
14371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			RTS51X_DEBUGP("blank block\n");
14381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_unused_block(chip, i);
14391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			continue;
14401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
14411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		cur_fst_page_logoff = xd_load_log_block_addr(redunt);
14431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if ((cur_fst_page_logoff == 0xFFFF)
14441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    || (cur_fst_page_logoff > max_logoff)) {
14451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = xd_erase_block(chip, i);
14461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval == STATUS_SUCCESS)
14471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_set_unused_block(chip, i);
14481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			continue;
14491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
14501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if ((zone_no == 0) && (cur_fst_page_logoff == 0)
14511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    && (redunt[PAGE_STATUS] != XD_GPG))
14521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_SET_MBR_FAIL(xd_card);
14531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (zone->l2p_table[cur_fst_page_logoff] == 0xFFFF) {
14551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			zone->l2p_table[cur_fst_page_logoff] =
14561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    (u16) (i & 0x3FF);
14571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			continue;
14581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
14591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		phy_block =
14611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    zone->l2p_table[cur_fst_page_logoff] +
14621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    ((u32) ((zone_no) << 10));
14631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		page_addr = ((i + 1) << xd_card->block_shift) - 1;
14651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_read_redundant(chip, page_addr, redunt, 11);
14671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
14681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			continue;
14691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		cur_lst_page_logoff = xd_load_log_block_addr(redunt);
14711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (cur_lst_page_logoff == cur_fst_page_logoff) {
14721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			int m;
14731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			page_addr =
14751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    ((phy_block + 1) << xd_card->block_shift) - 1;
14761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			for (m = 0; m < 3; m++) {
14781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				retval =
14791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				    xd_read_redundant(chip, page_addr, redunt,
14801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						      11);
14811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (retval == STATUS_SUCCESS)
14821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					break;
14831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
14841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (m == 3) {
14861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				zone->l2p_table[cur_fst_page_logoff] =
14871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				    (u16) (i & 0x3FF);
14881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				retval = xd_erase_block(chip, phy_block);
14891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (retval == STATUS_SUCCESS)
14901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					xd_set_unused_block(chip, phy_block);
14911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				continue;
14921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
14931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
14941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			ent_lst_page_logoff = xd_load_log_block_addr(redunt);
14951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (ent_lst_page_logoff != cur_fst_page_logoff) {
14961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				zone->l2p_table[cur_fst_page_logoff] =
14971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				    (u16) (i & 0x3FF);
14981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				retval = xd_erase_block(chip, phy_block);
14991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (retval == STATUS_SUCCESS)
15001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					xd_set_unused_block(chip, phy_block);
15011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				continue;
15021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			} else {
15031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				retval = xd_erase_block(chip, i);
15041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (retval == STATUS_SUCCESS)
15051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					xd_set_unused_block(chip, i);
15061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
15071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
15081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = xd_erase_block(chip, i);
15091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval == STATUS_SUCCESS)
15101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_set_unused_block(chip, i);
15111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
15121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
15131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (XD_CHK_4MB(xd_card))
15151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		end = 500;
15161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	else
15171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		end = 1000;
15181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	i = 0;
15201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	for (start = 0; start < end; start++) {
15211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (zone->l2p_table[start] == 0xFFFF)
15221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			i++;
15231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
15241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("Block count %d, invalid L2P entry %d\n", end, i);
15261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("Total unused block: %d\n", zone->unused_blk_cnt);
15271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((zone->unused_blk_cnt - i) < 1)
15291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		chip->card_wp |= XD_CARD;
15301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone->build_flag = 1;
15321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
15341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongBuild_Fail:
15361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone->l2p_table) {
15371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		vfree(zone->l2p_table);
15381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		zone->l2p_table = NULL;
15391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
15401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (zone->free_table) {
15411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		vfree(zone->free_table);
15421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		zone->free_table = NULL;
15431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
15441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_FAIL;
15461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
15471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_send_cmd(struct rts51x_chip *chip, u8 cmd)
15491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
15501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
15511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
15531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, cmd);
15551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
15561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_START | XD_SET_CMD);
15571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
15581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_END);
15591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CR, 100);
15611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
15621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
15631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, 1, 200);
15651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
15661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
15671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
15681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
15691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
15711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
15721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_read_multiple_pages(struct rts51x_chip *chip, u32 phy_blk,
15741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				  u32 log_blk, u8 start_page, u8 end_page,
15751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				  u8 *buf, void **ptr, unsigned int *offset)
15761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
15771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
15781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 page_addr, new_blk;
15791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u16 log_off;
15801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 reg_val, page_cnt;
15811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int zone_no, retval, i;
15821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (start_page > end_page)
15841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
15851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	page_cnt = end_page - start_page;
15871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone_no = (int)(log_blk / 1000);
15881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	log_off = (u16) (log_blk % 1000);
15891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((phy_blk & 0x3FF) == 0x3FF) {
15911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		for (i = 0; i < 256; i++) {
15921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			page_addr = ((u32) i) << xd_card->block_shift;
15931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = xd_read_redundant(chip, page_addr, NULL, 0);
15951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval == STATUS_SUCCESS)
15961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				break;
15971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
15981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) {
15991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_set_err_code(chip, XD_NO_CARD);
16001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, STATUS_FAIL);
16011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
16021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
16031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
16041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	page_addr = (phy_blk << xd_card->block_shift) + start_page;
16061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
16081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
16101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_PPB_TO_SIE,
16121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_PPB_TO_SIE);
16131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
16141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       RING_BUFFER);
16151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt);
16161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
16171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS);
16181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512,
16201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			 DMA_512);
16211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
16231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_START | XD_READ_PAGES);
16241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
16251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_END | XD_PPB_EMPTY,
16261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_END | XD_PPB_EMPTY);
16271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CDIR, 100);
16291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
16301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
16311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval =
16331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    rts51x_transfer_data_partial(chip, RCV_BULK_PIPE(chip), (void *)buf,
16341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					 ptr, offset, page_cnt * 512,
16351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					 scsi_sg_count(chip->srb), NULL, 2000);
16361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
16371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
16381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval == STATUS_TIMEDOUT) {
16401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_err_code(chip, XD_TO_ERROR);
16411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
16421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
16431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, Fail);
16441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
16451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
16461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, 1, 200);
16471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
16481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
16491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval == STATUS_TIMEDOUT) {
16511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_err_code(chip, XD_TO_ERROR);
16521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
16531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
16541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, Fail);
16551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
16561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
16571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
16591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongFail:
16611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_ep0_read_register(chip, XD_PAGE_STATUS, &reg_val);
16621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("XD_PAGE_STATUS: 0x%x\n", reg_val);
16631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (reg_val != XD_GPG)
16651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_set_err_code(chip, XD_PRG_ERROR);
16661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_ep0_read_register(chip, XD_CTL, &reg_val);
16681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("XD_CTL: 0x%x\n", reg_val);
16691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	/* Handle uncorrectable ECC error */
16711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (((reg_val & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE))
16721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	     == (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE))
16731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    || ((reg_val & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))
16741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		== (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) {
16751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		wait_timeout(100);
16761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) {
16781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_err_code(chip, XD_NO_CARD);
16791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
16801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
16811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_set_err_code(chip, XD_ECC_ERROR);
16831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
16841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		new_blk = xd_get_unused_block(chip, zone_no);
16851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (new_blk == NO_NEW_BLK) {
16861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_CLR_BAD_OLDBLK(xd_card);
16871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
16881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
16891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef XD_SPEEDUP
16901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval =
16911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    xd_auto_copy_page(chip, phy_blk, new_blk, 0,
16921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				      xd_card->page_off + 1);
16931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#else
16941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval =
16951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    xd_copy_page(chip, phy_blk, new_blk, 0,
16961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				 xd_card->page_off + 1);
16971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
16981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
16991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (!XD_CHK_BAD_NEWBLK(xd_card)) {
17001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				retval = xd_erase_block(chip, new_blk);
17011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (retval == STATUS_SUCCESS)
17021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					xd_set_unused_block(chip, new_blk);
17031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			} else {
17041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				XD_CLR_BAD_NEWBLK(xd_card);
17051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
17061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_CLR_BAD_OLDBLK(xd_card);
17071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
17081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
17091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_set_l2p_tbl(chip, zone_no, log_off, (u16) (new_blk & 0x3FF));
17101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_erase_block(chip, phy_blk);
17111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_mark_bad_block(chip, phy_blk);
17121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		XD_CLR_BAD_OLDBLK(xd_card);
17131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
17141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
17151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	TRACE_RET(chip, STATUS_FAIL);
17161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
17171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
17181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_finish_write(struct rts51x_chip *chip,
17191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			   u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off)
17201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
17211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
17221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval, zone_no;
17231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u16 log_off;
17241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
17251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("xd_finish_write, old_blk = 0x%x, new_blk = 0x%x,"
17261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				"log_blk = 0x%x\n", old_blk, new_blk, log_blk);
17271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
17281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (page_off > xd_card->page_off)
17291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
17301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
17311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone_no = (int)(log_blk / 1000);
17321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	log_off = (u16) (log_blk % 1000);
17331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
17341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (old_blk == BLK_NOT_FOUND) {
17351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_init_page(chip, new_blk, log_off,
17361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				      page_off, xd_card->page_off + 1);
17371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
17381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = xd_erase_block(chip, new_blk);
17391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval == STATUS_SUCCESS)
17401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_set_unused_block(chip, new_blk);
17411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
17421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
17431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else {
17441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef XD_SPEEDUP
17451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_auto_copy_page(chip, old_blk, new_blk,
17461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					   page_off, xd_card->page_off + 1);
17471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#else
17481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_copy_page(chip, old_blk, new_blk,
17491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				      page_off, xd_card->page_off + 1);
17501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
17511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
17521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (!XD_CHK_BAD_NEWBLK(xd_card)) {
17531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				retval = xd_erase_block(chip, new_blk);
17541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (retval == STATUS_SUCCESS)
17551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					xd_set_unused_block(chip, new_blk);
17561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
17571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_CLR_BAD_NEWBLK(xd_card);
17581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
17591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
17601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
17611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_erase_block(chip, old_blk);
17621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval == STATUS_SUCCESS) {
17631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (XD_CHK_BAD_OLDBLK(xd_card)) {
17641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_mark_bad_block(chip, old_blk);
17651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				XD_CLR_BAD_OLDBLK(xd_card);
17661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			} else {
17671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				/* Add source block to unused block */
17681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_set_unused_block(chip, old_blk);
17691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
17701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
17711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_err_code(chip, XD_NO_ERROR);
17721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			XD_CLR_BAD_OLDBLK(xd_card);
17731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
17741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
17751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
17761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	/* Add target block to L2P table */
17771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_set_l2p_tbl(chip, zone_no, log_off, (u16) (new_blk & 0x3FF));
17781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
17791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
17801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
17811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
17821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_prepare_write(struct rts51x_chip *chip,
17831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off)
17841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
17851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
17861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
17871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("xd_prepare_write, old_blk = 0x%x, new_blk = 0x%x,"
17881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				"log_blk = 0x%x, page_off = %d\n",
17891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				old_blk, new_blk, log_blk, (int)page_off);
17901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
17911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (page_off) {
17921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef XD_SPEEDUP
17931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_auto_copy_page(chip, old_blk, new_blk, 0, page_off);
17941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#else
17951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_copy_page(chip, old_blk, new_blk, 0, page_off);
17961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
17971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
17981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
17991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
18001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
18021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
18031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_write_multiple_pages(struct rts51x_chip *chip, u32 old_blk,
18051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				   u32 new_blk, u32 log_blk, u8 start_page,
18061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				   u8 end_page, u8 *buf, void **ptr,
18071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				   unsigned int *offset)
18081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
18091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
18101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 page_addr;
18111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int zone_no, retval;
18121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u16 log_off;
18131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 page_cnt, reg_val;
18141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("xd_write_multiple_pages, old_blk = 0x%x,"
18161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				"new_blk = 0x%x, log_blk = 0x%x\n",
18171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				old_blk, new_blk, log_blk);
18181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (start_page > end_page)
18201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, STATUS_FAIL);
18211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	page_cnt = end_page - start_page;
18231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone_no = (int)(log_blk / 1000);
18241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	log_off = (u16) (log_blk % 1000);
18251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	page_addr = (new_blk << xd_card->block_shift) + start_page;
18271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	/* Send index command */
18291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = xd_send_cmd(chip, READ1_1);
18301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
18311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
18321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
18341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	/* Prepare redundant field */
18361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF,
18371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       (u8) (log_off >> 8));
18381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF,
18391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       (u8) log_off);
18401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_GBLK);
18411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG);
18421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
18441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	/* Transform the block address by hardware */
18461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM,
18471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_BA_TRANSFORM);
18481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt);
18501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
18511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       RING_BUFFER);
18521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512,
18541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			 DMA_512);
18551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
18571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_START | XD_WRITE_PAGES);
18581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
18591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       XD_TRANSFER_END);
18601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_CDOR, 100);
18621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
18631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
18641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval =
18661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    rts51x_transfer_data_partial(chip, SND_BULK_PIPE(chip), (void *)buf,
18671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					 ptr, offset, page_cnt * 512,
18681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					 scsi_sg_count(chip->srb), NULL, 2000);
18691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
18701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
18711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval == STATUS_TIMEDOUT) {
18731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_err_code(chip, XD_TO_ERROR);
18741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
18751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
18761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, Fail);
18771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
18781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
18791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_get_rsp(chip, 1, 200);
18801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS) {
18811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_clear_xd_error(chip);
18821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval == STATUS_TIMEDOUT) {
18841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			xd_set_err_code(chip, XD_TO_ERROR);
18851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
18861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
18871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_GOTO(chip, Fail);
18881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
18891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
18901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (end_page == (xd_card->page_off + 1)) {
18921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->delay_write.delay_write_flag = 0;
18931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
18941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (old_blk != BLK_NOT_FOUND) {
18951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = xd_erase_block(chip, old_blk);
18961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval == STATUS_SUCCESS) {
18971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (XD_CHK_BAD_OLDBLK(xd_card)) {
18981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					xd_mark_bad_block(chip, old_blk);
18991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					XD_CLR_BAD_OLDBLK(xd_card);
19001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				} else {
19011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					xd_set_unused_block(chip, old_blk);
19021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				}
19031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			} else {
19041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_set_err_code(chip, XD_NO_ERROR);
19051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				XD_CLR_BAD_OLDBLK(xd_card);
19061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
19071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
19081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_set_l2p_tbl(chip, zone_no, log_off, (u16) (new_blk & 0x3FF));
19091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
19101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
19121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongFail:
19141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_ep0_read_register(chip, XD_DAT, &reg_val);
19151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("XD_DAT: 0x%x\n", reg_val);
19161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (reg_val & PROGRAM_ERROR) {
19181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_set_err_code(chip, XD_PRG_ERROR);
19191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_mark_bad_block(chip, new_blk);
19201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
19211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	TRACE_RET(chip, STATUS_FAIL);
19231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
19241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint xd_delay_write(struct rts51x_chip *chip)
19261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
19271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
19281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_delay_write_tag *delay_write = &(xd_card->delay_write);
19291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
19301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (delay_write->delay_write_flag) {
19321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("xd_delay_write\n");
19331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_switch_clock(chip);
19341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
19351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
19361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		delay_write->delay_write_flag = 0;
19381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_finish_write(chip,
19391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					 delay_write->old_phyblock,
19401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					 delay_write->new_phyblock,
19411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					 delay_write->logblock,
19421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					 delay_write->pageoff);
19431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS)
19441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
19451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
19461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
19481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
19491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
19511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	  u16 sector_cnt)
19521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
19531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
19541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	unsigned int lun = SCSI_LUN(srb);
19551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_delay_write_tag *delay_write = &(xd_card->delay_write);
19561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval, zone_no;
19571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u32 log_blk, old_blk = 0, new_blk = 0;
19581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u16 log_off, total_sec_cnt = sector_cnt;
19591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 start_page, end_page = 0, page_cnt;
19601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	u8 *buf;
19611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	void *ptr = NULL;
19621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	unsigned int offset = 0;
19631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_set_err_code(chip, XD_NO_ERROR);
19651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_card->counter = 0;
19671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("xd_rw: scsi_bufflen = %d, scsi_sg_count = %d\n",
19691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       scsi_bufflen(srb), scsi_sg_count(srb));
19701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("Data direction: %s\n",
19711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		       (srb->sc_data_direction ==
19721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			DMA_TO_DEVICE) ? "write" : "read");
19731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	buf = (u8 *) scsi_sglist(srb);
19751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = xd_switch_clock(chip);
19771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
19781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
19791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	log_blk = start_sector >> xd_card->block_shift;
19811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	start_page = (u8) start_sector & xd_card->page_off;
19821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	zone_no = (int)(log_blk / 1000);
19831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	log_off = (u16) (log_blk % 1000);
19841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("log_blk = 0x%x\n", log_blk);
19861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (xd_card->zone[zone_no].build_flag == 0) {
19881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_build_l2p_tbl(chip, zone_no);
19891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
19901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			chip->card_fail |= XD_CARD;
19911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
19921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
19931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
19941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
19951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
19961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (srb->sc_data_direction == DMA_TO_DEVICE) {
19971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (delay_write->delay_write_flag &&
19981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    (delay_write->logblock == log_blk) &&
19991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    (start_page > delay_write->pageoff)) {
20001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			delay_write->delay_write_flag = 0;
20011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (delay_write->old_phyblock != BLK_NOT_FOUND) {
20021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef XD_SPEEDUP
20031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				retval = xd_auto_copy_page(chip,
20041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					delay_write->old_phyblock,
20051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					delay_write->new_phyblock,
20061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					delay_write->pageoff, start_page);
20071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#else
20081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				retval = xd_copy_page(chip,
20091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						      delay_write->old_phyblock,
20101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						      delay_write->new_phyblock,
20111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						      delay_write->pageoff,
20121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						      start_page);
20131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif
20141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (retval != STATUS_SUCCESS) {
20151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					set_sense_type(chip, lun,
20161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						SENSE_TYPE_MEDIA_WRITE_ERR);
20171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					TRACE_RET(chip, retval);
20181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				}
20191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
20201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			old_blk = delay_write->old_phyblock;
20211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			new_blk = delay_write->new_phyblock;
20221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else if (delay_write->delay_write_flag &&
20231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			   (delay_write->logblock == log_blk) &&
20241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			   (start_page == delay_write->pageoff)) {
20251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			delay_write->delay_write_flag = 0;
20261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			old_blk = delay_write->old_phyblock;
20271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			new_blk = delay_write->new_phyblock;
20281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
20291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = xd_delay_write(chip);
20301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS) {
20311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				set_sense_type(chip, lun,
20321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       SENSE_TYPE_MEDIA_WRITE_ERR);
20331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, retval);
20341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
20351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
20361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			new_blk = xd_get_unused_block(chip, zone_no);
20371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if ((old_blk == BLK_NOT_FOUND)
20381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    || (new_blk == BLK_NOT_FOUND)) {
20391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				set_sense_type(chip, lun,
20401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       SENSE_TYPE_MEDIA_WRITE_ERR);
20411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, retval);
20421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
20431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
20441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval =
20451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    xd_prepare_write(chip, old_blk, new_blk, log_blk,
20461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					     start_page);
20471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS) {
20481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				if (monitor_card_cd(chip, XD_CARD) ==
20491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				    CD_NOT_EXIST) {
20501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					set_sense_type(chip, lun,
20511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						SENSE_TYPE_MEDIA_NOT_PRESENT);
20521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					TRACE_RET(chip, STATUS_FAIL);
20531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				}
20541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				set_sense_type(chip, lun,
20551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       SENSE_TYPE_MEDIA_WRITE_ERR);
20561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, retval);
20571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
20581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
20591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	} else {
20601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		retval = xd_delay_write(chip);
20611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (retval != STATUS_SUCCESS) {
20621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) {
20631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				set_sense_type(chip, lun,
20641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       SENSE_TYPE_MEDIA_NOT_PRESENT);
20651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, STATUS_FAIL);
20661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
20671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			set_sense_type(chip, lun,
20681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
20691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, retval);
20701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
20711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
20721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
20731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (old_blk == BLK_NOT_FOUND) {
20741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			set_sense_type(chip, lun,
20751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
20761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
20771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
20781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
20791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
20801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("old_blk = 0x%x\n", old_blk);
20811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (srb->sc_data_direction == DMA_TO_DEVICE)
20821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("new_blk = 0x%x\n", new_blk);
20831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
20841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	while (total_sec_cnt) {
20851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if ((start_page + total_sec_cnt) > (xd_card->page_off + 1))
20861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			end_page = xd_card->page_off + 1;
20871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		else
20881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			end_page = start_page + (u8) total_sec_cnt;
20891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		page_cnt = end_page - start_page;
20901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
20911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = xd_read_multiple_pages(chip, old_blk, log_blk,
20921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong							start_page, end_page,
20931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong							buf, &ptr, &offset);
20941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS) {
20951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				set_sense_type(chip, lun,
20961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
20971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, STATUS_FAIL);
20981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
20991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		} else {
21001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval =
21011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			    xd_write_multiple_pages(chip, old_blk, new_blk,
21021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						    log_blk, start_page,
21031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						    end_page, buf, &ptr,
21041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong						    &offset);
21051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS) {
21061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				set_sense_type(chip, lun,
21071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       SENSE_TYPE_MEDIA_WRITE_ERR);
21081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, STATUS_FAIL);
21091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
21101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
21111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		total_sec_cnt -= page_cnt;
21131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (total_sec_cnt == 0)
21151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			break;
21161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		log_blk++;
21181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		zone_no = (int)(log_blk / 1000);
21191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		log_off = (u16) (log_blk % 1000);
21201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (xd_card->zone[zone_no].build_flag == 0) {
21221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			retval = xd_build_l2p_tbl(chip, zone_no);
21231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (retval != STATUS_SUCCESS) {
21241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				chip->card_fail |= XD_CARD;
21251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				set_sense_type(chip, lun,
21261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       SENSE_TYPE_MEDIA_NOT_PRESENT);
21271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, retval);
21281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
21291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
21301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
21321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (old_blk == BLK_NOT_FOUND) {
21331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (srb->sc_data_direction == DMA_FROM_DEVICE) {
21341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				set_sense_type(chip, lun,
21351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
21361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			} else {
21371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				set_sense_type(chip, lun,
21381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       SENSE_TYPE_MEDIA_WRITE_ERR);
21391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
21401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			TRACE_RET(chip, STATUS_FAIL);
21411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
21421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (srb->sc_data_direction == DMA_TO_DEVICE) {
21441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			new_blk = xd_get_unused_block(chip, zone_no);
21451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (new_blk == BLK_NOT_FOUND) {
21461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				set_sense_type(chip, lun,
21471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong					       SENSE_TYPE_MEDIA_WRITE_ERR);
21481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				TRACE_RET(chip, STATUS_FAIL);
21491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
21501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
21511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		start_page = 0;
21531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
21541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if ((srb->sc_data_direction == DMA_TO_DEVICE) &&
21561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	    (end_page != (xd_card->page_off + 1))) {
21571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		delay_write->delay_write_flag = 1;
21581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		delay_write->old_phyblock = old_blk;
21591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		delay_write->new_phyblock = new_blk;
21601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		delay_write->logblock = log_blk;
21611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		delay_write->pageoff = end_page;
21621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
21631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	scsi_set_resid(srb, 0);
21651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
21671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
21681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongvoid xd_free_l2p_tbl(struct rts51x_chip *chip)
21701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
21711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
21721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int i = 0;
21731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (xd_card->zone != NULL) {
21751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		for (i = 0; i < xd_card->zone_cnt; i++) {
21761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (xd_card->zone[i].l2p_table != NULL) {
21771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				vfree(xd_card->zone[i].l2p_table);
21781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_card->zone[i].l2p_table = NULL;
21791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
21801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			if (xd_card->zone[i].free_table != NULL) {
21811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				vfree(xd_card->zone[i].free_table);
21821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				xd_card->zone[i].free_table = NULL;
21831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			}
21841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		}
21851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		vfree(xd_card->zone);
21861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->zone = NULL;
21871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
21881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
21891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongvoid xd_cleanup_work(struct rts51x_chip *chip)
21911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
21921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
21931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
21941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (xd_card->delay_write.delay_write_flag) {
21951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		RTS51X_DEBUGP("xD: delay write\n");
21961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_delay_write(chip);
21971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_card->counter = 0;
21981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
21991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
22001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint xd_power_off_card3v3(struct rts51x_chip *chip)
22021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
22031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
22041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_init_cmd(chip);
22061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_EN, XD_CLK_EN, 0);
22081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (chip->asic_code)
22101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		xd_pull_ctl_disable(chip);
22111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	else
22121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, 0xDF);
22131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0);
22141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (!chip->option.FT2_fast_mode) {
22151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK,
22161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			       POWER_OFF);
22171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		if (CHECK_PKG(chip, LQFP48)
22181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		    || chip->option.rts5129_D3318_off_enable)
22191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong			rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL,
22201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong				       DV3318_AUTO_PWR_OFF, 0);
22211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	}
22221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = rts51x_send_cmd(chip, MODE_C, 100);
22241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
22251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
22261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
22281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
22291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint release_xd_card(struct rts51x_chip *chip)
22311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{
22321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	struct xd_info *xd_card = &(chip->xd_card);
22331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	int retval;
22341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	RTS51X_DEBUGP("elease_xd_card\n");
22361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	chip->card_ready &= ~XD_CARD;
22381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	chip->card_fail &= ~XD_CARD;
22391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	chip->card_wp &= ~XD_CARD;
22401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_card->delay_write.delay_write_flag = 0;
22421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	xd_free_l2p_tbl(chip);
22441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	rts51x_write_register(chip, SFSM_ED, HW_CMD_STOP, HW_CMD_STOP);
22461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	retval = xd_power_off_card3v3(chip);
22481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (retval != STATUS_SUCCESS)
22491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		TRACE_RET(chip, retval);
22501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	if (chip->asic_code && CHECK_PKG(chip, QFN24))
22521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong		wait_timeout(20);
22531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong
22541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong	return STATUS_SUCCESS;
22551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong}
2256