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