Merge branch 'for-linville' of git://github.com/kvalo/ath
[firefly-linux-kernel-4.4.55.git] / 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 #include "ms_mg.h"
39
40 #ifdef SUPPORT_MAGIC_GATE
41
42 static int mg_check_int_error(struct rts51x_chip *chip)
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
53 static 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
82 int 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   */
123 int rts51x_mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
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) {
133                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
134                 TRACE_RET(chip, STATUS_FAIL);
135         }
136         rts51x_ms_cleanup_work(chip);
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) {
144                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
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) {
155                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
156                 TRACE_RET(chip, retval);
157         }
158         retval = mg_check_int_error(chip);
159         if (retval != STATUS_SUCCESS) {
160                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
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   */
174 int rts51x_mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip)
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
183         rts51x_ms_cleanup_work(chip);
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) {
200                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
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) {
207                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
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) {
214                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
215                 TRACE_GOTO(chip, GetEKBFinish);
216         }
217
218         bufflen = min(1052, (int)scsi_bufflen(srb));
219         rts51x_set_xfer_buf(buf, bufflen, srb);
220
221 GetEKBFinish:
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   */
233 int rts51x_mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
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
244         rts51x_ms_cleanup_work(chip);
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) {
252                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
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) {
259                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
260                 TRACE_RET(chip, retval);
261         }
262         retval = mg_check_int_error(chip);
263         if (retval != STATUS_SUCCESS) {
264                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
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) {
280                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
281                 TRACE_RET(chip, STATUS_FAIL);
282         }
283
284         retval = mg_send_ex_cmd(chip, MG_SET_RD, 0);
285         if (retval != STATUS_SUCCESS) {
286                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
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) {
300                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
301                 TRACE_RET(chip, retval);
302         }
303         retval = mg_check_int_error(chip);
304         if (retval != STATUS_SUCCESS) {
305                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
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   */
324 int rts51x_mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
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
334         rts51x_ms_cleanup_work(chip);
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) {
342                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
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) {
349                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
350                 TRACE_RET(chip, retval);
351         }
352         retval = mg_check_int_error(chip);
353         if (retval != STATUS_SUCCESS) {
354                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
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) {
379                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
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   */
393 int rts51x_mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
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
404         rts51x_ms_cleanup_work(chip);
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) {
412                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
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) {
426                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
427                 TRACE_RET(chip, retval);
428         }
429         retval = mg_check_int_error(chip);
430         if (retval != STATUS_SUCCESS) {
431                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
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
448   * precedes data transmission from medium to Ring buffer by DMA mechanism
449   * in order to get maximum performance and minimum code size simultaneously.
450   */
451 int rts51x_mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
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
461         rts51x_ms_cleanup_work(chip);
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) {
478                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
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) {
485                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
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) {
492                 rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
493                 TRACE_GOTO(chip, GetICVFinish);
494         }
495
496         bufflen = min(1028, (int)scsi_bufflen(srb));
497         rts51x_set_xfer_buf(buf, bufflen, srb);
498
499 GetICVFinish:
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   */
515 int rts51x_mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
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
528         rts51x_ms_cleanup_work(chip);
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)
545                                 rts51x_set_sense_type(chip, lun,
546                                         SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
547                         else
548                                 rts51x_set_sense_type(chip, lun,
549                                         SENSE_TYPE_MG_WRITE_ERR);
550                 } else {
551                         rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
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
567                 rts51x_trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
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) {
576                         rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
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)
587                                         rts51x_set_sense_type(chip, lun,
588                                                 SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
589                                 else
590                                         rts51x_set_sense_type(chip, lun,
591                                                 SENSE_TYPE_MG_WRITE_ERR);
592                         } else {
593                                 rts51x_set_sense_type(chip, lun,
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)
606                                         rts51x_set_sense_type(chip, lun,
607                                                 SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
608                                 else
609                                         rts51x_set_sense_type(chip, lun,
610                                                 SENSE_TYPE_MG_WRITE_ERR);
611                         } else {
612                                 rts51x_set_sense_type(chip, lun,
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)
626                                 rts51x_set_sense_type(chip, lun,
627                                         SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
628                         else
629                                 rts51x_set_sense_type(chip, lun,
630                                         SENSE_TYPE_MG_WRITE_ERR);
631                 } else {
632                         rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
633                 }
634                 TRACE_GOTO(chip, SetICVFinish);
635         }
636 #endif
637
638 SetICVFinish:
639         kfree(buf);
640         return retval;
641 }
642
643 #endif /* SUPPORT_MAGIC_GATE */