Commit | Line | Data |
---|---|---|
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 "rts51x_chip.h" | |
38 | #include "sd.h" | |
39 | ||
40 | #ifdef SUPPORT_CPRM | |
41 | ||
42 | static inline int get_rsp_type(u8 rsp_code, u8 *rsp_type, int *rsp_len) | |
43 | { | |
44 | if (!rsp_type || !rsp_len) | |
45 | return STATUS_FAIL; | |
46 | ||
47 | switch (rsp_code) { | |
48 | case 0x03: | |
49 | *rsp_type = SD_RSP_TYPE_R0; /* no response */ | |
50 | *rsp_len = 0; | |
51 | break; | |
52 | ||
53 | case 0x04: | |
54 | *rsp_type = SD_RSP_TYPE_R1; /* R1,R6(,R4,R5) */ | |
55 | *rsp_len = 6; | |
56 | break; | |
57 | ||
58 | case 0x05: | |
59 | *rsp_type = SD_RSP_TYPE_R1b; /* R1b */ | |
60 | *rsp_len = 6; | |
61 | break; | |
62 | ||
63 | case 0x06: | |
64 | *rsp_type = SD_RSP_TYPE_R2; /* R2 */ | |
65 | *rsp_len = 17; | |
66 | break; | |
67 | ||
68 | case 0x07: | |
69 | *rsp_type = SD_RSP_TYPE_R3; /* R3 */ | |
70 | *rsp_len = 6; | |
71 | break; | |
72 | ||
73 | default: | |
74 | return STATUS_FAIL; | |
75 | } | |
76 | ||
77 | return STATUS_SUCCESS; | |
78 | } | |
79 | ||
b9914e7d | 80 | static int ext_sd_send_cmd_get_rsp(struct rts51x_chip *chip, u8 cmd_idx, |
1dac4186 | 81 | u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, |
82 | int special_check) | |
83 | { | |
84 | int retval; | |
85 | int timeout = 50; | |
86 | u16 reg_addr; | |
87 | u8 buf[17], stat; | |
88 | int len = 2; | |
89 | int rty_cnt = 0; | |
90 | ||
91 | RTS51X_DEBUGP("EXT SD/MMC CMD %d\n", cmd_idx); | |
92 | ||
93 | if (rsp_type == SD_RSP_TYPE_R1b) | |
94 | timeout = 3000; | |
95 | ||
96 | RTY_SEND_CMD: | |
97 | ||
98 | rts51x_init_cmd(chip); | |
99 | ||
100 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx); | |
101 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8) (arg >> 24)); | |
102 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8) (arg >> 16)); | |
103 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8) (arg >> 8)); | |
104 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8) arg); | |
105 | ||
106 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); | |
107 | rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, | |
108 | 0x01, PINGPONG_BUFFER); | |
109 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, | |
110 | 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); | |
111 | rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, | |
112 | SD_TRANSFER_END); | |
113 | ||
114 | rts51x_add_cmd(chip, READ_REG_CMD, SD_STAT1, 0, 0); | |
115 | ||
116 | if (CHECK_USB(chip, USB_20)) { | |
117 | if (rsp_type == SD_RSP_TYPE_R2) { | |
118 | for (reg_addr = PPBUF_BASE2; | |
119 | reg_addr < PPBUF_BASE2 + 16; reg_addr++) { | |
120 | rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0, | |
121 | 0); | |
122 | } | |
123 | len = 19; | |
124 | } else if (rsp_type != SD_RSP_TYPE_R0) { | |
125 | /* Read data from SD_CMDx registers */ | |
126 | for (reg_addr = SD_CMD0; reg_addr <= SD_CMD4; | |
127 | reg_addr++) { | |
128 | rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0, | |
129 | 0); | |
130 | } | |
131 | len = 8; | |
132 | } else { | |
133 | len = 3; | |
134 | } | |
135 | rts51x_add_cmd(chip, READ_REG_CMD, SD_CMD5, 0, 0); | |
136 | } else { | |
137 | len = 2; | |
138 | } | |
139 | ||
140 | retval = rts51x_send_cmd(chip, MODE_CR, 100); | |
141 | if (retval != STATUS_SUCCESS) | |
142 | TRACE_RET(chip, retval); | |
143 | ||
144 | retval = rts51x_get_rsp(chip, len, timeout); | |
145 | ||
146 | if (CHECK_SD_TRANS_FAIL(chip, retval)) { | |
147 | rts51x_clear_sd_error(chip); | |
148 | ||
149 | if (retval == STATUS_TIMEDOUT) { | |
150 | if (rsp_type & SD_WAIT_BUSY_END) { | |
151 | retval = sd_check_data0_status(chip); | |
152 | if (retval != STATUS_SUCCESS) | |
153 | TRACE_RET(chip, retval); | |
154 | } | |
155 | } | |
156 | TRACE_RET(chip, STATUS_FAIL); | |
157 | } | |
158 | ||
159 | if (rsp_type == SD_RSP_TYPE_R0) | |
160 | return STATUS_SUCCESS; | |
161 | ||
162 | if (CHECK_USB(chip, USB_20)) { | |
163 | rts51x_read_rsp_buf(chip, 2, buf, len - 2); | |
164 | } else { | |
165 | if (rsp_type == SD_RSP_TYPE_R2) { | |
166 | reg_addr = PPBUF_BASE2; | |
167 | len = 16; | |
168 | } else { | |
169 | reg_addr = SD_CMD0; | |
170 | len = 5; | |
171 | } | |
172 | retval = | |
173 | rts51x_seq_read_register(chip, reg_addr, | |
174 | (unsigned short)len, buf); | |
175 | if (retval != STATUS_SUCCESS) | |
176 | TRACE_RET(chip, retval); | |
177 | RTS51X_READ_REG(chip, SD_CMD5, buf + len); | |
178 | } | |
179 | stat = chip->rsp_buf[1]; | |
180 | ||
181 | if ((buf[0] & 0xC0) != 0) | |
182 | TRACE_RET(chip, STATUS_FAIL); | |
183 | ||
184 | if (!(rsp_type & SD_NO_CHECK_CRC7)) { | |
185 | if (stat & SD_CRC7_ERR) { | |
186 | if (cmd_idx == WRITE_MULTIPLE_BLOCK) | |
187 | TRACE_RET(chip, STATUS_FAIL); | |
188 | if (rty_cnt < SD_MAX_RETRY_COUNT) { | |
189 | wait_timeout(20); | |
190 | rty_cnt++; | |
191 | goto RTY_SEND_CMD; | |
192 | } else { | |
193 | TRACE_RET(chip, STATUS_FAIL); | |
194 | } | |
195 | } | |
196 | } | |
197 | ||
198 | if ((cmd_idx == SELECT_CARD) || (cmd_idx == APP_CMD) || | |
199 | (cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) { | |
200 | if ((cmd_idx != STOP_TRANSMISSION) && (special_check == 0)) { | |
201 | if (buf[1] & 0x80) | |
202 | TRACE_RET(chip, STATUS_FAIL); | |
203 | } | |
dee0dc0d | 204 | if (buf[1] & 0x7F) |
1dac4186 | 205 | TRACE_RET(chip, STATUS_FAIL); |
1dac4186 | 206 | if (buf[2] & 0xF8) |
207 | TRACE_RET(chip, STATUS_FAIL); | |
208 | ||
209 | if (cmd_idx == SELECT_CARD) { | |
210 | if (rsp_type == SD_RSP_TYPE_R2) { | |
211 | if ((buf[3] & 0x1E) != 0x04) | |
212 | TRACE_RET(chip, STATUS_FAIL); | |
213 | } else if (rsp_type == SD_RSP_TYPE_R2) { | |
214 | if ((buf[3] & 0x1E) != 0x03) | |
215 | TRACE_RET(chip, STATUS_FAIL); | |
216 | } | |
217 | } | |
218 | } | |
219 | ||
220 | if (rsp && rsp_len) | |
221 | memcpy(rsp, buf, rsp_len); | |
222 | ||
223 | return STATUS_SUCCESS; | |
224 | } | |
225 | ||
dee0dc0d AA |
226 | static int ext_sd_get_rsp(struct rts51x_chip *chip, int len, |
227 | u8 *rsp, u8 rsp_type) | |
1dac4186 | 228 | { |
229 | int retval, rsp_len; | |
230 | u16 reg_addr; | |
231 | ||
232 | if (rsp_type == SD_RSP_TYPE_R0) | |
233 | return STATUS_SUCCESS; | |
234 | ||
235 | rts51x_init_cmd(chip); | |
236 | ||
237 | if (rsp_type == SD_RSP_TYPE_R2) { | |
238 | for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; | |
239 | reg_addr++) { | |
240 | rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0); | |
241 | } | |
242 | rsp_len = 17; | |
243 | } else if (rsp_type != SD_RSP_TYPE_R0) { | |
244 | for (reg_addr = SD_CMD0; reg_addr <= SD_CMD4; reg_addr++) | |
245 | rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0); | |
246 | rsp_len = 6; | |
247 | } | |
248 | rts51x_add_cmd(chip, READ_REG_CMD, SD_CMD5, 0xFF, 0); | |
249 | ||
250 | retval = rts51x_send_cmd(chip, MODE_CR, 100); | |
251 | if (retval != STATUS_SUCCESS) | |
252 | TRACE_RET(chip, retval); | |
253 | ||
254 | retval = rts51x_get_rsp(chip, rsp_len, 100); | |
255 | ||
256 | if (retval != STATUS_SUCCESS) | |
257 | TRACE_RET(chip, retval); | |
258 | ||
259 | if (rsp) { | |
260 | int min_len = (rsp_len < len) ? rsp_len : len; | |
261 | ||
262 | memcpy(rsp, rts51x_get_rsp_data(chip), min_len); | |
263 | ||
264 | RTS51X_DEBUGP("min_len = %d\n", min_len); | |
265 | RTS51X_DEBUGP("Response in cmd buf: 0x%x 0x%x 0x%x 0x%x\n", | |
266 | rsp[0], rsp[1], rsp[2], rsp[3]); | |
267 | } | |
268 | ||
269 | return STATUS_SUCCESS; | |
270 | } | |
271 | ||
272 | int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun, | |
273 | u8 cmd_idx, u8 standby, u8 acmd, u8 rsp_code, | |
274 | u32 arg) | |
275 | { | |
276 | struct sd_info *sd_card = &(chip->sd_card); | |
277 | int retval, rsp_len; | |
278 | u8 rsp_type; | |
279 | ||
280 | retval = sd_switch_clock(chip); | |
281 | if (retval != STATUS_SUCCESS) | |
282 | TRACE_RET(chip, TRANSPORT_FAILED); | |
283 | ||
284 | if (sd_card->pre_cmd_err) { | |
285 | sd_card->pre_cmd_err = 0; | |
286 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); | |
287 | TRACE_RET(chip, TRANSPORT_FAILED); | |
288 | } | |
289 | retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len); | |
290 | if (retval != STATUS_SUCCESS) { | |
291 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
292 | TRACE_RET(chip, TRANSPORT_FAILED); | |
293 | } | |
294 | sd_card->last_rsp_type = rsp_type; | |
295 | ||
296 | retval = sd_switch_clock(chip); | |
297 | if (retval != STATUS_SUCCESS) | |
298 | TRACE_RET(chip, TRANSPORT_FAILED); | |
1dac4186 | 299 | /* Set H/W SD/MMC Bus Width */ |
300 | rts51x_write_register(chip, SD_CFG1, 0x03, SD_BUS_WIDTH_4); | |
1dac4186 | 301 | |
302 | if (standby) { | |
303 | retval = sd_select_card(chip, 0); | |
304 | if (retval != STATUS_SUCCESS) | |
305 | TRACE_GOTO(chip, SD_Execute_Cmd_Failed); | |
306 | } | |
307 | ||
308 | if (acmd) { | |
309 | retval = | |
310 | ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, | |
311 | SD_RSP_TYPE_R1, NULL, 0, 0); | |
312 | if (retval != STATUS_SUCCESS) | |
313 | TRACE_GOTO(chip, SD_Execute_Cmd_Failed); | |
314 | } | |
315 | ||
316 | retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, | |
317 | sd_card->rsp, rsp_len, 0); | |
318 | if (retval != STATUS_SUCCESS) | |
319 | TRACE_GOTO(chip, SD_Execute_Cmd_Failed); | |
320 | ||
321 | if (standby) { | |
322 | retval = sd_select_card(chip, 1); | |
323 | if (retval != STATUS_SUCCESS) | |
324 | TRACE_GOTO(chip, SD_Execute_Cmd_Failed); | |
325 | } | |
1dac4186 | 326 | |
327 | return TRANSPORT_GOOD; | |
328 | ||
329 | SD_Execute_Cmd_Failed: | |
330 | sd_card->pre_cmd_err = 1; | |
331 | set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); | |
332 | release_sd_card(chip); | |
333 | do_reset_sd_card(chip); | |
334 | if (!(chip->card_ready & SD_CARD)) | |
335 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); | |
336 | ||
337 | TRACE_RET(chip, TRANSPORT_FAILED); | |
338 | } | |
339 | ||
340 | int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun, | |
341 | u8 cmd_idx, u8 cmd12, u8 standby, | |
342 | u8 acmd, u8 rsp_code, u32 arg, u32 data_len, | |
343 | void *data_buf, unsigned int buf_len, int use_sg) | |
344 | { | |
345 | struct sd_info *sd_card = &(chip->sd_card); | |
346 | int retval, rsp_len, i; | |
347 | int cmd13_checkbit = 0, read_err = 0; | |
348 | u8 rsp_type, bus_width; | |
349 | ||
350 | if (sd_card->pre_cmd_err) { | |
351 | sd_card->pre_cmd_err = 0; | |
352 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); | |
353 | TRACE_RET(chip, TRANSPORT_FAILED); | |
354 | } | |
355 | ||
356 | retval = sd_switch_clock(chip); | |
357 | if (retval != STATUS_SUCCESS) | |
358 | TRACE_RET(chip, STATUS_FAIL); | |
359 | retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len); | |
360 | if (retval != STATUS_SUCCESS) { | |
361 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
362 | TRACE_RET(chip, TRANSPORT_FAILED); | |
363 | } | |
364 | sd_card->last_rsp_type = rsp_type; | |
365 | ||
366 | retval = sd_switch_clock(chip); | |
367 | if (retval != STATUS_SUCCESS) | |
368 | TRACE_RET(chip, TRANSPORT_FAILED); | |
1dac4186 | 369 | bus_width = SD_BUS_WIDTH_4; |
1dac4186 | 370 | |
371 | if (data_len < 512) { | |
372 | retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, | |
373 | SD_RSP_TYPE_R1, NULL, 0, 0); | |
374 | if (retval != STATUS_SUCCESS) | |
375 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
376 | } | |
377 | ||
378 | if (standby) { | |
379 | retval = sd_select_card(chip, 0); | |
380 | if (retval != STATUS_SUCCESS) | |
381 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
382 | } | |
383 | ||
384 | if (acmd) { | |
385 | retval = | |
386 | ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, | |
387 | SD_RSP_TYPE_R1, NULL, 0, 0); | |
388 | if (retval != STATUS_SUCCESS) | |
389 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
390 | } | |
391 | ||
392 | if (data_len <= 512) { | |
393 | int min_len; | |
394 | u8 *buf; | |
395 | u16 byte_cnt, blk_cnt; | |
396 | u8 cmd[5]; | |
397 | unsigned int offset = 0; | |
398 | void *sg = NULL; | |
399 | ||
400 | byte_cnt = (u16) (data_len & 0x3FF); | |
401 | blk_cnt = 1; | |
402 | ||
403 | cmd[0] = 0x40 | cmd_idx; | |
404 | cmd[1] = (u8) (arg >> 24); | |
405 | cmd[2] = (u8) (arg >> 16); | |
406 | cmd[3] = (u8) (arg >> 8); | |
407 | cmd[4] = (u8) arg; | |
408 | ||
409 | buf = kmalloc(data_len, GFP_KERNEL); | |
410 | if (buf == NULL) | |
411 | TRACE_RET(chip, TRANSPORT_ERROR); | |
412 | ||
413 | retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt, | |
414 | blk_cnt, bus_width, buf, data_len, 2000); | |
415 | if (retval != STATUS_SUCCESS) { | |
416 | read_err = 1; | |
417 | kfree(buf); | |
418 | rts51x_write_register(chip, CARD_STOP, | |
419 | SD_STOP | SD_CLR_ERR, | |
420 | SD_STOP | SD_CLR_ERR); | |
421 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
422 | } | |
423 | ||
424 | min_len = min(data_len, buf_len); | |
425 | if (use_sg) | |
426 | rts51x_access_sglist(buf, min_len, (void *)data_buf, | |
427 | &sg, &offset, TO_XFER_BUF); | |
428 | else | |
429 | memcpy(data_buf, buf, min_len); | |
430 | ||
431 | kfree(buf); | |
432 | } else if (!(data_len & 0x1FF)) { | |
433 | rts51x_init_cmd(chip); | |
434 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); | |
435 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); | |
436 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, | |
437 | 0xFF, (u8) (data_len >> 17)); | |
438 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, | |
439 | 0xFF, (u8) ((data_len & 0x0001FE00) >> 9)); | |
440 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD0, 0xFF, | |
441 | 0x40 | cmd_idx); | |
442 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD1, 0xFF, | |
443 | (u8) (arg >> 24)); | |
444 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD2, 0xFF, | |
445 | (u8) (arg >> 16)); | |
446 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD3, 0xFF, | |
447 | (u8) (arg >> 8)); | |
448 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8) arg); | |
449 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x03, bus_width); | |
450 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); | |
451 | trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512); | |
452 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, | |
453 | SD_TM_AUTO_READ_2 | SD_TRANSFER_START); | |
454 | rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, | |
455 | SD_TRANSFER_END, SD_TRANSFER_END); | |
456 | retval = rts51x_send_cmd(chip, MODE_CDIR, 100); | |
457 | if (retval != STATUS_SUCCESS) { | |
458 | read_err = 1; | |
459 | rts51x_ep0_write_register(chip, CARD_STOP, | |
460 | SD_STOP | SD_CLR_ERR, | |
461 | SD_STOP | SD_CLR_ERR); | |
462 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
463 | } | |
464 | ||
465 | retval = | |
466 | rts51x_transfer_data_rcc(chip, RCV_BULK_PIPE(chip), | |
467 | data_buf, buf_len, use_sg, NULL, | |
468 | 10000, STAGE_DI); | |
469 | if (retval != STATUS_SUCCESS) { | |
470 | read_err = 1; | |
471 | rts51x_ep0_write_register(chip, CARD_STOP, | |
472 | SD_STOP | SD_CLR_ERR, | |
473 | SD_STOP | SD_CLR_ERR); | |
474 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
475 | } | |
476 | retval = rts51x_get_rsp(chip, 1, 500); | |
477 | if (CHECK_SD_TRANS_FAIL(chip, retval)) { | |
478 | read_err = 1; | |
479 | rts51x_ep0_write_register(chip, CARD_STOP, | |
480 | SD_STOP | SD_CLR_ERR, | |
481 | SD_STOP | SD_CLR_ERR); | |
482 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
483 | } | |
484 | } else { | |
485 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
486 | } | |
487 | ||
488 | retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type); | |
489 | if (retval != STATUS_SUCCESS) | |
490 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
491 | ||
492 | if (standby) { | |
493 | retval = sd_select_card(chip, 1); | |
494 | if (retval != STATUS_SUCCESS) | |
495 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
496 | } | |
497 | ||
498 | if (cmd12) { | |
499 | retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, | |
500 | 0, SD_RSP_TYPE_R1b, NULL, 0, | |
501 | 0); | |
502 | if (retval != STATUS_SUCCESS) | |
503 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
504 | } | |
505 | ||
506 | if (data_len < 512) { | |
507 | retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, | |
508 | SD_RSP_TYPE_R1, NULL, 0, 0); | |
509 | if (retval != STATUS_SUCCESS) | |
510 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
511 | ||
512 | rts51x_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); | |
513 | rts51x_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); | |
514 | } | |
515 | ||
516 | if (standby || cmd12) | |
517 | cmd13_checkbit = 1; | |
518 | ||
519 | for (i = 0; i < 3; i++) { | |
520 | retval = | |
521 | ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, | |
522 | SD_RSP_TYPE_R1, NULL, 0, | |
523 | cmd13_checkbit); | |
524 | if (retval == STATUS_SUCCESS) | |
525 | break; | |
526 | } | |
527 | if (retval != STATUS_SUCCESS) | |
528 | TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); | |
529 | ||
530 | return TRANSPORT_GOOD; | |
531 | ||
532 | SD_Execute_Read_Cmd_Failed: | |
533 | sd_card->pre_cmd_err = 1; | |
534 | set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); | |
535 | if (read_err) | |
536 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); | |
537 | release_sd_card(chip); | |
538 | do_reset_sd_card(chip); | |
539 | if (!(chip->card_ready & SD_CARD)) | |
540 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); | |
541 | ||
542 | TRACE_RET(chip, TRANSPORT_FAILED); | |
543 | } | |
544 | ||
545 | int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun, | |
546 | u8 cmd_idx, u8 cmd12, u8 standby, u8 acmd, | |
547 | u8 rsp_code, u32 arg, u32 data_len, | |
548 | void *data_buf, unsigned int buf_len, int use_sg) | |
549 | { | |
550 | struct sd_info *sd_card = &(chip->sd_card); | |
551 | int retval, rsp_len; | |
552 | int cmd13_checkbit = 0, write_err = 0; | |
553 | u8 rsp_type; | |
554 | u32 i; | |
1dac4186 | 555 | |
556 | if (sd_card->pre_cmd_err) { | |
557 | sd_card->pre_cmd_err = 0; | |
558 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); | |
559 | TRACE_RET(chip, TRANSPORT_FAILED); | |
560 | } | |
561 | ||
562 | retval = sd_switch_clock(chip); | |
563 | if (retval != STATUS_SUCCESS) | |
564 | TRACE_RET(chip, STATUS_FAIL); | |
1dac4186 | 565 | |
566 | retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len); | |
567 | if (retval != STATUS_SUCCESS) { | |
568 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
569 | TRACE_RET(chip, TRANSPORT_FAILED); | |
570 | } | |
571 | sd_card->last_rsp_type = rsp_type; | |
572 | ||
573 | retval = sd_switch_clock(chip); | |
574 | if (retval != STATUS_SUCCESS) | |
575 | TRACE_RET(chip, TRANSPORT_FAILED); | |
1dac4186 | 576 | rts51x_write_register(chip, SD_CFG1, 0x03, SD_BUS_WIDTH_4); |
1dac4186 | 577 | |
578 | if (data_len < 512) { | |
579 | retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, | |
580 | SD_RSP_TYPE_R1, NULL, 0, 0); | |
581 | if (retval != STATUS_SUCCESS) | |
582 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
583 | } | |
584 | ||
585 | if (standby) { | |
586 | retval = sd_select_card(chip, 0); | |
587 | if (retval != STATUS_SUCCESS) | |
588 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
589 | } | |
590 | ||
591 | if (acmd) { | |
592 | retval = | |
593 | ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, | |
594 | SD_RSP_TYPE_R1, NULL, 0, 0); | |
595 | if (retval != STATUS_SUCCESS) | |
596 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
597 | } | |
598 | ||
599 | retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, | |
600 | sd_card->rsp, rsp_len, 0); | |
601 | if (retval != STATUS_SUCCESS) | |
602 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
603 | ||
604 | if (data_len <= 512) { | |
605 | u8 *buf; | |
606 | unsigned int offset = 0; | |
607 | void *sg = NULL; | |
608 | ||
609 | buf = kmalloc(data_len, GFP_KERNEL); | |
610 | if (buf == NULL) | |
611 | TRACE_RET(chip, TRANSPORT_ERROR); | |
612 | ||
613 | if (use_sg) | |
614 | rts51x_access_sglist(buf, data_len, (void *)data_buf, | |
615 | &sg, &offset, FROM_XFER_BUF); | |
616 | else | |
617 | memcpy(buf, data_buf, data_len); | |
618 | ||
1dac4186 | 619 | |
620 | if (data_len > 256) { | |
621 | rts51x_init_cmd(chip); | |
622 | for (i = 0; i < 256; i++) { | |
623 | rts51x_add_cmd(chip, WRITE_REG_CMD, | |
624 | (u16) (PPBUF_BASE2 + i), 0xFF, | |
625 | buf[i]); | |
626 | } | |
627 | retval = rts51x_send_cmd(chip, MODE_C, 250); | |
628 | if (retval != STATUS_SUCCESS) { | |
629 | kfree(buf); | |
630 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
631 | } | |
632 | ||
633 | rts51x_init_cmd(chip); | |
634 | for (i = 256; i < data_len; i++) { | |
635 | rts51x_add_cmd(chip, WRITE_REG_CMD, | |
636 | (u16) (PPBUF_BASE2 + i), 0xFF, | |
637 | buf[i]); | |
638 | } | |
639 | retval = rts51x_send_cmd(chip, MODE_C, 250); | |
640 | if (retval != STATUS_SUCCESS) { | |
641 | kfree(buf); | |
642 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
643 | } | |
644 | } else { | |
645 | rts51x_init_cmd(chip); | |
646 | for (i = 0; i < data_len; i++) { | |
647 | rts51x_add_cmd(chip, WRITE_REG_CMD, | |
648 | (u16) (PPBUF_BASE2 + i), 0xFF, | |
649 | buf[i]); | |
650 | } | |
651 | retval = rts51x_send_cmd(chip, MODE_C, 250); | |
652 | if (retval != STATUS_SUCCESS) { | |
653 | kfree(buf); | |
654 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
655 | } | |
656 | } | |
657 | ||
658 | kfree(buf); | |
659 | ||
660 | rts51x_init_cmd(chip); | |
661 | ||
662 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, | |
663 | (u8) ((data_len >> 8) & 0x03)); | |
664 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, | |
665 | (u8) data_len); | |
666 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0x00); | |
667 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 0x01); | |
668 | rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, | |
669 | PINGPONG_BUFFER); | |
670 | ||
671 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, | |
672 | SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); | |
673 | rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, | |
674 | SD_TRANSFER_END, SD_TRANSFER_END); | |
675 | ||
676 | retval = rts51x_send_cmd(chip, MODE_CR, 100); | |
677 | if (retval != STATUS_SUCCESS) | |
678 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
679 | ||
680 | retval = rts51x_get_rsp(chip, 1, 250); | |
681 | if (CHECK_SD_TRANS_FAIL(chip, retval)) | |
682 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
683 | } else if (!(data_len & 0x1FF)) { | |
684 | rts51x_init_cmd(chip); | |
685 | ||
686 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); | |
687 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); | |
688 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, | |
689 | 0xFF, (u8) (data_len >> 17)); | |
690 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, | |
691 | 0xFF, (u8) ((data_len & 0x0001FE00) >> 9)); | |
692 | ||
693 | trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512); | |
694 | ||
695 | rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, | |
696 | SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); | |
697 | rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, | |
698 | SD_TRANSFER_END, SD_TRANSFER_END); | |
699 | ||
700 | retval = rts51x_send_cmd(chip, MODE_CDOR, 100); | |
701 | if (retval != STATUS_SUCCESS) | |
702 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
703 | ||
704 | retval = | |
705 | rts51x_transfer_data_rcc(chip, SND_BULK_PIPE(chip), | |
706 | data_buf, buf_len, use_sg, NULL, | |
707 | 10000, STAGE_DO); | |
708 | if (retval != STATUS_SUCCESS) | |
709 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
710 | ||
711 | retval = rts51x_get_rsp(chip, 1, 10000); | |
712 | if (CHECK_SD_TRANS_FAIL(chip, retval)) | |
713 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
714 | ||
715 | } else { | |
716 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
717 | } | |
718 | ||
719 | if (retval < 0) { | |
720 | write_err = 1; | |
721 | rts51x_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, | |
722 | SD_STOP | SD_CLR_ERR); | |
723 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
724 | } | |
1dac4186 | 725 | |
726 | if (standby) { | |
727 | retval = sd_select_card(chip, 1); | |
728 | if (retval != STATUS_SUCCESS) | |
729 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
730 | } | |
731 | ||
732 | if (cmd12) { | |
733 | retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, | |
734 | 0, SD_RSP_TYPE_R1b, NULL, 0, | |
735 | 0); | |
736 | if (retval != STATUS_SUCCESS) | |
737 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
738 | } | |
739 | ||
740 | if (data_len < 512) { | |
741 | retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, | |
742 | SD_RSP_TYPE_R1, NULL, 0, 0); | |
743 | if (retval != STATUS_SUCCESS) | |
744 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
745 | ||
746 | rts51x_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); | |
747 | rts51x_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); | |
748 | } | |
749 | ||
750 | if (cmd12 || standby) { | |
751 | /* There is CMD7 or CMD12 sent before CMD13 */ | |
752 | cmd13_checkbit = 1; | |
753 | } | |
754 | ||
755 | for (i = 0; i < 3; i++) { | |
756 | retval = | |
757 | ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, | |
758 | SD_RSP_TYPE_R1, NULL, 0, | |
759 | cmd13_checkbit); | |
760 | if (retval == STATUS_SUCCESS) | |
761 | break; | |
762 | } | |
763 | if (retval != STATUS_SUCCESS) | |
764 | TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); | |
1dac4186 | 765 | |
766 | return TRANSPORT_GOOD; | |
767 | ||
768 | SD_Execute_Write_Cmd_Failed: | |
769 | sd_card->pre_cmd_err = 1; | |
770 | set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); | |
771 | if (write_err) | |
772 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); | |
773 | release_sd_card(chip); | |
774 | do_reset_sd_card(chip); | |
775 | if (!(chip->card_ready & SD_CARD)) | |
776 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); | |
777 | ||
778 | TRACE_RET(chip, TRANSPORT_FAILED); | |
779 | } | |
780 | ||
781 | int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip) | |
782 | { | |
783 | struct sd_info *sd_card = &(chip->sd_card); | |
784 | unsigned int lun = SCSI_LUN(srb); | |
785 | int len; | |
786 | u8 buf[18] = { | |
787 | 0x00, | |
788 | 0x00, | |
789 | 0x00, | |
790 | 0x0E, | |
791 | 0x00, /* Version Number */ | |
792 | 0x00, /* WP | Media Type */ | |
793 | 0x00, /* RCA (Low byte) */ | |
794 | 0x00, /* RCA (High byte) */ | |
795 | 0x53, /* 'S' */ | |
796 | 0x44, /* 'D' */ | |
797 | 0x20, /* ' ' */ | |
798 | 0x43, /* 'C' */ | |
799 | 0x61, /* 'a' */ | |
800 | 0x72, /* 'r' */ | |
801 | 0x64, /* 'd' */ | |
802 | 0x00, /* Max LUN Number */ | |
803 | 0x00, | |
804 | 0x00, | |
805 | }; | |
806 | ||
807 | sd_card->pre_cmd_err = 0; | |
808 | ||
809 | if (!(CHK_BIT(chip->lun_mc, lun))) { | |
810 | SET_BIT(chip->lun_mc, lun); | |
811 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); | |
812 | TRACE_RET(chip, TRANSPORT_FAILED); | |
813 | } | |
814 | ||
815 | if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) | |
816 | || (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5]) | |
817 | || (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7]) | |
818 | || (0x64 != srb->cmnd[8])) { | |
819 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
820 | TRACE_RET(chip, TRANSPORT_FAILED); | |
821 | } | |
822 | ||
823 | switch (srb->cmnd[1] & 0x0F) { | |
824 | case 0: | |
825 | sd_card->sd_pass_thru_en = 0; | |
826 | break; | |
827 | ||
828 | case 1: | |
829 | sd_card->sd_pass_thru_en = 1; | |
830 | break; | |
831 | ||
832 | default: | |
833 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
834 | TRACE_RET(chip, TRANSPORT_FAILED); | |
835 | } | |
836 | ||
837 | /* 0x01:SD Memory Card; 0x02:Other Media; 0x03:Illegal Media; */ | |
838 | buf[5] = (1 == CHK_SD(sd_card)) ? 0x01 : 0x02; | |
839 | if (chip->card_wp & SD_CARD) | |
840 | buf[5] |= 0x80; | |
841 | ||
842 | buf[6] = (u8) (sd_card->sd_addr >> 16); | |
843 | buf[7] = (u8) (sd_card->sd_addr >> 24); | |
844 | ||
845 | buf[15] = chip->max_lun; | |
846 | ||
dee0dc0d | 847 | len = min_t(unsigned, 18, scsi_bufflen(srb)); |
1dac4186 | 848 | rts51x_set_xfer_buf(buf, len, srb); |
849 | ||
850 | return TRANSPORT_GOOD; | |
851 | } | |
852 | ||
853 | int sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip) | |
854 | { | |
855 | struct sd_info *sd_card = &(chip->sd_card); | |
856 | unsigned int lun = SCSI_LUN(srb); | |
857 | int retval; | |
858 | u8 cmd_idx, rsp_code; | |
859 | u8 standby = 0, acmd = 0; | |
860 | u32 arg; | |
861 | ||
862 | if (!sd_card->sd_pass_thru_en) { | |
863 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
864 | TRACE_RET(chip, TRANSPORT_FAILED); | |
865 | } | |
866 | ||
867 | cmd_idx = srb->cmnd[2] & 0x3F; | |
868 | if (srb->cmnd[1] & 0x02) | |
869 | standby = 1; | |
870 | if (srb->cmnd[1] & 0x01) | |
871 | acmd = 1; | |
872 | ||
873 | arg = ((u32) srb->cmnd[3] << 24) | ((u32) srb->cmnd[4] << 16) | | |
874 | ((u32) srb->cmnd[5] << 8) | srb->cmnd[6]; | |
875 | ||
876 | rsp_code = srb->cmnd[10]; | |
877 | ||
878 | retval = | |
879 | ext_sd_execute_no_data(chip, lun, cmd_idx, standby, acmd, rsp_code, | |
880 | arg); | |
881 | scsi_set_resid(srb, 0); | |
882 | return retval; | |
883 | } | |
884 | ||
885 | int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip) | |
886 | { | |
887 | struct sd_info *sd_card = &(chip->sd_card); | |
888 | int retval; | |
889 | unsigned int lun = SCSI_LUN(srb); | |
890 | u8 cmd_idx, rsp_code, send_cmd12 = 0, standby = 0, acmd = 0; | |
891 | u32 arg, data_len; | |
892 | ||
893 | if (!sd_card->sd_pass_thru_en) { | |
894 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
895 | TRACE_RET(chip, TRANSPORT_FAILED); | |
896 | } | |
897 | ||
898 | cmd_idx = srb->cmnd[2] & 0x3F; | |
899 | if (srb->cmnd[1] & 0x04) | |
900 | send_cmd12 = 1; | |
901 | if (srb->cmnd[1] & 0x02) | |
902 | standby = 1; | |
903 | if (srb->cmnd[1] & 0x01) | |
904 | acmd = 1; | |
905 | ||
906 | arg = ((u32) srb->cmnd[3] << 24) | ((u32) srb->cmnd[4] << 16) | | |
907 | ((u32) srb->cmnd[5] << 8) | srb->cmnd[6]; | |
908 | ||
909 | data_len = | |
910 | ((u32) srb->cmnd[7] << 16) | ((u32) srb->cmnd[8] << 8) | | |
911 | srb->cmnd[9]; | |
912 | rsp_code = srb->cmnd[10]; | |
913 | ||
914 | retval = | |
915 | ext_sd_execute_read_data(chip, lun, cmd_idx, send_cmd12, standby, | |
916 | acmd, rsp_code, arg, data_len, | |
917 | scsi_sglist(srb), scsi_bufflen(srb), | |
918 | scsi_sg_count(srb)); | |
919 | scsi_set_resid(srb, 0); | |
920 | return retval; | |
921 | } | |
922 | ||
923 | int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip) | |
924 | { | |
925 | struct sd_info *sd_card = &(chip->sd_card); | |
926 | int retval; | |
927 | unsigned int lun = SCSI_LUN(srb); | |
928 | u8 cmd_idx, rsp_code, send_cmd12 = 0, standby = 0, acmd = 0; | |
929 | u32 data_len, arg; | |
930 | ||
931 | if (!sd_card->sd_pass_thru_en) { | |
932 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
933 | TRACE_RET(chip, TRANSPORT_FAILED); | |
934 | } | |
935 | ||
936 | cmd_idx = srb->cmnd[2] & 0x3F; | |
937 | if (srb->cmnd[1] & 0x04) | |
938 | send_cmd12 = 1; | |
939 | if (srb->cmnd[1] & 0x02) | |
940 | standby = 1; | |
941 | if (srb->cmnd[1] & 0x01) | |
942 | acmd = 1; | |
943 | ||
944 | data_len = | |
945 | ((u32) srb->cmnd[7] << 16) | ((u32) srb->cmnd[8] << 8) | | |
946 | srb->cmnd[9]; | |
947 | arg = | |
948 | ((u32) srb->cmnd[3] << 24) | ((u32) srb->cmnd[4] << 16) | | |
949 | ((u32) srb->cmnd[5] << 8) | srb->cmnd[6]; | |
950 | rsp_code = srb->cmnd[10]; | |
951 | ||
952 | retval = | |
953 | ext_sd_execute_write_data(chip, lun, cmd_idx, send_cmd12, standby, | |
954 | acmd, rsp_code, arg, data_len, | |
955 | scsi_sglist(srb), scsi_bufflen(srb), | |
956 | scsi_sg_count(srb)); | |
957 | scsi_set_resid(srb, 0); | |
958 | return retval; | |
959 | } | |
960 | ||
961 | int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip) | |
962 | { | |
963 | struct sd_info *sd_card = &(chip->sd_card); | |
964 | unsigned int lun = SCSI_LUN(srb); | |
965 | int count; | |
966 | u16 data_len; | |
967 | ||
968 | if (!sd_card->sd_pass_thru_en) { | |
969 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
970 | TRACE_RET(chip, TRANSPORT_FAILED); | |
971 | } | |
972 | ||
973 | if (sd_card->pre_cmd_err) { | |
974 | sd_card->pre_cmd_err = 0; | |
975 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); | |
976 | TRACE_RET(chip, TRANSPORT_FAILED); | |
977 | } | |
978 | ||
979 | data_len = ((u16) srb->cmnd[7] << 8) | srb->cmnd[8]; | |
980 | ||
981 | if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) { | |
982 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
983 | TRACE_RET(chip, TRANSPORT_FAILED); | |
984 | } else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) { | |
985 | count = (data_len < 17) ? data_len : 17; | |
986 | } else { | |
987 | count = (data_len < 6) ? data_len : 6; | |
988 | } | |
989 | rts51x_set_xfer_buf(sd_card->rsp, count, srb); | |
990 | ||
991 | RTS51X_DEBUGP("Response length: %d\n", data_len); | |
992 | RTS51X_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n", | |
993 | sd_card->rsp[0], sd_card->rsp[1], sd_card->rsp[2], | |
994 | sd_card->rsp[3]); | |
995 | ||
996 | scsi_set_resid(srb, 0); | |
997 | return TRANSPORT_GOOD; | |
998 | } | |
999 | ||
1000 | int sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip) | |
1001 | { | |
1002 | struct sd_info *sd_card = &(chip->sd_card); | |
1003 | unsigned int lun = SCSI_LUN(srb); | |
1004 | int retval; | |
1005 | ||
1006 | if (!sd_card->sd_pass_thru_en) { | |
1007 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
1008 | TRACE_RET(chip, TRANSPORT_FAILED); | |
1009 | } | |
1010 | ||
1011 | if (sd_card->pre_cmd_err) { | |
1012 | sd_card->pre_cmd_err = 0; | |
1013 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); | |
1014 | TRACE_RET(chip, TRANSPORT_FAILED); | |
1015 | } | |
1016 | ||
1017 | if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) | |
1018 | || (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5]) | |
1019 | || (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7]) | |
1020 | || (0x64 != srb->cmnd[8])) { | |
1021 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
1022 | TRACE_RET(chip, TRANSPORT_FAILED); | |
1023 | } | |
1024 | ||
1025 | switch (srb->cmnd[1] & 0x0F) { | |
1026 | case 0: | |
1027 | /* SD Card Power Off -> ON and Initialization */ | |
1dac4186 | 1028 | retval = reset_sd_card(chip); |
1029 | if (retval != STATUS_SUCCESS) { | |
1dac4186 | 1030 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); |
1031 | sd_card->pre_cmd_err = 1; | |
1032 | TRACE_RET(chip, TRANSPORT_FAILED); | |
1033 | } | |
1dac4186 | 1034 | break; |
1035 | ||
1036 | case 1: | |
1037 | /* reset CMD(CMD0) and Initialization | |
1038 | * (without SD Card Power Off -> ON) */ | |
2ff4ff54 | 1039 | retval = reset_sd(chip); |
1dac4186 | 1040 | if (retval != STATUS_SUCCESS) { |
1041 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); | |
1042 | sd_card->pre_cmd_err = 1; | |
1043 | TRACE_RET(chip, TRANSPORT_FAILED); | |
1044 | } | |
1045 | break; | |
1046 | ||
1047 | default: | |
1048 | set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); | |
1049 | TRACE_RET(chip, TRANSPORT_FAILED); | |
1050 | } | |
1051 | ||
1052 | scsi_set_resid(srb, 0); | |
1053 | return TRANSPORT_GOOD; | |
1054 | } | |
1055 | #endif |