]> Pileus Git - ~andy/linux/blob - drivers/staging/rts5139/ms_mg.c
Merge tag 'v3.8-rc7' into next
[~andy/linux] / drivers / staging / rts5139 / ms_mg.c
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
41 static 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
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
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   */
122 int rts51x_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                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
133                 TRACE_RET(chip, STATUS_FAIL);
134         }
135         rts51x_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                 rts51x_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                 rts51x_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                 rts51x_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   */
173 int rts51x_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         rts51x_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                 rts51x_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                 rts51x_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                 rts51x_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   */
232 int rts51x_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         rts51x_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                 rts51x_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                 rts51x_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                 rts51x_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                 rts51x_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                 rts51x_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                 rts51x_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                 rts51x_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   */
323 int rts51x_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         rts51x_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                 rts51x_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                 rts51x_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                 rts51x_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                 rts51x_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   */
392 int rts51x_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         rts51x_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                 rts51x_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                 rts51x_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                 rts51x_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 transmission from medium to Ring buffer by DMA mechanism
448   * in order to get maximum performance and minimum code size simultaneously.
449   */
450 int rts51x_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         rts51x_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                 rts51x_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                 rts51x_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                 rts51x_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   */
514 int rts51x_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         rts51x_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                                 rts51x_set_sense_type(chip, lun,
545                                         SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
546                         else
547                                 rts51x_set_sense_type(chip, lun,
548                                         SENSE_TYPE_MG_WRITE_ERR);
549                 } else {
550                         rts51x_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                 rts51x_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                         rts51x_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                                         rts51x_set_sense_type(chip, lun,
587                                                 SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
588                                 else
589                                         rts51x_set_sense_type(chip, lun,
590                                                 SENSE_TYPE_MG_WRITE_ERR);
591                         } else {
592                                 rts51x_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                                         rts51x_set_sense_type(chip, lun,
606                                                 SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
607                                 else
608                                         rts51x_set_sense_type(chip, lun,
609                                                 SENSE_TYPE_MG_WRITE_ERR);
610                         } else {
611                                 rts51x_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                                 rts51x_set_sense_type(chip, lun,
626                                         SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
627                         else
628                                 rts51x_set_sense_type(chip, lun,
629                                         SENSE_TYPE_MG_WRITE_ERR);
630                 } else {
631                         rts51x_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 */