Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ms_mg.c
Go to the documentation of this file.
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 ([email protected])
20  * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
21  * Maintainer:
22  * Edwin Rong ([email protected])
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 
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 
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) {
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) {
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) {
155  TRACE_RET(chip, retval);
156  }
157  retval = mg_check_int_error(chip);
158  if (retval != STATUS_SUCCESS) {
160  TRACE_RET(chip, retval);
161  }
162 
163  return STATUS_SUCCESS;
164 }
165 
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) {
200  TRACE_GOTO(chip, GetEKBFinish);
201  }
202 
204  3, WAIT_INT, 0, 0, buf + 4, 1536);
205  if (retval != STATUS_SUCCESS) {
208  MS_STOP | MS_CLR_ERR);
209  TRACE_GOTO(chip, GetEKBFinish);
210  }
211  retval = mg_check_int_error(chip);
212  if (retval != STATUS_SUCCESS) {
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 
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) {
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) {
259  TRACE_RET(chip, retval);
260  }
261  retval = mg_check_int_error(chip);
262  if (retval != STATUS_SUCCESS) {
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 &
273  break;
274 
275  wait_timeout(1);
276  }
277 
278  if (i == 2500) {
280  TRACE_RET(chip, STATUS_FAIL);
281  }
282 
283  retval = mg_send_ex_cmd(chip, MG_SET_RD, 0);
284  if (retval != STATUS_SUCCESS) {
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) {
300  TRACE_RET(chip, retval);
301  }
302  retval = mg_check_int_error(chip);
303  if (retval != STATUS_SUCCESS) {
305  TRACE_RET(chip, retval);
306  }
307 
308  ms_card->mg_auth = 0;
309 
310  return STATUS_SUCCESS;
311 }
312 
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) {
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) {
349  TRACE_RET(chip, retval);
350  }
351  retval = mg_check_int_error(chip);
352  if (retval != STATUS_SUCCESS) {
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 |
372  break;
373 
374  wait_timeout(1);
375  }
376 
377  if (i == 2500) {
379  TRACE_RET(chip, STATUS_FAIL);
380  }
381 
382  return STATUS_SUCCESS;
383 }
384 
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) {
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) {
426  TRACE_RET(chip, retval);
427  }
428  retval = mg_check_int_error(chip);
429  if (retval != STATUS_SUCCESS) {
431  TRACE_RET(chip, retval);
432  }
433 
434  ms_card->mg_auth = 1;
435 
436  return STATUS_SUCCESS;
437 }
438 
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) {
478  TRACE_GOTO(chip, GetICVFinish);
479  }
480 
482  2, WAIT_INT, 0, 0, buf + 4, 1024);
483  if (retval != STATUS_SUCCESS) {
486  MS_STOP | MS_CLR_ERR);
487  TRACE_GOTO(chip, GetICVFinish);
488  }
489  retval = mg_check_int_error(chip);
490  if (retval != STATUS_SUCCESS) {
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 
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,
546  else
547  set_sense_type(chip, lun,
549  } else {
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,
564  WAIT_INT);
565 
567 
572 
573  retval = rts51x_send_cmd(chip, MODE_CDOR, 100);
574  if (retval != STATUS_SUCCESS) {
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,
588  else
589  set_sense_type(chip, lun,
591  } else {
592  set_sense_type(chip, lun,
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,
607  else
608  set_sense_type(chip, lun,
610  } else {
611  set_sense_type(chip, lun,
613  }
614  retval = STATUS_FAIL;
615  TRACE_GOTO(chip, SetICVFinish);
616  }
617  }
618 #else
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,
627  else
628  set_sense_type(chip, lun,
630  } else {
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 */