Merge branch 'disintegrate-asm-generic' of git://git.infradead.org/users/dhowells...
[GitHub/mt8127/android_kernel_alcatel_ttab.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
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 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 */
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 */
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 */
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 */
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 transmission from medium to Ring buffer by DMA mechanism
448 * in order to get maximum performance and minimum code size simultaneously.
449 */
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 */
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 */