1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Driver for Datafab USB Compact Flash reader |
4 | * |
5 | * datafab driver v0.1: |
6 | * |
7 | * First release |
8 | * |
9 | * Current development and maintenance by: |
10 | * (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org) |
11 | * |
12 | * Many thanks to Robert Baruch for the SanDisk SmartMedia reader driver |
13 | * which I used as a template for this driver. |
14 | * |
15 | * Some bugfixes and scatter-gather code by Gregory P. Smith |
16 | * (greg-usb@electricrain.com) |
17 | * |
18 | * Fix for media change by Joerg Schneider (js@joergschneider.com) |
19 | * |
20 | * Other contributors: |
21 | * (c) 2002 Alan Stern <stern@rowland.org> |
22 | */ |
23 | |
24 | /* |
25 | * This driver attempts to support USB CompactFlash reader/writer devices |
26 | * based on Datafab USB-to-ATA chips. It was specifically developed for the |
27 | * Datafab MDCFE-B USB CompactFlash reader but has since been found to work |
28 | * with a variety of Datafab-based devices from a number of manufacturers. |
29 | * I've received a report of this driver working with a Datafab-based |
30 | * SmartMedia device though please be aware that I'm personally unable to |
31 | * test SmartMedia support. |
32 | * |
33 | * This driver supports reading and writing. If you're truly paranoid, |
34 | * however, you can force the driver into a write-protected state by setting |
35 | * the WP enable bits in datafab_handle_mode_sense(). See the comments |
36 | * in that routine. |
37 | */ |
38 | |
39 | #include <linux/errno.h> |
40 | #include <linux/module.h> |
41 | #include <linux/slab.h> |
42 | |
43 | #include <scsi/scsi.h> |
44 | #include <scsi/scsi_cmnd.h> |
45 | |
46 | #include "usb.h" |
47 | #include "transport.h" |
48 | #include "protocol.h" |
49 | #include "debug.h" |
50 | #include "scsiglue.h" |
51 | |
52 | #define DRV_NAME "ums-datafab" |
53 | |
54 | MODULE_DESCRIPTION("Driver for Datafab USB Compact Flash reader" ); |
55 | MODULE_AUTHOR("Jimmie Mayfield <mayfield+datafab@sackheads.org>" ); |
56 | MODULE_LICENSE("GPL" ); |
57 | MODULE_IMPORT_NS(USB_STORAGE); |
58 | |
59 | struct datafab_info { |
60 | unsigned long sectors; /* total sector count */ |
61 | unsigned long ssize; /* sector size in bytes */ |
62 | signed char lun; /* used for dual-slot readers */ |
63 | |
64 | /* the following aren't used yet */ |
65 | unsigned char sense_key; |
66 | unsigned long sense_asc; /* additional sense code */ |
67 | unsigned long sense_ascq; /* additional sense code qualifier */ |
68 | }; |
69 | |
70 | static int datafab_determine_lun(struct us_data *us, |
71 | struct datafab_info *info); |
72 | |
73 | |
74 | /* |
75 | * The table of devices |
76 | */ |
77 | #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ |
78 | vendorName, productName, useProtocol, useTransport, \ |
79 | initFunction, flags) \ |
80 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ |
81 | .driver_info = (flags) } |
82 | |
83 | static struct usb_device_id datafab_usb_ids[] = { |
84 | # include "unusual_datafab.h" |
85 | { } /* Terminating entry */ |
86 | }; |
87 | MODULE_DEVICE_TABLE(usb, datafab_usb_ids); |
88 | |
89 | #undef UNUSUAL_DEV |
90 | |
91 | /* |
92 | * The flags table |
93 | */ |
94 | #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ |
95 | vendor_name, product_name, use_protocol, use_transport, \ |
96 | init_function, Flags) \ |
97 | { \ |
98 | .vendorName = vendor_name, \ |
99 | .productName = product_name, \ |
100 | .useProtocol = use_protocol, \ |
101 | .useTransport = use_transport, \ |
102 | .initFunction = init_function, \ |
103 | } |
104 | |
105 | static struct us_unusual_dev datafab_unusual_dev_list[] = { |
106 | # include "unusual_datafab.h" |
107 | { } /* Terminating entry */ |
108 | }; |
109 | |
110 | #undef UNUSUAL_DEV |
111 | |
112 | |
113 | static inline int |
114 | datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) { |
115 | if (len == 0) |
116 | return USB_STOR_XFER_GOOD; |
117 | |
118 | usb_stor_dbg(us, fmt: "len = %d\n" , len); |
119 | return usb_stor_bulk_transfer_buf(us, pipe: us->recv_bulk_pipe, |
120 | buf: data, length: len, NULL); |
121 | } |
122 | |
123 | |
124 | static inline int |
125 | datafab_bulk_write(struct us_data *us, unsigned char *data, unsigned int len) { |
126 | if (len == 0) |
127 | return USB_STOR_XFER_GOOD; |
128 | |
129 | usb_stor_dbg(us, fmt: "len = %d\n" , len); |
130 | return usb_stor_bulk_transfer_buf(us, pipe: us->send_bulk_pipe, |
131 | buf: data, length: len, NULL); |
132 | } |
133 | |
134 | |
135 | static int datafab_read_data(struct us_data *us, |
136 | struct datafab_info *info, |
137 | u32 sector, |
138 | u32 sectors) |
139 | { |
140 | unsigned char *command = us->iobuf; |
141 | unsigned char *buffer; |
142 | unsigned char thistime; |
143 | unsigned int totallen, alloclen; |
144 | int len, result; |
145 | unsigned int sg_offset = 0; |
146 | struct scatterlist *sg = NULL; |
147 | |
148 | // we're working in LBA mode. according to the ATA spec, |
149 | // we can support up to 28-bit addressing. I don't know if Datafab |
150 | // supports beyond 24-bit addressing. It's kind of hard to test |
151 | // since it requires > 8GB CF card. |
152 | // |
153 | if (sectors > 0x0FFFFFFF) |
154 | return USB_STOR_TRANSPORT_ERROR; |
155 | |
156 | if (info->lun == -1) { |
157 | result = datafab_determine_lun(us, info); |
158 | if (result != USB_STOR_TRANSPORT_GOOD) |
159 | return result; |
160 | } |
161 | |
162 | totallen = sectors * info->ssize; |
163 | |
164 | // Since we don't read more than 64 KB at a time, we have to create |
165 | // a bounce buffer and move the data a piece at a time between the |
166 | // bounce buffer and the actual transfer buffer. |
167 | |
168 | alloclen = min(totallen, 65536u); |
169 | buffer = kmalloc(size: alloclen, GFP_NOIO); |
170 | if (buffer == NULL) |
171 | return USB_STOR_TRANSPORT_ERROR; |
172 | |
173 | do { |
174 | // loop, never allocate or transfer more than 64k at once |
175 | // (min(128k, 255*info->ssize) is the real limit) |
176 | |
177 | len = min(totallen, alloclen); |
178 | thistime = (len / info->ssize) & 0xff; |
179 | |
180 | command[0] = 0; |
181 | command[1] = thistime; |
182 | command[2] = sector & 0xFF; |
183 | command[3] = (sector >> 8) & 0xFF; |
184 | command[4] = (sector >> 16) & 0xFF; |
185 | |
186 | command[5] = 0xE0 + (info->lun << 4); |
187 | command[5] |= (sector >> 24) & 0x0F; |
188 | command[6] = 0x20; |
189 | command[7] = 0x01; |
190 | |
191 | // send the read command |
192 | result = datafab_bulk_write(us, data: command, len: 8); |
193 | if (result != USB_STOR_XFER_GOOD) |
194 | goto leave; |
195 | |
196 | // read the result |
197 | result = datafab_bulk_read(us, data: buffer, len); |
198 | if (result != USB_STOR_XFER_GOOD) |
199 | goto leave; |
200 | |
201 | // Store the data in the transfer buffer |
202 | usb_stor_access_xfer_buf(buffer, buflen: len, srb: us->srb, |
203 | &sg, offset: &sg_offset, dir: TO_XFER_BUF); |
204 | |
205 | sector += thistime; |
206 | totallen -= len; |
207 | } while (totallen > 0); |
208 | |
209 | kfree(objp: buffer); |
210 | return USB_STOR_TRANSPORT_GOOD; |
211 | |
212 | leave: |
213 | kfree(objp: buffer); |
214 | return USB_STOR_TRANSPORT_ERROR; |
215 | } |
216 | |
217 | |
218 | static int datafab_write_data(struct us_data *us, |
219 | struct datafab_info *info, |
220 | u32 sector, |
221 | u32 sectors) |
222 | { |
223 | unsigned char *command = us->iobuf; |
224 | unsigned char *reply = us->iobuf; |
225 | unsigned char *buffer; |
226 | unsigned char thistime; |
227 | unsigned int totallen, alloclen; |
228 | int len, result; |
229 | unsigned int sg_offset = 0; |
230 | struct scatterlist *sg = NULL; |
231 | |
232 | // we're working in LBA mode. according to the ATA spec, |
233 | // we can support up to 28-bit addressing. I don't know if Datafab |
234 | // supports beyond 24-bit addressing. It's kind of hard to test |
235 | // since it requires > 8GB CF card. |
236 | // |
237 | if (sectors > 0x0FFFFFFF) |
238 | return USB_STOR_TRANSPORT_ERROR; |
239 | |
240 | if (info->lun == -1) { |
241 | result = datafab_determine_lun(us, info); |
242 | if (result != USB_STOR_TRANSPORT_GOOD) |
243 | return result; |
244 | } |
245 | |
246 | totallen = sectors * info->ssize; |
247 | |
248 | // Since we don't write more than 64 KB at a time, we have to create |
249 | // a bounce buffer and move the data a piece at a time between the |
250 | // bounce buffer and the actual transfer buffer. |
251 | |
252 | alloclen = min(totallen, 65536u); |
253 | buffer = kmalloc(size: alloclen, GFP_NOIO); |
254 | if (buffer == NULL) |
255 | return USB_STOR_TRANSPORT_ERROR; |
256 | |
257 | do { |
258 | // loop, never allocate or transfer more than 64k at once |
259 | // (min(128k, 255*info->ssize) is the real limit) |
260 | |
261 | len = min(totallen, alloclen); |
262 | thistime = (len / info->ssize) & 0xff; |
263 | |
264 | // Get the data from the transfer buffer |
265 | usb_stor_access_xfer_buf(buffer, buflen: len, srb: us->srb, |
266 | &sg, offset: &sg_offset, dir: FROM_XFER_BUF); |
267 | |
268 | command[0] = 0; |
269 | command[1] = thistime; |
270 | command[2] = sector & 0xFF; |
271 | command[3] = (sector >> 8) & 0xFF; |
272 | command[4] = (sector >> 16) & 0xFF; |
273 | |
274 | command[5] = 0xE0 + (info->lun << 4); |
275 | command[5] |= (sector >> 24) & 0x0F; |
276 | command[6] = 0x30; |
277 | command[7] = 0x02; |
278 | |
279 | // send the command |
280 | result = datafab_bulk_write(us, data: command, len: 8); |
281 | if (result != USB_STOR_XFER_GOOD) |
282 | goto leave; |
283 | |
284 | // send the data |
285 | result = datafab_bulk_write(us, data: buffer, len); |
286 | if (result != USB_STOR_XFER_GOOD) |
287 | goto leave; |
288 | |
289 | // read the result |
290 | result = datafab_bulk_read(us, data: reply, len: 2); |
291 | if (result != USB_STOR_XFER_GOOD) |
292 | goto leave; |
293 | |
294 | if (reply[0] != 0x50 && reply[1] != 0) { |
295 | usb_stor_dbg(us, fmt: "Gah! write return code: %02x %02x\n" , |
296 | reply[0], reply[1]); |
297 | goto leave; |
298 | } |
299 | |
300 | sector += thistime; |
301 | totallen -= len; |
302 | } while (totallen > 0); |
303 | |
304 | kfree(objp: buffer); |
305 | return USB_STOR_TRANSPORT_GOOD; |
306 | |
307 | leave: |
308 | kfree(objp: buffer); |
309 | return USB_STOR_TRANSPORT_ERROR; |
310 | } |
311 | |
312 | |
313 | static int datafab_determine_lun(struct us_data *us, |
314 | struct datafab_info *info) |
315 | { |
316 | // Dual-slot readers can be thought of as dual-LUN devices. |
317 | // We need to determine which card slot is being used. |
318 | // We'll send an IDENTIFY DEVICE command and see which LUN responds... |
319 | // |
320 | // There might be a better way of doing this? |
321 | |
322 | static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; |
323 | unsigned char *command = us->iobuf; |
324 | unsigned char *buf; |
325 | int count = 0, rc; |
326 | |
327 | if (!info) |
328 | return USB_STOR_TRANSPORT_ERROR; |
329 | |
330 | memcpy(command, scommand, 8); |
331 | buf = kmalloc(size: 512, GFP_NOIO); |
332 | if (!buf) |
333 | return USB_STOR_TRANSPORT_ERROR; |
334 | |
335 | usb_stor_dbg(us, fmt: "locating...\n" ); |
336 | |
337 | // we'll try 3 times before giving up... |
338 | // |
339 | while (count++ < 3) { |
340 | command[5] = 0xa0; |
341 | |
342 | rc = datafab_bulk_write(us, data: command, len: 8); |
343 | if (rc != USB_STOR_XFER_GOOD) { |
344 | rc = USB_STOR_TRANSPORT_ERROR; |
345 | goto leave; |
346 | } |
347 | |
348 | rc = datafab_bulk_read(us, data: buf, len: 512); |
349 | if (rc == USB_STOR_XFER_GOOD) { |
350 | info->lun = 0; |
351 | rc = USB_STOR_TRANSPORT_GOOD; |
352 | goto leave; |
353 | } |
354 | |
355 | command[5] = 0xb0; |
356 | |
357 | rc = datafab_bulk_write(us, data: command, len: 8); |
358 | if (rc != USB_STOR_XFER_GOOD) { |
359 | rc = USB_STOR_TRANSPORT_ERROR; |
360 | goto leave; |
361 | } |
362 | |
363 | rc = datafab_bulk_read(us, data: buf, len: 512); |
364 | if (rc == USB_STOR_XFER_GOOD) { |
365 | info->lun = 1; |
366 | rc = USB_STOR_TRANSPORT_GOOD; |
367 | goto leave; |
368 | } |
369 | |
370 | msleep(msecs: 20); |
371 | } |
372 | |
373 | rc = USB_STOR_TRANSPORT_ERROR; |
374 | |
375 | leave: |
376 | kfree(objp: buf); |
377 | return rc; |
378 | } |
379 | |
380 | static int datafab_id_device(struct us_data *us, |
381 | struct datafab_info *info) |
382 | { |
383 | // this is a variation of the ATA "IDENTIFY DEVICE" command...according |
384 | // to the ATA spec, 'Sector Count' isn't used but the Windows driver |
385 | // sets this bit so we do too... |
386 | // |
387 | static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; |
388 | unsigned char *command = us->iobuf; |
389 | unsigned char *reply; |
390 | int rc; |
391 | |
392 | if (!info) |
393 | return USB_STOR_TRANSPORT_ERROR; |
394 | |
395 | if (info->lun == -1) { |
396 | rc = datafab_determine_lun(us, info); |
397 | if (rc != USB_STOR_TRANSPORT_GOOD) |
398 | return rc; |
399 | } |
400 | |
401 | memcpy(command, scommand, 8); |
402 | reply = kmalloc(size: 512, GFP_NOIO); |
403 | if (!reply) |
404 | return USB_STOR_TRANSPORT_ERROR; |
405 | |
406 | command[5] += (info->lun << 4); |
407 | |
408 | rc = datafab_bulk_write(us, data: command, len: 8); |
409 | if (rc != USB_STOR_XFER_GOOD) { |
410 | rc = USB_STOR_TRANSPORT_ERROR; |
411 | goto leave; |
412 | } |
413 | |
414 | // we'll go ahead and extract the media capacity while we're here... |
415 | // |
416 | rc = datafab_bulk_read(us, data: reply, len: 512); |
417 | if (rc == USB_STOR_XFER_GOOD) { |
418 | // capacity is at word offset 57-58 |
419 | // |
420 | info->sectors = ((u32)(reply[117]) << 24) | |
421 | ((u32)(reply[116]) << 16) | |
422 | ((u32)(reply[115]) << 8) | |
423 | ((u32)(reply[114]) ); |
424 | rc = USB_STOR_TRANSPORT_GOOD; |
425 | goto leave; |
426 | } |
427 | |
428 | rc = USB_STOR_TRANSPORT_ERROR; |
429 | |
430 | leave: |
431 | kfree(objp: reply); |
432 | return rc; |
433 | } |
434 | |
435 | |
436 | static int datafab_handle_mode_sense(struct us_data *us, |
437 | struct scsi_cmnd * srb, |
438 | int sense_6) |
439 | { |
440 | static unsigned char rw_err_page[12] = { |
441 | 0x1, 0xA, 0x21, 1, 0, 0, 0, 0, 1, 0, 0, 0 |
442 | }; |
443 | static unsigned char cache_page[12] = { |
444 | 0x8, 0xA, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
445 | }; |
446 | static unsigned char rbac_page[12] = { |
447 | 0x1B, 0xA, 0, 0x81, 0, 0, 0, 0, 0, 0, 0, 0 |
448 | }; |
449 | static unsigned char timer_page[8] = { |
450 | 0x1C, 0x6, 0, 0, 0, 0 |
451 | }; |
452 | unsigned char pc, page_code; |
453 | unsigned int i = 0; |
454 | struct datafab_info *info = (struct datafab_info *) (us->extra); |
455 | unsigned char *ptr = us->iobuf; |
456 | |
457 | // most of this stuff is just a hack to get things working. the |
458 | // datafab reader doesn't present a SCSI interface so we |
459 | // fudge the SCSI commands... |
460 | // |
461 | |
462 | pc = srb->cmnd[2] >> 6; |
463 | page_code = srb->cmnd[2] & 0x3F; |
464 | |
465 | switch (pc) { |
466 | case 0x0: |
467 | usb_stor_dbg(us, fmt: "Current values\n" ); |
468 | break; |
469 | case 0x1: |
470 | usb_stor_dbg(us, fmt: "Changeable values\n" ); |
471 | break; |
472 | case 0x2: |
473 | usb_stor_dbg(us, fmt: "Default values\n" ); |
474 | break; |
475 | case 0x3: |
476 | usb_stor_dbg(us, fmt: "Saves values\n" ); |
477 | break; |
478 | } |
479 | |
480 | memset(ptr, 0, 8); |
481 | if (sense_6) { |
482 | ptr[2] = 0x00; // WP enable: 0x80 |
483 | i = 4; |
484 | } else { |
485 | ptr[3] = 0x00; // WP enable: 0x80 |
486 | i = 8; |
487 | } |
488 | |
489 | switch (page_code) { |
490 | default: |
491 | // vendor-specific mode |
492 | info->sense_key = 0x05; |
493 | info->sense_asc = 0x24; |
494 | info->sense_ascq = 0x00; |
495 | return USB_STOR_TRANSPORT_FAILED; |
496 | |
497 | case 0x1: |
498 | memcpy(ptr + i, rw_err_page, sizeof(rw_err_page)); |
499 | i += sizeof(rw_err_page); |
500 | break; |
501 | |
502 | case 0x8: |
503 | memcpy(ptr + i, cache_page, sizeof(cache_page)); |
504 | i += sizeof(cache_page); |
505 | break; |
506 | |
507 | case 0x1B: |
508 | memcpy(ptr + i, rbac_page, sizeof(rbac_page)); |
509 | i += sizeof(rbac_page); |
510 | break; |
511 | |
512 | case 0x1C: |
513 | memcpy(ptr + i, timer_page, sizeof(timer_page)); |
514 | i += sizeof(timer_page); |
515 | break; |
516 | |
517 | case 0x3F: // retrieve all pages |
518 | memcpy(ptr + i, timer_page, sizeof(timer_page)); |
519 | i += sizeof(timer_page); |
520 | memcpy(ptr + i, rbac_page, sizeof(rbac_page)); |
521 | i += sizeof(rbac_page); |
522 | memcpy(ptr + i, cache_page, sizeof(cache_page)); |
523 | i += sizeof(cache_page); |
524 | memcpy(ptr + i, rw_err_page, sizeof(rw_err_page)); |
525 | i += sizeof(rw_err_page); |
526 | break; |
527 | } |
528 | |
529 | if (sense_6) |
530 | ptr[0] = i - 1; |
531 | else |
532 | ((__be16 *) ptr)[0] = cpu_to_be16(i - 2); |
533 | usb_stor_set_xfer_buf(buffer: ptr, buflen: i, srb); |
534 | |
535 | return USB_STOR_TRANSPORT_GOOD; |
536 | } |
537 | |
538 | static void datafab_info_destructor(void *) |
539 | { |
540 | // this routine is a placeholder... |
541 | // currently, we don't allocate any extra memory so we're okay |
542 | } |
543 | |
544 | |
545 | // Transport for the Datafab MDCFE-B |
546 | // |
547 | static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us) |
548 | { |
549 | struct datafab_info *info; |
550 | int rc; |
551 | unsigned long block, blocks; |
552 | unsigned char *ptr = us->iobuf; |
553 | static unsigned char inquiry_reply[8] = { |
554 | 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00 |
555 | }; |
556 | |
557 | if (!us->extra) { |
558 | us->extra = kzalloc(size: sizeof(struct datafab_info), GFP_NOIO); |
559 | if (!us->extra) |
560 | return USB_STOR_TRANSPORT_ERROR; |
561 | |
562 | us->extra_destructor = datafab_info_destructor; |
563 | ((struct datafab_info *)us->extra)->lun = -1; |
564 | } |
565 | |
566 | info = (struct datafab_info *) (us->extra); |
567 | |
568 | if (srb->cmnd[0] == INQUIRY) { |
569 | usb_stor_dbg(us, fmt: "INQUIRY - Returning bogus response\n" ); |
570 | memcpy(ptr, inquiry_reply, sizeof(inquiry_reply)); |
571 | fill_inquiry_response(us, data: ptr, data_len: 36); |
572 | return USB_STOR_TRANSPORT_GOOD; |
573 | } |
574 | |
575 | if (srb->cmnd[0] == READ_CAPACITY) { |
576 | info->ssize = 0x200; // hard coded 512 byte sectors as per ATA spec |
577 | rc = datafab_id_device(us, info); |
578 | if (rc != USB_STOR_TRANSPORT_GOOD) |
579 | return rc; |
580 | |
581 | usb_stor_dbg(us, fmt: "READ_CAPACITY: %ld sectors, %ld bytes per sector\n" , |
582 | info->sectors, info->ssize); |
583 | |
584 | // build the reply |
585 | // we need the last sector, not the number of sectors |
586 | ((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1); |
587 | ((__be32 *) ptr)[1] = cpu_to_be32(info->ssize); |
588 | usb_stor_set_xfer_buf(buffer: ptr, buflen: 8, srb); |
589 | |
590 | return USB_STOR_TRANSPORT_GOOD; |
591 | } |
592 | |
593 | if (srb->cmnd[0] == MODE_SELECT_10) { |
594 | usb_stor_dbg(us, fmt: "Gah! MODE_SELECT_10\n" ); |
595 | return USB_STOR_TRANSPORT_ERROR; |
596 | } |
597 | |
598 | // don't bother implementing READ_6 or WRITE_6. |
599 | // |
600 | if (srb->cmnd[0] == READ_10) { |
601 | block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | |
602 | ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); |
603 | |
604 | blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); |
605 | |
606 | usb_stor_dbg(us, fmt: "READ_10: read block 0x%04lx count %ld\n" , |
607 | block, blocks); |
608 | return datafab_read_data(us, info, sector: block, sectors: blocks); |
609 | } |
610 | |
611 | if (srb->cmnd[0] == READ_12) { |
612 | // we'll probably never see a READ_12 but we'll do it anyway... |
613 | // |
614 | block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | |
615 | ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); |
616 | |
617 | blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) | |
618 | ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); |
619 | |
620 | usb_stor_dbg(us, fmt: "READ_12: read block 0x%04lx count %ld\n" , |
621 | block, blocks); |
622 | return datafab_read_data(us, info, sector: block, sectors: blocks); |
623 | } |
624 | |
625 | if (srb->cmnd[0] == WRITE_10) { |
626 | block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | |
627 | ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); |
628 | |
629 | blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); |
630 | |
631 | usb_stor_dbg(us, fmt: "WRITE_10: write block 0x%04lx count %ld\n" , |
632 | block, blocks); |
633 | return datafab_write_data(us, info, sector: block, sectors: blocks); |
634 | } |
635 | |
636 | if (srb->cmnd[0] == WRITE_12) { |
637 | // we'll probably never see a WRITE_12 but we'll do it anyway... |
638 | // |
639 | block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | |
640 | ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); |
641 | |
642 | blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) | |
643 | ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); |
644 | |
645 | usb_stor_dbg(us, fmt: "WRITE_12: write block 0x%04lx count %ld\n" , |
646 | block, blocks); |
647 | return datafab_write_data(us, info, sector: block, sectors: blocks); |
648 | } |
649 | |
650 | if (srb->cmnd[0] == TEST_UNIT_READY) { |
651 | usb_stor_dbg(us, fmt: "TEST_UNIT_READY\n" ); |
652 | return datafab_id_device(us, info); |
653 | } |
654 | |
655 | if (srb->cmnd[0] == REQUEST_SENSE) { |
656 | usb_stor_dbg(us, fmt: "REQUEST_SENSE - Returning faked response\n" ); |
657 | |
658 | // this response is pretty bogus right now. eventually if necessary |
659 | // we can set the correct sense data. so far though it hasn't been |
660 | // necessary |
661 | // |
662 | memset(ptr, 0, 18); |
663 | ptr[0] = 0xF0; |
664 | ptr[2] = info->sense_key; |
665 | ptr[7] = 11; |
666 | ptr[12] = info->sense_asc; |
667 | ptr[13] = info->sense_ascq; |
668 | usb_stor_set_xfer_buf(buffer: ptr, buflen: 18, srb); |
669 | |
670 | return USB_STOR_TRANSPORT_GOOD; |
671 | } |
672 | |
673 | if (srb->cmnd[0] == MODE_SENSE) { |
674 | usb_stor_dbg(us, fmt: "MODE_SENSE_6 detected\n" ); |
675 | return datafab_handle_mode_sense(us, srb, sense_6: 1); |
676 | } |
677 | |
678 | if (srb->cmnd[0] == MODE_SENSE_10) { |
679 | usb_stor_dbg(us, fmt: "MODE_SENSE_10 detected\n" ); |
680 | return datafab_handle_mode_sense(us, srb, sense_6: 0); |
681 | } |
682 | |
683 | if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { |
684 | /* |
685 | * sure. whatever. not like we can stop the user from |
686 | * popping the media out of the device (no locking doors, etc) |
687 | */ |
688 | return USB_STOR_TRANSPORT_GOOD; |
689 | } |
690 | |
691 | if (srb->cmnd[0] == START_STOP) { |
692 | /* |
693 | * this is used by sd.c'check_scsidisk_media_change to detect |
694 | * media change |
695 | */ |
696 | usb_stor_dbg(us, fmt: "START_STOP\n" ); |
697 | /* |
698 | * the first datafab_id_device after a media change returns |
699 | * an error (determined experimentally) |
700 | */ |
701 | rc = datafab_id_device(us, info); |
702 | if (rc == USB_STOR_TRANSPORT_GOOD) { |
703 | info->sense_key = NO_SENSE; |
704 | srb->result = SUCCESS; |
705 | } else { |
706 | info->sense_key = UNIT_ATTENTION; |
707 | srb->result = SAM_STAT_CHECK_CONDITION; |
708 | } |
709 | return rc; |
710 | } |
711 | |
712 | usb_stor_dbg(us, fmt: "Gah! Unknown command: %d (0x%x)\n" , |
713 | srb->cmnd[0], srb->cmnd[0]); |
714 | info->sense_key = 0x05; |
715 | info->sense_asc = 0x20; |
716 | info->sense_ascq = 0x00; |
717 | return USB_STOR_TRANSPORT_FAILED; |
718 | } |
719 | |
720 | static struct scsi_host_template datafab_host_template; |
721 | |
722 | static int datafab_probe(struct usb_interface *intf, |
723 | const struct usb_device_id *id) |
724 | { |
725 | struct us_data *us; |
726 | int result; |
727 | |
728 | result = usb_stor_probe1(pus: &us, intf, id, |
729 | unusual_dev: (id - datafab_usb_ids) + datafab_unusual_dev_list, |
730 | sht: &datafab_host_template); |
731 | if (result) |
732 | return result; |
733 | |
734 | us->transport_name = "Datafab Bulk-Only" ; |
735 | us->transport = datafab_transport; |
736 | us->transport_reset = usb_stor_Bulk_reset; |
737 | us->max_lun = 1; |
738 | |
739 | result = usb_stor_probe2(us); |
740 | return result; |
741 | } |
742 | |
743 | static struct usb_driver datafab_driver = { |
744 | .name = DRV_NAME, |
745 | .probe = datafab_probe, |
746 | .disconnect = usb_stor_disconnect, |
747 | .suspend = usb_stor_suspend, |
748 | .resume = usb_stor_resume, |
749 | .reset_resume = usb_stor_reset_resume, |
750 | .pre_reset = usb_stor_pre_reset, |
751 | .post_reset = usb_stor_post_reset, |
752 | .id_table = datafab_usb_ids, |
753 | .soft_unbind = 1, |
754 | .no_dynamic_id = 1, |
755 | }; |
756 | |
757 | module_usb_stor_driver(datafab_driver, datafab_host_template, DRV_NAME); |
758 | |