diff options
| author | Roman Yeryomin <roman@advem.lv> | 2013-05-17 20:40:24 +0300 |
|---|---|---|
| committer | Roman Yeryomin <roman@advem.lv> | 2013-05-26 00:48:34 +0300 |
| commit | 7e810011201bf926cba09ec07424893e4cd8ce67 (patch) | |
| tree | 202fc7a42607e366848ca59c7a61a8f9fa2712ca /target/linux/realtek/files/drivers/usb/misc/rts51xx/ms_mg.c | |
| parent | a45894b5a0f65585440d98bf71ef3e919c84cb5f (diff) | |
Move to rsdk 3.2.4. Compiles cleanly.
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/drivers/usb/misc/rts51xx/ms_mg.c')
| -rw-r--r-- | target/linux/realtek/files/drivers/usb/misc/rts51xx/ms_mg.c | 709 |
1 files changed, 709 insertions, 0 deletions
diff --git a/target/linux/realtek/files/drivers/usb/misc/rts51xx/ms_mg.c b/target/linux/realtek/files/drivers/usb/misc/rts51xx/ms_mg.c new file mode 100644 index 000000000..7b65a573f --- /dev/null +++ b/target/linux/realtek/files/drivers/usb/misc/rts51xx/ms_mg.c @@ -0,0 +1,709 @@ +/* Driver for Realtek RTS51xx USB card reader + * + * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http: + * + * Author: + * wwang (wei_wang@realsil.com.cn) + * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China + */ + +#include <linux/blkdev.h> +#include <linux/kthread.h> +#include <linux/sched.h> +#include <linux/slab.h> + +#include "debug.h" +#include "trace.h" +#include "rts51x.h" +#include "rts51x_transport.h" +#include "rts51x_scsi.h" +#include "rts51x_card.h" +#include "ms.h" + +#ifdef SUPPORT_MAGIC_GATE + +int ms_switch_clock(struct rts51x_chip *chip); +int ms_write_bytes(struct rts51x_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len); +int ms_read_bytes(struct rts51x_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len); +int ms_set_rw_reg_addr(struct rts51x_chip *chip, + u8 read_start, u8 read_cnt, u8 write_start, u8 write_cnt); +int ms_transfer_data(struct rts51x_chip *chip, u8 trans_mode, u8 tpc, u16 sec_cnt, + u8 cfg, int mode_2k, int use_sg, void *buf, int buf_len); + + +int mg_check_int_error(struct rts51x_chip *chip) +{ + u8 value; + + rts51x_read_register(chip,MS_TRANS_CFG,&value); + if(value&(INT_ERR|INT_CMDNK)) + { + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int mg_send_ex_cmd(struct rts51x_chip *chip, u8 cmd, u8 entry_num) +{ + int retval, i; + u8 data[8]; + + data[0] = cmd; + data[1] = 0; + data[2] = 0; + data[3] = 0; + data[4] = 0; + data[5] = 0; + data[6] = entry_num; + data[7] = 0; + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7, WAIT_INT, data, 8); + if (retval == STATUS_SUCCESS) { + break; + } + } + if (i == MS_MAX_RETRY_COUNT) { + TRACE_RET(chip, STATUS_FAIL); + } + + retval = mg_check_int_error(chip); + if(retval!=STATUS_SUCCESS) + { + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +/** + * Set TPC Parameter Register to 00 + + * It sets the data size of a READ_SHORT_DATA and a WRITE_SHORT_DATA TPC + * as 32 bytes. + */ +int mg_set_tpc_para_sub(struct rts51x_chip *chip, int type, u8 mg_entry_num) +{ + int retval; + u8 buf[6]; + + RTS51X_DEBUGP(("--%s--\n", __FUNCTION__)); + + if (type == 0) { + retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_TPCParm, 1); + } else { + retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6); + } + if (retval != STATUS_SUCCESS) { + TRACE_RET(chip, retval); + } + + buf[0] = 0; + buf[1] = 0; + if (type == 1) { + buf[2] = 0; + buf[3] = 0; + buf[4] = 0; + buf[5] = mg_entry_num; + } + retval = ms_write_bytes(chip, PRO_WRITE_REG, (type == 0) ? 1 : 6, NO_WAIT_INT, buf, 6); + if (retval != STATUS_SUCCESS) { + TRACE_RET(chip, retval); + } + + return STATUS_SUCCESS; +} + +/** + * Get MagciGate ID and set Leaf ID to medium. + + * After receiving this SCSI command, adapter shall fulfill 2 tasks below in order: + * 1. send GET_ID TPC command to get MagicGate ID and hold it till Response&challenge CMD. + * 2. send SET_ID TPC command to medium with Leaf ID released by host in this SCSI CMD. + */ +int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip) +{ + int retval; + int i; + unsigned int lun = SCSI_LUN(srb); + u8 buf1[32], buf2[12]; + + RTS51X_DEBUGP(("--%s--\n", __FUNCTION__)); + + if (scsi_bufflen(srb) < 12) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, STATUS_FAIL); + } + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) { + TRACE_RET(chip, retval); + } + + retval = mg_send_ex_cmd(chip, MG_SET_LID, 0); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + TRACE_RET(chip, retval); + } + + memset(buf1, 0, 32); + rts51x_get_xfer_buf(buf2, min(12, (int)scsi_bufflen(srb)), srb); + for (i = 0; i < 8; i++) { + buf1[8+i] = buf2[4+i]; + } + retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf1, 32); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + TRACE_RET(chip, retval); + } + + retval = mg_check_int_error(chip); + if(retval!=STATUS_SUCCESS) + { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + TRACE_RET(chip, retval); + } + + return STATUS_SUCCESS; +} + +/** + * Send Local EKB to host. + + * After receiving this SCSI command, adapter shall read the divided data(1536 bytes totally) + * from medium by using READ_LONG_DATA TPC for 3 times, and report data to host with + * data-length is 1052 bytes. + */ +int mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip) +{ + int retval = STATUS_FAIL; + int bufflen; + unsigned int lun = SCSI_LUN(srb); + u8 *buf = NULL; + + RTS51X_DEBUGP(("--%s--\n", __FUNCTION__)); + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) { + TRACE_RET(chip, retval); + } + + buf = (u8 *)kmalloc(1540, GFP_KERNEL); + if (!buf) { + TRACE_RET(chip, STATUS_NOMEM); + } + + buf[0] = 0x04; + buf[1] = 0x1A; + buf[2] = 0x00; + buf[3] = 0x00; + + retval = mg_send_ex_cmd(chip, MG_GET_LEKB, 0); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_GOTO(chip, GetEKBFinish); + } + + retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, + 3, WAIT_INT, 0, 0, buf + 4, 1536); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + rts51x_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR); + TRACE_GOTO(chip, GetEKBFinish); + } + + retval = mg_check_int_error(chip); + if(retval!=STATUS_SUCCESS) + { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_GOTO(chip, GetEKBFinish); + } + + bufflen = min(1052, (int)scsi_bufflen(srb)); + rts51x_set_xfer_buf(buf, bufflen, srb); + +GetEKBFinish: + if (buf) { + kfree(buf); + } + return retval; +} + +/** + * Send challenge(host) to medium. + + * After receiving this SCSI command, adapter shall sequentially issues TPC commands + * to the medium for writing 8-bytes data as challenge by host within a short data packet. + */ +int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + int bufflen; + int i; + unsigned int lun = SCSI_LUN(srb); + u8 buf[32],tmp; + + RTS51X_DEBUGP(("--%s--\n", __FUNCTION__)); + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) { + TRACE_RET(chip, retval); + } + + retval = mg_send_ex_cmd(chip, MG_GET_ID, 0); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, retval); + } + + retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf, 32); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, retval); + } + + retval = mg_check_int_error(chip); + if(retval!=STATUS_SUCCESS) + { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, retval); + } + + memcpy(ms_card->magic_gate_id, buf, 16); + + for (i = 0; i < 2500; i++) { + RTS51X_READ_REG(chip, MS_TRANS_CFG, &tmp); + if (tmp & (MS_INT_CED | MS_INT_CMDNK | MS_INT_BREQ |MS_INT_ERR)) { + break; + } + + wait_timeout(1); + } + + if (i == 2500) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = mg_send_ex_cmd(chip, MG_SET_RD, 0); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, retval); + } + + bufflen = min(12, (int)scsi_bufflen(srb)); + rts51x_get_xfer_buf(buf, bufflen, srb); + + for (i = 0; i < 8; i++) { + buf[i] = buf[4+i]; + } + for (i = 0; i < 24; i++) { + buf[8+i] = 0; + } + retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, retval); + } + + retval = mg_check_int_error(chip); + if(retval!=STATUS_SUCCESS) + { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, retval); + } + + ms_card->mg_auth = 0; + + return STATUS_SUCCESS; +} + +/** + * Send Response and Challenge data to host. + + * After receiving this SCSI command, adapter shall communicates with the medium, get + * parameters(HRd, Rms, MagicGateID) by using READ_SHORT_DATA TPC and send the + * data to host according to certain format required by MG-R specification. + + * The paremeter MagicGateID is the one that adapter has obtained from the medium by TPC + * commands in Set Leaf ID command phase previously. + */ +int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval,i; + int bufflen; + unsigned int lun = SCSI_LUN(srb); + u8 buf1[32], buf2[36],tmp; + + RTS51X_DEBUGP(("--%s--\n", __FUNCTION__)); + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) { + TRACE_RET(chip, retval); + } + + retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_RET(chip, retval); + } + + retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf1, 32); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_RET(chip, retval); + } + + retval = mg_check_int_error(chip); + if(retval!=STATUS_SUCCESS) + { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_RET(chip, retval); + } + + buf2[0] = 0x00; + buf2[1] = 0x22; + buf2[2] = 0x00; + buf2[3] = 0x00; + + memcpy(buf2 + 4, ms_card->magic_gate_id, 16); + memcpy(buf2 + 20, buf1, 16); + + bufflen = min(36, (int)scsi_bufflen(srb)); + rts51x_set_xfer_buf(buf2, bufflen, srb); + + for (i = 0; i < 2500; i++) { + RTS51X_READ_REG(chip, MS_TRANS_CFG, &tmp); + if (tmp & (MS_INT_CED | MS_INT_CMDNK | MS_INT_BREQ |MS_INT_ERR)) { + break; + } + + wait_timeout(1); + } + + if (i == 2500) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +/** + * Send response(host) to medium. + + * After receiving this SCSI command, adapter shall sequentially issues TPC commands + * to the medium for writing 8-bytes data as challenge by host within a short data packet. + */ +int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + int i; + int bufflen; + unsigned int lun = SCSI_LUN(srb); + u8 buf[32]; + + RTS51X_DEBUGP(("--%s--\n", __FUNCTION__)); + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) { + TRACE_RET(chip, retval); + } + + retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_RET(chip, retval); + } + + bufflen = min(12, (int)scsi_bufflen(srb)); + rts51x_get_xfer_buf(buf, bufflen, srb); + + for (i = 0; i < 8; i++) { + buf[i] = buf[4+i]; + } + for (i = 0; i < 24; i++) { + buf[8+i] = 0; + } + retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_RET(chip, retval); + } + + retval = mg_check_int_error(chip); + if(retval!=STATUS_SUCCESS) + { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_RET(chip, retval); + } + + ms_card->mg_auth = 1; + + return STATUS_SUCCESS; +} + +/** + * Send ICV data to host. + + * After receiving this SCSI command, adapter shall read the divided data(1024 bytes totally) + * from medium by using READ_LONG_DATA TPC for 2 times, and report data to host with + * data-length is 1028 bytes. + + * Since the extra 4 bytes data is just only a prefix to original data that read from medium, so + * that the 4-byte data pushed into Ring buffer precedes data tramsinssion from medium to + * Ring buffer by DMA mechanisim in order to get maximum performance and minimum code + * size simultaneously. + */ +int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + int bufflen; + unsigned int lun = SCSI_LUN(srb); + u8 *buf = NULL; + + RTS51X_DEBUGP(("--%s--\n", __FUNCTION__)); + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) { + TRACE_RET(chip, retval); + } + + buf = (u8 *)kmalloc(1028, GFP_KERNEL); + if (!buf) { + TRACE_RET(chip, STATUS_NOMEM); + } + + buf[0] = 0x04; + buf[1] = 0x02; + buf[2] = 0x00; + buf[3] = 0x00; + + retval = mg_send_ex_cmd(chip, MG_GET_IBD, ms_card->mg_entry_num); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_GOTO(chip, GetICVFinish); + } + + retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, + 2, WAIT_INT, 0, 0, buf + 4, 1024); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + rts51x_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR); + TRACE_GOTO(chip, GetICVFinish); + } + + retval = mg_check_int_error(chip); + if(retval!=STATUS_SUCCESS) + { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_GOTO(chip, GetICVFinish); + } + + bufflen = min(1028, (int)scsi_bufflen(srb)); + rts51x_set_xfer_buf(buf, bufflen, srb); + +GetICVFinish: + if (buf) { + kfree(buf); + } + return retval; +} + +/** + * Send ICV data to medium. + + * After receiving this SCSI command, adapter shall receive 1028 bytes and write the later 1024 + * bytes to medium by WRITE_LONG_DATA TPC consecutively. + + * Since the first 4-bytes data is just only a prefix to original data that sent by host, and it + * should be skipped by shifting DMA pointer before writing 1024 bytes to medium. + */ +int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + int bufflen; +#ifdef MG_SET_ICV_SLOW + int i; +#endif + unsigned int lun = SCSI_LUN(srb); + u8 *buf = NULL; + + RTS51X_DEBUGP(("--%s--\n", __FUNCTION__)); + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) { + TRACE_RET(chip, retval); + } + + buf = (u8 *)kmalloc(1028, GFP_KERNEL); + if (!buf) { + TRACE_RET(chip, STATUS_NOMEM); + } + + bufflen = min(1028, (int)scsi_bufflen(srb)); + rts51x_get_xfer_buf(buf, bufflen, srb); + + retval = mg_send_ex_cmd(chip, MG_SET_IBD, ms_card->mg_entry_num); + if (retval != STATUS_SUCCESS) { + if (ms_card->mg_auth == 0) { + if ((buf[5] & 0xC0) != 0) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + } else { + set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } + } else { + set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } + TRACE_GOTO(chip, SetICVFinish); + } + +#ifdef MG_SET_ICV_SLOW + for (i = 0; i < 2; i++) { + udelay(50); + + rts51x_init_cmd(chip); + + rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, PRO_WRITE_LONG_DATA); + rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, WAIT_INT); + + trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512); + + rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, + MS_TRANSFER_START | MS_TM_NORMAL_WRITE); + rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END); + + retval = rts51x_send_cmd(chip, MODE_CDOR, 100); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + TRACE_GOTO(chip, SetICVFinish); + } + + retval = rts51x_transfer_data_rcc(chip, SND_BULK_PIPE(chip), + buf + 4 + i*512, 512, 0, NULL, 3000, STAGE_DO); + if (retval != STATUS_SUCCESS) { + rts51x_clear_ms_error(chip); + if (ms_card->mg_auth == 0) { + if ((buf[5] & 0xC0) != 0) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + } else { + set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } + } else { + set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } + retval = STATUS_FAIL; + TRACE_GOTO(chip, SetICVFinish); + } + + retval = rts51x_get_rsp(chip, 1, 3000); + +#ifdef RCC_BUG_FIX_SP + if((chip->option.rcc_fail_flag == 2)&&(chip->option.rcc_bug_fix_en==1)) + { + u8 tmpvalue; + int num = 0; + + chip->rcc_read_response = 0; + rts51x_ep0_read_register(chip, SFSM_ED, &tmpvalue); + if(!(tmpvalue&CARD_ERR)) + { + for(num=0;num < 3000;num++) + { + rts51x_ep0_read_register(chip, MS_TRANSFER, &tmpvalue); + if(tmpvalue&MS_TRANSFER_END) + { + break; + } + wait_timeout(1); + } + } + if((tmpvalue&MS_TRANSFER_ERR)||(num==3000)) + { + retval = STATUS_FAIL; + } + else + { + *chip->rsp_buf = tmpvalue; + retval = STATUS_SUCCESS; + } + rts51x_reset_pipe(chip,0); + rts51x_ep0_write_register(chip, MC_FIFO_CTL, FIFO_FLUSH, FIFO_FLUSH); + rts51x_ep0_write_register(chip, SFSM_ED, 0xf8, 0xf8); + } +#endif + + if (CHECK_MS_TRANS_FAIL(chip, retval)||mg_check_int_error(chip)) { + rts51x_clear_ms_error(chip); + if (ms_card->mg_auth == 0) { + if ((buf[5] & 0xC0) != 0) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + } else { + set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } + } else { + set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } + retval = STATUS_FAIL; + TRACE_GOTO(chip, SetICVFinish); + } + } +#else + retval = ms_transfer_data(chip, MS_TM_AUTO_WRITE, PRO_WRITE_LONG_DATA, + 2, WAIT_INT, 0, 0, buf + 4, 1024); + if (retval != STATUS_SUCCESS) { + rts51x_clear_ms_error(chip); + if (ms_card->mg_auth == 0) { + if ((buf[5] & 0xC0) != 0) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + } else { + set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } + } else { + set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } + TRACE_GOTO(chip, SetICVFinish); + } +#endif + +SetICVFinish: + if (buf) { + kfree(buf); + } + return retval; +} + +#endif |
