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" |
38 | |
39 | #ifdef SUPPORT_MAGIC_GATE |
40 | |
8ce9002e |
41 | static int mg_check_int_error(struct rts51x_chip *chip) |
1dac4186 |
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 |
7086e6e5 |
447 | * precedes data transmission from medium to Ring buffer by DMA mechanism |
1dac4186 |
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 */ |