]>
Commit | Line | Data |
---|---|---|
41e568d1 | 1 | /* |
2 | * | |
3 | * This program is free software; you can redistribute it and/or modify it | |
4 | * under the terms of the GNU General Public License as published by the | |
5 | * Free Software Foundation; either version 2, or (at your option) any | |
6 | * later version. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, but | |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | * General Public License for more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License along | |
14 | * with this program; if not, write to the Free Software Foundation, Inc., | |
15 | * 675 Mass Ave, Cambridge, MA 02139, USA. | |
16 | */ | |
17 | #include <linux/jiffies.h> | |
18 | #include <linux/errno.h> | |
19 | #include <linux/module.h> | |
20 | #include <linux/slab.h> | |
21 | ||
22 | #include <scsi/scsi.h> | |
23 | #include <scsi/scsi_cmnd.h> | |
24 | ||
25 | #include <linux/firmware.h> | |
26 | ||
27 | #include "usb.h" | |
28 | #include "transport.h" | |
29 | #include "protocol.h" | |
30 | #include "debug.h" | |
31 | ||
32 | MODULE_DESCRIPTION("Driver for ENE UB6250 reader"); | |
33 | MODULE_LICENSE("GPL"); | |
34 | ||
35 | ||
36 | /* | |
37 | * The table of devices | |
38 | */ | |
39 | #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ | |
40 | vendorName, productName, useProtocol, useTransport, \ | |
41 | initFunction, flags) \ | |
42 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ | |
43 | .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } | |
44 | ||
45 | struct usb_device_id ene_ub6250_usb_ids[] = { | |
46 | # include "unusual_ene_ub6250.h" | |
47 | { } /* Terminating entry */ | |
48 | }; | |
49 | MODULE_DEVICE_TABLE(usb, ene_ub6250_usb_ids); | |
50 | ||
51 | #undef UNUSUAL_DEV | |
52 | ||
53 | /* | |
54 | * The flags table | |
55 | */ | |
56 | #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ | |
57 | vendor_name, product_name, use_protocol, use_transport, \ | |
58 | init_function, Flags) \ | |
59 | { \ | |
60 | .vendorName = vendor_name, \ | |
61 | .productName = product_name, \ | |
62 | .useProtocol = use_protocol, \ | |
63 | .useTransport = use_transport, \ | |
64 | .initFunction = init_function, \ | |
65 | } | |
66 | ||
67 | static struct us_unusual_dev ene_ub6250_unusual_dev_list[] = { | |
68 | # include "unusual_ene_ub6250.h" | |
69 | { } /* Terminating entry */ | |
70 | }; | |
71 | ||
72 | #undef UNUSUAL_DEV | |
73 | ||
74 | ||
75 | ||
76 | /* ENE bin code len */ | |
77 | #define ENE_BIN_CODE_LEN 0x800 | |
78 | /* EnE HW Register */ | |
79 | #define REG_CARD_STATUS 0xFF83 | |
80 | #define REG_HW_TRAP1 0xFF89 | |
81 | ||
82 | /* SRB Status */ | |
83 | #define SS_SUCCESS 0x00 /* No Sense */ | |
84 | #define SS_NOT_READY 0x02 | |
85 | #define SS_MEDIUM_ERR 0x03 | |
86 | #define SS_HW_ERR 0x04 | |
87 | #define SS_ILLEGAL_REQUEST 0x05 | |
88 | #define SS_UNIT_ATTENTION 0x06 | |
89 | ||
90 | /* ENE Load FW Pattern */ | |
91 | #define SD_INIT1_PATTERN 1 | |
92 | #define SD_INIT2_PATTERN 2 | |
93 | #define SD_RW_PATTERN 3 | |
94 | #define MS_INIT_PATTERN 4 | |
95 | #define MSP_RW_PATTERN 5 | |
96 | #define MS_RW_PATTERN 6 | |
97 | #define SM_INIT_PATTERN 7 | |
98 | #define SM_RW_PATTERN 8 | |
99 | ||
100 | #define FDIR_WRITE 0 | |
101 | #define FDIR_READ 1 | |
102 | ||
103 | ||
104 | struct SD_STATUS { | |
105 | u8 Insert:1; | |
106 | u8 Ready:1; | |
107 | u8 MediaChange:1; | |
108 | u8 IsMMC:1; | |
109 | u8 HiCapacity:1; | |
110 | u8 HiSpeed:1; | |
111 | u8 WtP:1; | |
112 | u8 Reserved:1; | |
113 | }; | |
114 | ||
115 | struct MS_STATUS { | |
116 | u8 Insert:1; | |
117 | u8 Ready:1; | |
118 | u8 MediaChange:1; | |
119 | u8 IsMSPro:1; | |
120 | u8 IsMSPHG:1; | |
121 | u8 Reserved1:1; | |
122 | u8 WtP:1; | |
123 | u8 Reserved2:1; | |
124 | }; | |
125 | ||
126 | struct SM_STATUS { | |
127 | u8 Insert:1; | |
128 | u8 Ready:1; | |
129 | u8 MediaChange:1; | |
130 | u8 Reserved:3; | |
131 | u8 WtP:1; | |
132 | u8 IsMS:1; | |
133 | }; | |
134 | ||
135 | ||
136 | /* SD Block Length */ | |
137 | /* 2^9 = 512 Bytes, The HW maximum read/write data length */ | |
138 | #define SD_BLOCK_LEN 9 | |
139 | ||
140 | struct ene_ub6250_info { | |
141 | /* for 6250 code */ | |
142 | struct SD_STATUS SD_Status; | |
143 | struct MS_STATUS MS_Status; | |
144 | struct SM_STATUS SM_Status; | |
145 | ||
146 | /* ----- SD Control Data ---------------- */ | |
147 | /*SD_REGISTER SD_Regs; */ | |
148 | u16 SD_Block_Mult; | |
149 | u8 SD_READ_BL_LEN; | |
150 | u16 SD_C_SIZE; | |
151 | u8 SD_C_SIZE_MULT; | |
152 | ||
153 | /* SD/MMC New spec. */ | |
154 | u8 SD_SPEC_VER; | |
155 | u8 SD_CSD_VER; | |
156 | u8 SD20_HIGH_CAPACITY; | |
157 | u32 HC_C_SIZE; | |
158 | u8 MMC_SPEC_VER; | |
159 | u8 MMC_BusWidth; | |
160 | u8 MMC_HIGH_CAPACITY; | |
161 | ||
162 | /*----- MS Control Data ---------------- */ | |
163 | bool MS_SWWP; | |
164 | u32 MSP_TotalBlock; | |
165 | /*MS_LibControl MS_Lib;*/ | |
166 | bool MS_IsRWPage; | |
167 | u16 MS_Model; | |
168 | ||
169 | /*----- SM Control Data ---------------- */ | |
170 | u8 SM_DeviceID; | |
171 | u8 SM_CardID; | |
172 | ||
173 | unsigned char *testbuf; | |
174 | u8 BIN_FLAG; | |
175 | u32 bl_num; | |
176 | int SrbStatus; | |
177 | ||
178 | /*------Power Managerment ---------------*/ | |
179 | bool Power_IsResum; | |
180 | }; | |
181 | ||
182 | static int ene_sd_init(struct us_data *us); | |
183 | static int ene_load_bincode(struct us_data *us, unsigned char flag); | |
184 | ||
185 | static void ene_ub6250_info_destructor(void *extra) | |
186 | { | |
187 | if (!extra) | |
188 | return; | |
189 | } | |
190 | ||
191 | static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg) | |
192 | { | |
193 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
194 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | |
195 | ||
196 | int result; | |
197 | unsigned int residue; | |
198 | unsigned int cswlen = 0, partial = 0; | |
199 | unsigned int transfer_length = bcb->DataTransferLength; | |
200 | ||
201 | /* US_DEBUGP("transport --- ene_send_scsi_cmd\n"); */ | |
202 | /* send cmd to out endpoint */ | |
203 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | |
204 | bcb, US_BULK_CB_WRAP_LEN, NULL); | |
205 | if (result != USB_STOR_XFER_GOOD) { | |
206 | US_DEBUGP("send cmd to out endpoint fail ---\n"); | |
207 | return USB_STOR_TRANSPORT_ERROR; | |
208 | } | |
209 | ||
210 | if (buf) { | |
211 | unsigned int pipe = fDir; | |
212 | ||
213 | if (fDir == FDIR_READ) | |
214 | pipe = us->recv_bulk_pipe; | |
215 | else | |
216 | pipe = us->send_bulk_pipe; | |
217 | ||
218 | /* Bulk */ | |
219 | if (use_sg) { | |
220 | result = usb_stor_bulk_srb(us, pipe, us->srb); | |
221 | } else { | |
222 | result = usb_stor_bulk_transfer_sg(us, pipe, buf, | |
223 | transfer_length, 0, &partial); | |
224 | } | |
225 | if (result != USB_STOR_XFER_GOOD) { | |
226 | US_DEBUGP("data transfer fail ---\n"); | |
227 | return USB_STOR_TRANSPORT_ERROR; | |
228 | } | |
229 | } | |
230 | ||
231 | /* Get CSW for device status */ | |
232 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, | |
233 | US_BULK_CS_WRAP_LEN, &cswlen); | |
234 | ||
235 | if (result == USB_STOR_XFER_SHORT && cswlen == 0) { | |
236 | US_DEBUGP("Received 0-length CSW; retrying...\n"); | |
237 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | |
238 | bcs, US_BULK_CS_WRAP_LEN, &cswlen); | |
239 | } | |
240 | ||
241 | if (result == USB_STOR_XFER_STALLED) { | |
242 | /* get the status again */ | |
243 | US_DEBUGP("Attempting to get CSW (2nd try)...\n"); | |
244 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | |
245 | bcs, US_BULK_CS_WRAP_LEN, NULL); | |
246 | } | |
247 | ||
248 | if (result != USB_STOR_XFER_GOOD) | |
249 | return USB_STOR_TRANSPORT_ERROR; | |
250 | ||
251 | /* check bulk status */ | |
252 | residue = le32_to_cpu(bcs->Residue); | |
253 | ||
254 | /* try to compute the actual residue, based on how much data | |
255 | * was really transferred and what the device tells us */ | |
256 | if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) { | |
257 | residue = min(residue, transfer_length); | |
258 | if (us->srb != NULL) | |
259 | scsi_set_resid(us->srb, max(scsi_get_resid(us->srb), | |
260 | (int)residue)); | |
261 | } | |
262 | ||
263 | if (bcs->Status != US_BULK_STAT_OK) | |
264 | return USB_STOR_TRANSPORT_ERROR; | |
265 | ||
266 | return USB_STOR_TRANSPORT_GOOD; | |
267 | } | |
268 | ||
269 | static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb) | |
270 | { | |
271 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | |
272 | ||
273 | if (info->SD_Status.Insert && info->SD_Status.Ready) | |
274 | return USB_STOR_TRANSPORT_GOOD; | |
275 | else { | |
276 | ene_sd_init(us); | |
277 | return USB_STOR_TRANSPORT_GOOD; | |
278 | } | |
279 | ||
280 | return USB_STOR_TRANSPORT_GOOD; | |
281 | } | |
282 | ||
283 | static int sd_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb) | |
284 | { | |
285 | unsigned char data_ptr[36] = { | |
286 | 0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, | |
287 | 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, | |
288 | 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, | |
289 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30 }; | |
290 | ||
291 | usb_stor_set_xfer_buf(data_ptr, 36, srb); | |
292 | return USB_STOR_TRANSPORT_GOOD; | |
293 | } | |
294 | ||
295 | static int sd_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb) | |
296 | { | |
297 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | |
298 | unsigned char mediaNoWP[12] = { | |
299 | 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, | |
300 | 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 }; | |
301 | unsigned char mediaWP[12] = { | |
302 | 0x0b, 0x00, 0x80, 0x08, 0x00, 0x00, | |
303 | 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 }; | |
304 | ||
305 | if (info->SD_Status.WtP) | |
306 | usb_stor_set_xfer_buf(mediaWP, 12, srb); | |
307 | else | |
308 | usb_stor_set_xfer_buf(mediaNoWP, 12, srb); | |
309 | ||
310 | ||
311 | return USB_STOR_TRANSPORT_GOOD; | |
312 | } | |
313 | ||
314 | static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb) | |
315 | { | |
316 | u32 bl_num; | |
317 | u16 bl_len; | |
318 | unsigned int offset = 0; | |
319 | unsigned char buf[8]; | |
320 | struct scatterlist *sg = NULL; | |
321 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | |
322 | ||
323 | US_DEBUGP("sd_scsi_read_capacity\n"); | |
324 | if (info->SD_Status.HiCapacity) { | |
325 | bl_len = 0x200; | |
326 | if (info->SD_Status.IsMMC) | |
327 | bl_num = info->HC_C_SIZE-1; | |
328 | else | |
329 | bl_num = (info->HC_C_SIZE + 1) * 1024 - 1; | |
330 | } else { | |
331 | bl_len = 1<<(info->SD_READ_BL_LEN); | |
332 | bl_num = info->SD_Block_Mult * (info->SD_C_SIZE + 1) | |
333 | * (1 << (info->SD_C_SIZE_MULT + 2)) - 1; | |
334 | } | |
335 | info->bl_num = bl_num; | |
336 | US_DEBUGP("bl_len = %x\n", bl_len); | |
337 | US_DEBUGP("bl_num = %x\n", bl_num); | |
338 | ||
339 | /*srb->request_bufflen = 8; */ | |
340 | buf[0] = (bl_num >> 24) & 0xff; | |
341 | buf[1] = (bl_num >> 16) & 0xff; | |
342 | buf[2] = (bl_num >> 8) & 0xff; | |
343 | buf[3] = (bl_num >> 0) & 0xff; | |
344 | buf[4] = (bl_len >> 24) & 0xff; | |
345 | buf[5] = (bl_len >> 16) & 0xff; | |
346 | buf[6] = (bl_len >> 8) & 0xff; | |
347 | buf[7] = (bl_len >> 0) & 0xff; | |
348 | ||
349 | usb_stor_access_xfer_buf(buf, 8, srb, &sg, &offset, TO_XFER_BUF); | |
350 | ||
351 | return USB_STOR_TRANSPORT_GOOD; | |
352 | } | |
353 | ||
354 | static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb) | |
355 | { | |
356 | int result; | |
357 | unsigned char *cdb = srb->cmnd; | |
358 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
359 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | |
360 | ||
361 | u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) | | |
362 | ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff); | |
363 | u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff); | |
364 | u32 bnByte = bn * 0x200; | |
365 | u32 blenByte = blen * 0x200; | |
366 | ||
367 | if (bn > info->bl_num) | |
368 | return USB_STOR_TRANSPORT_ERROR; | |
369 | ||
370 | result = ene_load_bincode(us, SD_RW_PATTERN); | |
371 | if (result != USB_STOR_XFER_GOOD) { | |
372 | US_DEBUGP("Load SD RW pattern Fail !!\n"); | |
373 | return USB_STOR_TRANSPORT_ERROR; | |
374 | } | |
375 | ||
376 | if (info->SD_Status.HiCapacity) | |
377 | bnByte = bn; | |
378 | ||
379 | /* set up the command wrapper */ | |
380 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); | |
381 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | |
382 | bcb->DataTransferLength = blenByte; | |
383 | bcb->Flags = 0x80; | |
384 | bcb->CDB[0] = 0xF1; | |
385 | bcb->CDB[5] = (unsigned char)(bnByte); | |
386 | bcb->CDB[4] = (unsigned char)(bnByte>>8); | |
387 | bcb->CDB[3] = (unsigned char)(bnByte>>16); | |
388 | bcb->CDB[2] = (unsigned char)(bnByte>>24); | |
389 | ||
390 | result = ene_send_scsi_cmd(us, FDIR_READ, scsi_sglist(srb), 1); | |
391 | return result; | |
392 | } | |
393 | ||
394 | static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb) | |
395 | { | |
396 | int result; | |
397 | unsigned char *cdb = srb->cmnd; | |
398 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
399 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | |
400 | ||
401 | u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) | | |
402 | ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff); | |
403 | u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff); | |
404 | u32 bnByte = bn * 0x200; | |
405 | u32 blenByte = blen * 0x200; | |
406 | ||
407 | if (bn > info->bl_num) | |
408 | return USB_STOR_TRANSPORT_ERROR; | |
409 | ||
410 | result = ene_load_bincode(us, SD_RW_PATTERN); | |
411 | if (result != USB_STOR_XFER_GOOD) { | |
412 | US_DEBUGP("Load SD RW pattern Fail !!\n"); | |
413 | return USB_STOR_TRANSPORT_ERROR; | |
414 | } | |
415 | ||
416 | if (info->SD_Status.HiCapacity) | |
417 | bnByte = bn; | |
418 | ||
419 | /* set up the command wrapper */ | |
420 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); | |
421 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | |
422 | bcb->DataTransferLength = blenByte; | |
423 | bcb->Flags = 0x00; | |
424 | bcb->CDB[0] = 0xF0; | |
425 | bcb->CDB[5] = (unsigned char)(bnByte); | |
426 | bcb->CDB[4] = (unsigned char)(bnByte>>8); | |
427 | bcb->CDB[3] = (unsigned char)(bnByte>>16); | |
428 | bcb->CDB[2] = (unsigned char)(bnByte>>24); | |
429 | ||
430 | result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1); | |
431 | return result; | |
432 | } | |
433 | ||
434 | static int ene_get_card_type(struct us_data *us, u16 index, void *buf) | |
435 | { | |
436 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
437 | int result; | |
438 | ||
439 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); | |
440 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | |
441 | bcb->DataTransferLength = 0x01; | |
442 | bcb->Flags = 0x80; | |
443 | bcb->CDB[0] = 0xED; | |
444 | bcb->CDB[2] = (unsigned char)(index>>8); | |
445 | bcb->CDB[3] = (unsigned char)index; | |
446 | ||
447 | result = ene_send_scsi_cmd(us, FDIR_READ, buf, 0); | |
448 | return result; | |
449 | } | |
450 | ||
451 | static int ene_get_card_status(struct us_data *us, u8 *buf) | |
452 | { | |
453 | u16 tmpreg; | |
454 | u32 reg4b; | |
455 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | |
456 | ||
457 | /*US_DEBUGP("transport --- ENE_ReadSDReg\n");*/ | |
458 | reg4b = *(u32 *)&buf[0x18]; | |
459 | info->SD_READ_BL_LEN = (u8)((reg4b >> 8) & 0x0f); | |
460 | ||
461 | tmpreg = (u16) reg4b; | |
462 | reg4b = *(u32 *)(&buf[0x14]); | |
463 | if (info->SD_Status.HiCapacity && !info->SD_Status.IsMMC) | |
464 | info->HC_C_SIZE = (reg4b >> 8) & 0x3fffff; | |
465 | ||
466 | info->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (u16)(reg4b >> 22); | |
467 | info->SD_C_SIZE_MULT = (u8)(reg4b >> 7) & 0x07; | |
468 | if (info->SD_Status.HiCapacity && info->SD_Status.IsMMC) | |
469 | info->HC_C_SIZE = *(u32 *)(&buf[0x100]); | |
470 | ||
471 | if (info->SD_READ_BL_LEN > SD_BLOCK_LEN) { | |
472 | info->SD_Block_Mult = 1 << (info->SD_READ_BL_LEN-SD_BLOCK_LEN); | |
473 | info->SD_READ_BL_LEN = SD_BLOCK_LEN; | |
474 | } else { | |
475 | info->SD_Block_Mult = 1; | |
476 | } | |
477 | ||
478 | return USB_STOR_TRANSPORT_GOOD; | |
479 | } | |
480 | ||
481 | static int ene_load_bincode(struct us_data *us, unsigned char flag) | |
482 | { | |
483 | int err; | |
484 | char *fw_name = NULL; | |
485 | unsigned char *buf = NULL; | |
486 | const struct firmware *sd_fw = NULL; | |
487 | int result = USB_STOR_TRANSPORT_ERROR; | |
488 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
489 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | |
490 | ||
491 | if (info->BIN_FLAG == flag) | |
492 | return USB_STOR_TRANSPORT_GOOD; | |
493 | ||
41e568d1 | 494 | switch (flag) { |
495 | /* For SD */ | |
496 | case SD_INIT1_PATTERN: | |
497 | US_DEBUGP("SD_INIT1_PATTERN\n"); | |
498 | fw_name = "ene-ub6250/sd_init1.bin"; | |
499 | break; | |
500 | case SD_INIT2_PATTERN: | |
501 | US_DEBUGP("SD_INIT2_PATTERN\n"); | |
502 | fw_name = "ene-ub6250/sd_init2.bin"; | |
503 | break; | |
504 | case SD_RW_PATTERN: | |
505 | US_DEBUGP("SD_RDWR_PATTERN\n"); | |
506 | fw_name = "ene-ub6250/sd_rdwr.bin"; | |
507 | break; | |
508 | default: | |
509 | US_DEBUGP("----------- Unknown PATTERN ----------\n"); | |
510 | goto nofw; | |
511 | } | |
512 | ||
513 | err = request_firmware(&sd_fw, fw_name, &us->pusb_dev->dev); | |
514 | if (err) { | |
515 | US_DEBUGP("load firmware %s failed\n", fw_name); | |
516 | goto nofw; | |
517 | } | |
518 | buf = kmalloc(sd_fw->size, GFP_KERNEL); | |
519 | if (buf == NULL) { | |
520 | US_DEBUGP("Malloc memory for fireware failed!\n"); | |
521 | goto nofw; | |
522 | } | |
523 | memcpy(buf, sd_fw->data, sd_fw->size); | |
524 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); | |
525 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | |
526 | bcb->DataTransferLength = sd_fw->size; | |
527 | bcb->Flags = 0x00; | |
528 | bcb->CDB[0] = 0xEF; | |
529 | ||
530 | result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0); | |
531 | info->BIN_FLAG = flag; | |
532 | kfree(buf); | |
533 | ||
534 | nofw: | |
535 | if (sd_fw != NULL) { | |
536 | release_firmware(sd_fw); | |
537 | sd_fw = NULL; | |
538 | } | |
539 | ||
540 | return result; | |
541 | } | |
542 | ||
543 | static int ene_sd_init(struct us_data *us) | |
544 | { | |
545 | int result; | |
546 | u8 buf[0x200]; | |
547 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
548 | struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; | |
549 | ||
550 | US_DEBUGP("transport --- ENE_SDInit\n"); | |
551 | /* SD Init Part-1 */ | |
552 | result = ene_load_bincode(us, SD_INIT1_PATTERN); | |
553 | if (result != USB_STOR_XFER_GOOD) { | |
554 | US_DEBUGP("Load SD Init Code Part-1 Fail !!\n"); | |
555 | return USB_STOR_TRANSPORT_ERROR; | |
556 | } | |
557 | ||
558 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); | |
559 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | |
560 | bcb->Flags = 0x80; | |
561 | bcb->CDB[0] = 0xF2; | |
562 | ||
563 | result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0); | |
564 | if (result != USB_STOR_XFER_GOOD) { | |
25985edc | 565 | US_DEBUGP("Execution SD Init Code Fail !!\n"); |
41e568d1 | 566 | return USB_STOR_TRANSPORT_ERROR; |
567 | } | |
568 | ||
569 | /* SD Init Part-2 */ | |
570 | result = ene_load_bincode(us, SD_INIT2_PATTERN); | |
571 | if (result != USB_STOR_XFER_GOOD) { | |
572 | US_DEBUGP("Load SD Init Code Part-2 Fail !!\n"); | |
573 | return USB_STOR_TRANSPORT_ERROR; | |
574 | } | |
575 | ||
576 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); | |
577 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | |
578 | bcb->DataTransferLength = 0x200; | |
579 | bcb->Flags = 0x80; | |
580 | bcb->CDB[0] = 0xF1; | |
581 | ||
582 | result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); | |
583 | if (result != USB_STOR_XFER_GOOD) { | |
25985edc | 584 | US_DEBUGP("Execution SD Init Code Fail !!\n"); |
41e568d1 | 585 | return USB_STOR_TRANSPORT_ERROR; |
586 | } | |
587 | ||
588 | info->SD_Status = *(struct SD_STATUS *)&buf[0]; | |
589 | if (info->SD_Status.Insert && info->SD_Status.Ready) { | |
590 | ene_get_card_status(us, (unsigned char *)&buf); | |
591 | US_DEBUGP("Insert = %x\n", info->SD_Status.Insert); | |
592 | US_DEBUGP("Ready = %x\n", info->SD_Status.Ready); | |
593 | US_DEBUGP("IsMMC = %x\n", info->SD_Status.IsMMC); | |
594 | US_DEBUGP("HiCapacity = %x\n", info->SD_Status.HiCapacity); | |
595 | US_DEBUGP("HiSpeed = %x\n", info->SD_Status.HiSpeed); | |
596 | US_DEBUGP("WtP = %x\n", info->SD_Status.WtP); | |
597 | } else { | |
598 | US_DEBUGP("SD Card Not Ready --- %x\n", buf[0]); | |
599 | return USB_STOR_TRANSPORT_ERROR; | |
600 | } | |
601 | return USB_STOR_TRANSPORT_GOOD; | |
602 | } | |
603 | ||
604 | ||
605 | static int ene_init(struct us_data *us) | |
606 | { | |
607 | int result; | |
608 | u8 misc_reg03 = 0; | |
609 | struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); | |
610 | ||
611 | result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); | |
612 | if (result != USB_STOR_XFER_GOOD) | |
613 | return USB_STOR_TRANSPORT_ERROR; | |
614 | ||
615 | if (misc_reg03 & 0x01) { | |
616 | if (!info->SD_Status.Ready) { | |
617 | result = ene_sd_init(us); | |
618 | if (result != USB_STOR_XFER_GOOD) | |
619 | return USB_STOR_TRANSPORT_ERROR; | |
620 | } | |
621 | } | |
622 | ||
623 | return result; | |
624 | } | |
625 | ||
626 | /*----- sd_scsi_irp() ---------*/ | |
627 | static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb) | |
628 | { | |
629 | int result; | |
630 | struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra; | |
631 | ||
632 | info->SrbStatus = SS_SUCCESS; | |
633 | switch (srb->cmnd[0]) { | |
634 | case TEST_UNIT_READY: | |
635 | result = sd_scsi_test_unit_ready(us, srb); | |
636 | break; /* 0x00 */ | |
637 | case INQUIRY: | |
638 | result = sd_scsi_inquiry(us, srb); | |
639 | break; /* 0x12 */ | |
640 | case MODE_SENSE: | |
641 | result = sd_scsi_mode_sense(us, srb); | |
642 | break; /* 0x1A */ | |
643 | /* | |
644 | case START_STOP: | |
645 | result = SD_SCSI_Start_Stop(us, srb); | |
646 | break; //0x1B | |
647 | */ | |
648 | case READ_CAPACITY: | |
649 | result = sd_scsi_read_capacity(us, srb); | |
650 | break; /* 0x25 */ | |
651 | case READ_10: | |
652 | result = sd_scsi_read(us, srb); | |
653 | break; /* 0x28 */ | |
654 | case WRITE_10: | |
655 | result = sd_scsi_write(us, srb); | |
656 | break; /* 0x2A */ | |
657 | default: | |
658 | info->SrbStatus = SS_ILLEGAL_REQUEST; | |
659 | result = USB_STOR_TRANSPORT_FAILED; | |
660 | break; | |
661 | } | |
662 | return result; | |
663 | } | |
664 | ||
665 | static int ene_transport(struct scsi_cmnd *srb, struct us_data *us) | |
666 | { | |
667 | int result = 0; | |
668 | struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); | |
669 | ||
670 | /*US_DEBUG(usb_stor_show_command(srb)); */ | |
671 | scsi_set_resid(srb, 0); | |
672 | if (unlikely(!info->SD_Status.Ready)) | |
673 | result = ene_init(us); | |
674 | else | |
675 | result = sd_scsi_irp(us, srb); | |
676 | ||
677 | return 0; | |
678 | } | |
679 | ||
680 | ||
681 | static int ene_ub6250_probe(struct usb_interface *intf, | |
682 | const struct usb_device_id *id) | |
683 | { | |
684 | int result; | |
685 | u8 misc_reg03 = 0; | |
686 | struct us_data *us; | |
687 | ||
688 | result = usb_stor_probe1(&us, intf, id, | |
689 | (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list); | |
690 | if (result) | |
691 | return result; | |
692 | ||
693 | /* FIXME: where should the code alloc extra buf ? */ | |
694 | if (!us->extra) { | |
695 | us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL); | |
696 | if (!us->extra) | |
697 | return -ENOMEM; | |
698 | us->extra_destructor = ene_ub6250_info_destructor; | |
699 | } | |
700 | ||
701 | us->transport_name = "ene_ub6250"; | |
702 | us->transport = ene_transport; | |
703 | us->max_lun = 0; | |
704 | ||
705 | result = usb_stor_probe2(us); | |
706 | if (result) | |
707 | return result; | |
708 | ||
709 | /* probe card type */ | |
710 | result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); | |
711 | if (result != USB_STOR_XFER_GOOD) { | |
712 | usb_stor_disconnect(intf); | |
713 | return USB_STOR_TRANSPORT_ERROR; | |
714 | } | |
715 | ||
716 | if (!(misc_reg03 & 0x01)) { | |
717 | result = -ENODEV; | |
718 | printk(KERN_NOTICE "ums_eneub6250: The driver only supports SD\ | |
719 | card. To use SM/MS card, please build driver/stagging/keucr\n"); | |
720 | usb_stor_disconnect(intf); | |
721 | } | |
722 | ||
723 | return result; | |
724 | } | |
725 | ||
726 | ||
727 | #ifdef CONFIG_PM | |
728 | ||
729 | static int ene_ub6250_resume(struct usb_interface *iface) | |
730 | { | |
731 | u8 tmp = 0; | |
732 | struct us_data *us = usb_get_intfdata(iface); | |
733 | struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); | |
734 | ||
735 | mutex_lock(&us->dev_mutex); | |
736 | ||
737 | US_DEBUGP("%s\n", __func__); | |
738 | if (us->suspend_resume_hook) | |
739 | (us->suspend_resume_hook)(us, US_RESUME); | |
740 | ||
741 | mutex_unlock(&us->dev_mutex); | |
742 | ||
743 | info->Power_IsResum = true; | |
744 | /*info->SD_Status.Ready = 0; */ | |
745 | info->SD_Status = *(struct SD_STATUS *)&tmp; | |
746 | info->MS_Status = *(struct MS_STATUS *)&tmp; | |
747 | info->SM_Status = *(struct SM_STATUS *)&tmp; | |
748 | ||
749 | return 0; | |
750 | } | |
751 | ||
752 | static int ene_ub6250_reset_resume(struct usb_interface *iface) | |
753 | { | |
754 | u8 tmp = 0; | |
755 | struct us_data *us = usb_get_intfdata(iface); | |
756 | struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); | |
757 | US_DEBUGP("%s\n", __func__); | |
758 | /* Report the reset to the SCSI core */ | |
759 | usb_stor_reset_resume(iface); | |
760 | ||
761 | /* FIXME: Notify the subdrivers that they need to reinitialize | |
762 | * the device */ | |
763 | info->Power_IsResum = true; | |
764 | /*info->SD_Status.Ready = 0; */ | |
765 | info->SD_Status = *(struct SD_STATUS *)&tmp; | |
766 | info->MS_Status = *(struct MS_STATUS *)&tmp; | |
767 | info->SM_Status = *(struct SM_STATUS *)&tmp; | |
768 | ||
769 | return 0; | |
770 | } | |
771 | ||
772 | #else | |
773 | ||
774 | #define ene_ub6250_resume NULL | |
775 | #define ene_ub6250_reset_resume NULL | |
776 | ||
777 | #endif | |
778 | ||
779 | static struct usb_driver ene_ub6250_driver = { | |
780 | .name = "ums_eneub6250", | |
781 | .probe = ene_ub6250_probe, | |
782 | .disconnect = usb_stor_disconnect, | |
783 | .suspend = usb_stor_suspend, | |
784 | .resume = ene_ub6250_resume, | |
785 | .reset_resume = ene_ub6250_reset_resume, | |
786 | .pre_reset = usb_stor_pre_reset, | |
787 | .post_reset = usb_stor_post_reset, | |
788 | .id_table = ene_ub6250_usb_ids, | |
789 | .soft_unbind = 1, | |
790 | }; | |
791 | ||
792 | static int __init ene_ub6250_init(void) | |
793 | { | |
794 | return usb_register(&ene_ub6250_driver); | |
795 | } | |
796 | ||
797 | static void __exit ene_ub6250_exit(void) | |
798 | { | |
799 | usb_deregister(&ene_ub6250_driver); | |
800 | } | |
801 | ||
802 | module_init(ene_ub6250_init); | |
803 | module_exit(ene_ub6250_exit); |