• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Driver for Realtek RTS51xx USB card reader
2  *
3  * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2, or (at your option) any
8  * later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author:
19  *   wwang (wei_wang@realsil.com.cn)
20  *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
21  * Maintainer:
22  *   Edwin Rong (edwin_rong@realsil.com.cn)
23  *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
24  */
25 
26 #include <linux/blkdev.h>
27 #include <linux/kthread.h>
28 #include <linux/sched.h>
29 #include <linux/slab.h>
30 
31 #include "debug.h"
32 #include "trace.h"
33 #include "rts51x.h"
34 #include "rts51x_transport.h"
35 #include "rts51x_scsi.h"
36 #include "rts51x_card.h"
37 #include "ms.h"
38 
39 #ifdef SUPPORT_MAGIC_GATE
40 
mg_check_int_error(struct rts51x_chip * chip)41 int mg_check_int_error(struct rts51x_chip *chip)
42 {
43 	u8 value;
44 
45 	rts51x_read_register(chip, MS_TRANS_CFG, &value);
46 	if (value & (INT_ERR | INT_CMDNK))
47 		TRACE_RET(chip, STATUS_FAIL);
48 
49 	return STATUS_SUCCESS;
50 }
51 
mg_send_ex_cmd(struct rts51x_chip * chip,u8 cmd,u8 entry_num)52 static int mg_send_ex_cmd(struct rts51x_chip *chip, u8 cmd, u8 entry_num)
53 {
54 	int retval, i;
55 	u8 data[8];
56 
57 	data[0] = cmd;
58 	data[1] = 0;
59 	data[2] = 0;
60 	data[3] = 0;
61 	data[4] = 0;
62 	data[5] = 0;
63 	data[6] = entry_num;
64 	data[7] = 0;
65 
66 	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
67 		retval =
68 		    ms_write_bytes(chip, PRO_EX_SET_CMD, 7, WAIT_INT, data, 8);
69 		if (retval == STATUS_SUCCESS)
70 			break;
71 	}
72 	if (i == MS_MAX_RETRY_COUNT)
73 		TRACE_RET(chip, STATUS_FAIL);
74 	retval = mg_check_int_error(chip);
75 	if (retval != STATUS_SUCCESS)
76 		TRACE_RET(chip, STATUS_FAIL);
77 
78 	return STATUS_SUCCESS;
79 }
80 
mg_set_tpc_para_sub(struct rts51x_chip * chip,int type,u8 mg_entry_num)81 int mg_set_tpc_para_sub(struct rts51x_chip *chip, int type, u8 mg_entry_num)
82 {
83 	int retval;
84 	u8 buf[6];
85 
86 	RTS51X_DEBUGP("--%s--\n", __func__);
87 
88 	if (type == 0)
89 		retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_TPCParm, 1);
90 	else
91 		retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6);
92 	if (retval != STATUS_SUCCESS)
93 		TRACE_RET(chip, retval);
94 
95 	buf[0] = 0;
96 	buf[1] = 0;
97 	if (type == 1) {
98 		buf[2] = 0;
99 		buf[3] = 0;
100 		buf[4] = 0;
101 		buf[5] = mg_entry_num;
102 	}
103 	retval =
104 	    ms_write_bytes(chip, PRO_WRITE_REG, (type == 0) ? 1 : 6,
105 			   NO_WAIT_INT, buf, 6);
106 	if (retval != STATUS_SUCCESS)
107 		TRACE_RET(chip, retval);
108 
109 	return STATUS_SUCCESS;
110 }
111 
112 /**
113   * Get MagciGate ID and set Leaf ID to medium.
114 
115   * After receiving this SCSI command, adapter shall fulfill 2 tasks
116   * below in order:
117   * 1. send GET_ID TPC command to get MagicGate ID and hold it till
118   * Response&challenge CMD.
119   * 2. send SET_ID TPC command to medium with Leaf ID released by host
120   * in this SCSI CMD.
121   */
mg_set_leaf_id(struct scsi_cmnd * srb,struct rts51x_chip * chip)122 int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
123 {
124 	int retval;
125 	int i;
126 	unsigned int lun = SCSI_LUN(srb);
127 	u8 buf1[32], buf2[12];
128 
129 	RTS51X_DEBUGP("--%s--\n", __func__);
130 
131 	if (scsi_bufflen(srb) < 12) {
132 		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
133 		TRACE_RET(chip, STATUS_FAIL);
134 	}
135 	ms_cleanup_work(chip);
136 
137 	retval = ms_switch_clock(chip);
138 	if (retval != STATUS_SUCCESS)
139 		TRACE_RET(chip, retval);
140 
141 	retval = mg_send_ex_cmd(chip, MG_SET_LID, 0);
142 	if (retval != STATUS_SUCCESS) {
143 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
144 		TRACE_RET(chip, retval);
145 	}
146 
147 	memset(buf1, 0, 32);
148 	rts51x_get_xfer_buf(buf2, min(12, (int)scsi_bufflen(srb)), srb);
149 	for (i = 0; i < 8; i++)
150 		buf1[8 + i] = buf2[4 + i];
151 	retval =
152 	    ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf1, 32);
153 	if (retval != STATUS_SUCCESS) {
154 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
155 		TRACE_RET(chip, retval);
156 	}
157 	retval = mg_check_int_error(chip);
158 	if (retval != STATUS_SUCCESS) {
159 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
160 		TRACE_RET(chip, retval);
161 	}
162 
163 	return STATUS_SUCCESS;
164 }
165 
166 /**
167   * Send Local EKB to host.
168 
169   * After receiving this SCSI command, adapter shall read the divided
170   * data(1536 bytes totally) from medium by using READ_LONG_DATA TPC
171   * for 3 times, and report data to host with data-length is 1052 bytes.
172   */
mg_get_local_EKB(struct scsi_cmnd * srb,struct rts51x_chip * chip)173 int mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip)
174 {
175 	int retval = STATUS_FAIL;
176 	int bufflen;
177 	unsigned int lun = SCSI_LUN(srb);
178 	u8 *buf = NULL;
179 
180 	RTS51X_DEBUGP("--%s--\n", __func__);
181 
182 	ms_cleanup_work(chip);
183 
184 	retval = ms_switch_clock(chip);
185 	if (retval != STATUS_SUCCESS)
186 		TRACE_RET(chip, retval);
187 
188 	buf = kmalloc(1540, GFP_KERNEL);
189 	if (!buf)
190 		TRACE_RET(chip, STATUS_NOMEM);
191 
192 	buf[0] = 0x04;
193 	buf[1] = 0x1A;
194 	buf[2] = 0x00;
195 	buf[3] = 0x00;
196 
197 	retval = mg_send_ex_cmd(chip, MG_GET_LEKB, 0);
198 	if (retval != STATUS_SUCCESS) {
199 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
200 		TRACE_GOTO(chip, GetEKBFinish);
201 	}
202 
203 	retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
204 				  3, WAIT_INT, 0, 0, buf + 4, 1536);
205 	if (retval != STATUS_SUCCESS) {
206 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
207 		rts51x_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR,
208 				      MS_STOP | MS_CLR_ERR);
209 		TRACE_GOTO(chip, GetEKBFinish);
210 	}
211 	retval = mg_check_int_error(chip);
212 	if (retval != STATUS_SUCCESS) {
213 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
214 		TRACE_GOTO(chip, GetEKBFinish);
215 	}
216 
217 	bufflen = min(1052, (int)scsi_bufflen(srb));
218 	rts51x_set_xfer_buf(buf, bufflen, srb);
219 
220 GetEKBFinish:
221 	kfree(buf);
222 	return retval;
223 }
224 
225 /**
226   * Send challenge(host) to medium.
227 
228   * After receiving this SCSI command, adapter shall sequentially issues
229   * TPC commands to the medium for writing 8-bytes data as challenge
230   * by host within a short data packet.
231   */
mg_chg(struct scsi_cmnd * srb,struct rts51x_chip * chip)232 int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
233 {
234 	struct ms_info *ms_card = &(chip->ms_card);
235 	int retval;
236 	int bufflen;
237 	int i;
238 	unsigned int lun = SCSI_LUN(srb);
239 	u8 buf[32], tmp;
240 
241 	RTS51X_DEBUGP("--%s--\n", __func__);
242 
243 	ms_cleanup_work(chip);
244 
245 	retval = ms_switch_clock(chip);
246 	if (retval != STATUS_SUCCESS)
247 		TRACE_RET(chip, retval);
248 
249 	retval = mg_send_ex_cmd(chip, MG_GET_ID, 0);
250 	if (retval != STATUS_SUCCESS) {
251 		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
252 		TRACE_RET(chip, retval);
253 	}
254 
255 	retval =
256 	    ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf, 32);
257 	if (retval != STATUS_SUCCESS) {
258 		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
259 		TRACE_RET(chip, retval);
260 	}
261 	retval = mg_check_int_error(chip);
262 	if (retval != STATUS_SUCCESS) {
263 		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
264 		TRACE_RET(chip, retval);
265 	}
266 
267 	memcpy(ms_card->magic_gate_id, buf, 16);
268 
269 	for (i = 0; i < 2500; i++) {
270 		RTS51X_READ_REG(chip, MS_TRANS_CFG, &tmp);
271 		if (tmp &
272 		    (MS_INT_CED | MS_INT_CMDNK | MS_INT_BREQ | MS_INT_ERR))
273 			break;
274 
275 		wait_timeout(1);
276 	}
277 
278 	if (i == 2500) {
279 		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
280 		TRACE_RET(chip, STATUS_FAIL);
281 	}
282 
283 	retval = mg_send_ex_cmd(chip, MG_SET_RD, 0);
284 	if (retval != STATUS_SUCCESS) {
285 		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
286 		TRACE_RET(chip, retval);
287 	}
288 
289 	bufflen = min(12, (int)scsi_bufflen(srb));
290 	rts51x_get_xfer_buf(buf, bufflen, srb);
291 
292 	for (i = 0; i < 8; i++)
293 		buf[i] = buf[4 + i];
294 	for (i = 0; i < 24; i++)
295 		buf[8 + i] = 0;
296 	retval =
297 	    ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32);
298 	if (retval != STATUS_SUCCESS) {
299 		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
300 		TRACE_RET(chip, retval);
301 	}
302 	retval = mg_check_int_error(chip);
303 	if (retval != STATUS_SUCCESS) {
304 		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
305 		TRACE_RET(chip, retval);
306 	}
307 
308 	ms_card->mg_auth = 0;
309 
310 	return STATUS_SUCCESS;
311 }
312 
313 /**
314   * Send Response and Challenge data  to host.
315 
316   * After receiving this SCSI command, adapter shall communicates with
317   * the medium, get parameters(HRd, Rms, MagicGateID) by using READ_SHORT_DATA
318   * TPC and send the data to host according to certain format required by
319   * MG-R specification.
320   * The paremeter MagicGateID is the one that adapter has obtained from
321   * the medium by TPC commands in Set Leaf ID command phase previously.
322   */
mg_get_rsp_chg(struct scsi_cmnd * srb,struct rts51x_chip * chip)323 int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
324 {
325 	struct ms_info *ms_card = &(chip->ms_card);
326 	int retval, i;
327 	int bufflen;
328 	unsigned int lun = SCSI_LUN(srb);
329 	u8 buf1[32], buf2[36], tmp;
330 
331 	RTS51X_DEBUGP("--%s--\n", __func__);
332 
333 	ms_cleanup_work(chip);
334 
335 	retval = ms_switch_clock(chip);
336 	if (retval != STATUS_SUCCESS)
337 		TRACE_RET(chip, retval);
338 
339 	retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0);
340 	if (retval != STATUS_SUCCESS) {
341 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
342 		TRACE_RET(chip, retval);
343 	}
344 
345 	retval =
346 	    ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf1, 32);
347 	if (retval != STATUS_SUCCESS) {
348 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
349 		TRACE_RET(chip, retval);
350 	}
351 	retval = mg_check_int_error(chip);
352 	if (retval != STATUS_SUCCESS) {
353 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
354 		TRACE_RET(chip, retval);
355 	}
356 
357 	buf2[0] = 0x00;
358 	buf2[1] = 0x22;
359 	buf2[2] = 0x00;
360 	buf2[3] = 0x00;
361 
362 	memcpy(buf2 + 4, ms_card->magic_gate_id, 16);
363 	memcpy(buf2 + 20, buf1, 16);
364 
365 	bufflen = min(36, (int)scsi_bufflen(srb));
366 	rts51x_set_xfer_buf(buf2, bufflen, srb);
367 
368 	for (i = 0; i < 2500; i++) {
369 		RTS51X_READ_REG(chip, MS_TRANS_CFG, &tmp);
370 		if (tmp & (MS_INT_CED | MS_INT_CMDNK |
371 				MS_INT_BREQ | MS_INT_ERR))
372 			break;
373 
374 		wait_timeout(1);
375 	}
376 
377 	if (i == 2500) {
378 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
379 		TRACE_RET(chip, STATUS_FAIL);
380 	}
381 
382 	return STATUS_SUCCESS;
383 }
384 
385 /**
386   * Send response(host) to medium.
387 
388   * After receiving this SCSI command, adapter shall sequentially
389   * issues TPC commands to the medium for writing 8-bytes data as
390   * challenge by host within a short data packet.
391   */
mg_rsp(struct scsi_cmnd * srb,struct rts51x_chip * chip)392 int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
393 {
394 	struct ms_info *ms_card = &(chip->ms_card);
395 	int retval;
396 	int i;
397 	int bufflen;
398 	unsigned int lun = SCSI_LUN(srb);
399 	u8 buf[32];
400 
401 	RTS51X_DEBUGP("--%s--\n", __func__);
402 
403 	ms_cleanup_work(chip);
404 
405 	retval = ms_switch_clock(chip);
406 	if (retval != STATUS_SUCCESS)
407 		TRACE_RET(chip, retval);
408 
409 	retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0);
410 	if (retval != STATUS_SUCCESS) {
411 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
412 		TRACE_RET(chip, retval);
413 	}
414 
415 	bufflen = min(12, (int)scsi_bufflen(srb));
416 	rts51x_get_xfer_buf(buf, bufflen, srb);
417 
418 	for (i = 0; i < 8; i++)
419 		buf[i] = buf[4 + i];
420 	for (i = 0; i < 24; i++)
421 		buf[8 + i] = 0;
422 	retval =
423 	    ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32);
424 	if (retval != STATUS_SUCCESS) {
425 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
426 		TRACE_RET(chip, retval);
427 	}
428 	retval = mg_check_int_error(chip);
429 	if (retval != STATUS_SUCCESS) {
430 		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
431 		TRACE_RET(chip, retval);
432 	}
433 
434 	ms_card->mg_auth = 1;
435 
436 	return STATUS_SUCCESS;
437 }
438 
439 /** * Send ICV data to host.
440 
441   * After receiving this SCSI command, adapter shall read the divided
442   * data(1024 bytes totally) from medium by using READ_LONG_DATA TPC
443   * for 2 times, and report data to host with data-length is 1028 bytes.
444   *
445   * Since the extra 4 bytes data is just only a prefix to original data
446   * that read from medium, so that the 4-byte data pushed into Ring buffer
447   * precedes data tramsinssion from medium to Ring buffer by DMA mechanisim
448   * in order to get maximum performance and minimum code size simultaneously.
449   */
mg_get_ICV(struct scsi_cmnd * srb,struct rts51x_chip * chip)450 int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
451 {
452 	struct ms_info *ms_card = &(chip->ms_card);
453 	int retval;
454 	int bufflen;
455 	unsigned int lun = SCSI_LUN(srb);
456 	u8 *buf = NULL;
457 
458 	RTS51X_DEBUGP("--%s--\n", __func__);
459 
460 	ms_cleanup_work(chip);
461 
462 	retval = ms_switch_clock(chip);
463 	if (retval != STATUS_SUCCESS)
464 		TRACE_RET(chip, retval);
465 
466 	buf = kmalloc(1028, GFP_KERNEL);
467 	if (!buf)
468 		TRACE_RET(chip, STATUS_NOMEM);
469 
470 	buf[0] = 0x04;
471 	buf[1] = 0x02;
472 	buf[2] = 0x00;
473 	buf[3] = 0x00;
474 
475 	retval = mg_send_ex_cmd(chip, MG_GET_IBD, ms_card->mg_entry_num);
476 	if (retval != STATUS_SUCCESS) {
477 		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
478 		TRACE_GOTO(chip, GetICVFinish);
479 	}
480 
481 	retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
482 				  2, WAIT_INT, 0, 0, buf + 4, 1024);
483 	if (retval != STATUS_SUCCESS) {
484 		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
485 		rts51x_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR,
486 				      MS_STOP | MS_CLR_ERR);
487 		TRACE_GOTO(chip, GetICVFinish);
488 	}
489 	retval = mg_check_int_error(chip);
490 	if (retval != STATUS_SUCCESS) {
491 		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
492 		TRACE_GOTO(chip, GetICVFinish);
493 	}
494 
495 	bufflen = min(1028, (int)scsi_bufflen(srb));
496 	rts51x_set_xfer_buf(buf, bufflen, srb);
497 
498 GetICVFinish:
499 	kfree(buf);
500 	return retval;
501 }
502 
503 /**
504   * Send ICV data to medium.
505 
506   * After receiving this SCSI command, adapter shall receive 1028 bytes
507   * and write the later 1024 bytes to medium by WRITE_LONG_DATA TPC
508   * consecutively.
509   *
510   * Since the first 4-bytes data is just only a prefix to original data
511   * that sent by host, and it should be skipped by shifting DMA pointer
512   * before writing 1024 bytes to medium.
513   */
mg_set_ICV(struct scsi_cmnd * srb,struct rts51x_chip * chip)514 int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
515 {
516 	struct ms_info *ms_card = &(chip->ms_card);
517 	int retval;
518 	int bufflen;
519 #ifdef MG_SET_ICV_SLOW
520 	int i;
521 #endif
522 	unsigned int lun = SCSI_LUN(srb);
523 	u8 *buf = NULL;
524 
525 	RTS51X_DEBUGP("--%s--\n", __func__);
526 
527 	ms_cleanup_work(chip);
528 
529 	retval = ms_switch_clock(chip);
530 	if (retval != STATUS_SUCCESS)
531 		TRACE_RET(chip, retval);
532 
533 	buf = kmalloc(1028, GFP_KERNEL);
534 	if (!buf)
535 		TRACE_RET(chip, STATUS_NOMEM);
536 
537 	bufflen = min(1028, (int)scsi_bufflen(srb));
538 	rts51x_get_xfer_buf(buf, bufflen, srb);
539 
540 	retval = mg_send_ex_cmd(chip, MG_SET_IBD, ms_card->mg_entry_num);
541 	if (retval != STATUS_SUCCESS) {
542 		if (ms_card->mg_auth == 0) {
543 			if ((buf[5] & 0xC0) != 0)
544 				set_sense_type(chip, lun,
545 					SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
546 			else
547 				set_sense_type(chip, lun,
548 					SENSE_TYPE_MG_WRITE_ERR);
549 		} else {
550 			set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
551 		}
552 		TRACE_GOTO(chip, SetICVFinish);
553 	}
554 
555 #ifdef MG_SET_ICV_SLOW
556 	for (i = 0; i < 2; i++) {
557 		udelay(50);
558 
559 		rts51x_init_cmd(chip);
560 
561 		rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF,
562 			       PRO_WRITE_LONG_DATA);
563 		rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF,
564 			       WAIT_INT);
565 
566 		trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
567 
568 		rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
569 			       MS_TRANSFER_START | MS_TM_NORMAL_WRITE);
570 		rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER,
571 			       MS_TRANSFER_END, MS_TRANSFER_END);
572 
573 		retval = rts51x_send_cmd(chip, MODE_CDOR, 100);
574 		if (retval != STATUS_SUCCESS) {
575 			set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
576 			TRACE_GOTO(chip, SetICVFinish);
577 		}
578 
579 		retval = rts51x_transfer_data_rcc(chip, SND_BULK_PIPE(chip),
580 						  buf + 4 + i * 512, 512, 0,
581 						  NULL, 3000, STAGE_DO);
582 		if (retval != STATUS_SUCCESS) {
583 			rts51x_clear_ms_error(chip);
584 			if (ms_card->mg_auth == 0) {
585 				if ((buf[5] & 0xC0) != 0)
586 					set_sense_type(chip, lun,
587 						SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
588 				else
589 					set_sense_type(chip, lun,
590 						SENSE_TYPE_MG_WRITE_ERR);
591 			} else {
592 				set_sense_type(chip, lun,
593 					       SENSE_TYPE_MG_WRITE_ERR);
594 			}
595 			retval = STATUS_FAIL;
596 			TRACE_GOTO(chip, SetICVFinish);
597 		}
598 
599 		retval = rts51x_get_rsp(chip, 1, 3000);
600 		if (CHECK_MS_TRANS_FAIL(chip, retval)
601 		    || mg_check_int_error(chip)) {
602 			rts51x_clear_ms_error(chip);
603 			if (ms_card->mg_auth == 0) {
604 				if ((buf[5] & 0xC0) != 0)
605 					set_sense_type(chip, lun,
606 						SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
607 				else
608 					set_sense_type(chip, lun,
609 						SENSE_TYPE_MG_WRITE_ERR);
610 			} else {
611 				set_sense_type(chip, lun,
612 					       SENSE_TYPE_MG_WRITE_ERR);
613 			}
614 			retval = STATUS_FAIL;
615 			TRACE_GOTO(chip, SetICVFinish);
616 		}
617 	}
618 #else
619 	retval = ms_transfer_data(chip, MS_TM_AUTO_WRITE, PRO_WRITE_LONG_DATA,
620 				  2, WAIT_INT, 0, 0, buf + 4, 1024);
621 	if (retval != STATUS_SUCCESS) {
622 		rts51x_clear_ms_error(chip);
623 		if (ms_card->mg_auth == 0) {
624 			if ((buf[5] & 0xC0) != 0)
625 				set_sense_type(chip, lun,
626 					SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
627 			else
628 				set_sense_type(chip, lun,
629 					SENSE_TYPE_MG_WRITE_ERR);
630 		} else {
631 			set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
632 		}
633 		TRACE_GOTO(chip, SetICVFinish);
634 	}
635 #endif
636 
637 SetICVFinish:
638 	kfree(buf);
639 	return retval;
640 }
641 
642 #endif /* SUPPORT_MAGIC_GATE */
643