diff options
Diffstat (limited to 'drivers/usb/storage/usb.c')
-rw-r--r-- | drivers/usb/storage/usb.c | 106 |
1 files changed, 92 insertions, 14 deletions
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 27016fd2cad1..4becf495ca2d 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
@@ -75,9 +75,6 @@ | |||
75 | #ifdef CONFIG_USB_STORAGE_SDDR55 | 75 | #ifdef CONFIG_USB_STORAGE_SDDR55 |
76 | #include "sddr55.h" | 76 | #include "sddr55.h" |
77 | #endif | 77 | #endif |
78 | #ifdef CONFIG_USB_STORAGE_DPCM | ||
79 | #include "dpcm.h" | ||
80 | #endif | ||
81 | #ifdef CONFIG_USB_STORAGE_FREECOM | 78 | #ifdef CONFIG_USB_STORAGE_FREECOM |
82 | #include "freecom.h" | 79 | #include "freecom.h" |
83 | #endif | 80 | #endif |
@@ -103,6 +100,7 @@ | |||
103 | #include "cypress_atacb.h" | 100 | #include "cypress_atacb.h" |
104 | #endif | 101 | #endif |
105 | #include "sierra_ms.h" | 102 | #include "sierra_ms.h" |
103 | #include "option_ms.h" | ||
106 | 104 | ||
107 | /* Some informational data */ | 105 | /* Some informational data */ |
108 | MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); | 106 | MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); |
@@ -113,6 +111,10 @@ static unsigned int delay_use = 5; | |||
113 | module_param(delay_use, uint, S_IRUGO | S_IWUSR); | 111 | module_param(delay_use, uint, S_IRUGO | S_IWUSR); |
114 | MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); | 112 | MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); |
115 | 113 | ||
114 | static char quirks[128]; | ||
115 | module_param_string(quirks, quirks, sizeof(quirks), S_IRUGO | S_IWUSR); | ||
116 | MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks"); | ||
117 | |||
116 | 118 | ||
117 | /* | 119 | /* |
118 | * The entries in this table correspond, line for line, | 120 | * The entries in this table correspond, line for line, |
@@ -126,6 +128,8 @@ MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); | |||
126 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ | 128 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ |
127 | .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } | 129 | .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } |
128 | 130 | ||
131 | #define COMPLIANT_DEV UNUSUAL_DEV | ||
132 | |||
129 | #define USUAL_DEV(useProto, useTrans, useType) \ | 133 | #define USUAL_DEV(useProto, useTrans, useType) \ |
130 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ | 134 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ |
131 | .driver_info = (USB_US_TYPE_STOR<<24) } | 135 | .driver_info = (USB_US_TYPE_STOR<<24) } |
@@ -134,6 +138,7 @@ static struct usb_device_id storage_usb_ids [] = { | |||
134 | 138 | ||
135 | # include "unusual_devs.h" | 139 | # include "unusual_devs.h" |
136 | #undef UNUSUAL_DEV | 140 | #undef UNUSUAL_DEV |
141 | #undef COMPLIANT_DEV | ||
137 | #undef USUAL_DEV | 142 | #undef USUAL_DEV |
138 | /* Terminating entry */ | 143 | /* Terminating entry */ |
139 | { } | 144 | { } |
@@ -164,6 +169,8 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids); | |||
164 | .initFunction = init_function, \ | 169 | .initFunction = init_function, \ |
165 | } | 170 | } |
166 | 171 | ||
172 | #define COMPLIANT_DEV UNUSUAL_DEV | ||
173 | |||
167 | #define USUAL_DEV(use_protocol, use_transport, use_type) \ | 174 | #define USUAL_DEV(use_protocol, use_transport, use_type) \ |
168 | { \ | 175 | { \ |
169 | .useProtocol = use_protocol, \ | 176 | .useProtocol = use_protocol, \ |
@@ -173,6 +180,7 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids); | |||
173 | static struct us_unusual_dev us_unusual_dev_list[] = { | 180 | static struct us_unusual_dev us_unusual_dev_list[] = { |
174 | # include "unusual_devs.h" | 181 | # include "unusual_devs.h" |
175 | # undef UNUSUAL_DEV | 182 | # undef UNUSUAL_DEV |
183 | # undef COMPLIANT_DEV | ||
176 | # undef USUAL_DEV | 184 | # undef USUAL_DEV |
177 | 185 | ||
178 | /* Terminating entry */ | 186 | /* Terminating entry */ |
@@ -464,13 +472,83 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf) | |||
464 | US_DEBUGP("I/O buffer allocation failed\n"); | 472 | US_DEBUGP("I/O buffer allocation failed\n"); |
465 | return -ENOMEM; | 473 | return -ENOMEM; |
466 | } | 474 | } |
475 | return 0; | ||
476 | } | ||
467 | 477 | ||
468 | us->sensebuf = kmalloc(US_SENSE_SIZE, GFP_KERNEL); | 478 | /* Works only for digits and letters, but small and fast */ |
469 | if (!us->sensebuf) { | 479 | #define TOLOWER(x) ((x) | 0x20) |
470 | US_DEBUGP("Sense buffer allocation failed\n"); | 480 | |
471 | return -ENOMEM; | 481 | /* Adjust device flags based on the "quirks=" module parameter */ |
482 | static void adjust_quirks(struct us_data *us) | ||
483 | { | ||
484 | char *p; | ||
485 | u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor); | ||
486 | u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct); | ||
487 | unsigned f = 0; | ||
488 | unsigned int mask = (US_FL_SANE_SENSE | US_FL_FIX_CAPACITY | | ||
489 | US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE | | ||
490 | US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 | | ||
491 | US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE | | ||
492 | US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT); | ||
493 | |||
494 | p = quirks; | ||
495 | while (*p) { | ||
496 | /* Each entry consists of VID:PID:flags */ | ||
497 | if (vid == simple_strtoul(p, &p, 16) && | ||
498 | *p == ':' && | ||
499 | pid == simple_strtoul(p+1, &p, 16) && | ||
500 | *p == ':') | ||
501 | break; | ||
502 | |||
503 | /* Move forward to the next entry */ | ||
504 | while (*p) { | ||
505 | if (*p++ == ',') | ||
506 | break; | ||
507 | } | ||
472 | } | 508 | } |
473 | return 0; | 509 | if (!*p) /* No match */ |
510 | return; | ||
511 | |||
512 | /* Collect the flags */ | ||
513 | while (*++p && *p != ',') { | ||
514 | switch (TOLOWER(*p)) { | ||
515 | case 'a': | ||
516 | f |= US_FL_SANE_SENSE; | ||
517 | break; | ||
518 | case 'c': | ||
519 | f |= US_FL_FIX_CAPACITY; | ||
520 | break; | ||
521 | case 'h': | ||
522 | f |= US_FL_CAPACITY_HEURISTICS; | ||
523 | break; | ||
524 | case 'i': | ||
525 | f |= US_FL_IGNORE_DEVICE; | ||
526 | break; | ||
527 | case 'l': | ||
528 | f |= US_FL_NOT_LOCKABLE; | ||
529 | break; | ||
530 | case 'm': | ||
531 | f |= US_FL_MAX_SECTORS_64; | ||
532 | break; | ||
533 | case 'o': | ||
534 | f |= US_FL_CAPACITY_OK; | ||
535 | break; | ||
536 | case 'r': | ||
537 | f |= US_FL_IGNORE_RESIDUE; | ||
538 | break; | ||
539 | case 's': | ||
540 | f |= US_FL_SINGLE_LUN; | ||
541 | break; | ||
542 | case 'w': | ||
543 | f |= US_FL_NO_WP_DETECT; | ||
544 | break; | ||
545 | /* Ignore unrecognized flag characters */ | ||
546 | } | ||
547 | } | ||
548 | us->fflags = (us->fflags & ~mask) | f; | ||
549 | dev_info(&us->pusb_intf->dev, "Quirks match for " | ||
550 | "vid %04x pid %04x: %x\n", | ||
551 | vid, pid, f); | ||
474 | } | 552 | } |
475 | 553 | ||
476 | /* Find an unusual_dev descriptor (always succeeds in the current code) */ | 554 | /* Find an unusual_dev descriptor (always succeeds in the current code) */ |
@@ -497,6 +575,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id) | |||
497 | idesc->bInterfaceProtocol : | 575 | idesc->bInterfaceProtocol : |
498 | unusual_dev->useTransport; | 576 | unusual_dev->useTransport; |
499 | us->fflags = USB_US_ORIG_FLAGS(id->driver_info); | 577 | us->fflags = USB_US_ORIG_FLAGS(id->driver_info); |
578 | adjust_quirks(us); | ||
500 | 579 | ||
501 | if (us->fflags & US_FL_IGNORE_DEVICE) { | 580 | if (us->fflags & US_FL_IGNORE_DEVICE) { |
502 | printk(KERN_INFO USB_STORAGE "device ignored\n"); | 581 | printk(KERN_INFO USB_STORAGE "device ignored\n"); |
@@ -562,7 +641,7 @@ static int get_transport(struct us_data *us) | |||
562 | 641 | ||
563 | case US_PR_CBI: | 642 | case US_PR_CBI: |
564 | us->transport_name = "Control/Bulk/Interrupt"; | 643 | us->transport_name = "Control/Bulk/Interrupt"; |
565 | us->transport = usb_stor_CBI_transport; | 644 | us->transport = usb_stor_CB_transport; |
566 | us->transport_reset = usb_stor_CB_reset; | 645 | us->transport_reset = usb_stor_CB_reset; |
567 | us->max_lun = 7; | 646 | us->max_lun = 7; |
568 | break; | 647 | break; |
@@ -675,19 +754,19 @@ static int get_protocol(struct us_data *us) | |||
675 | 754 | ||
676 | case US_SC_8020: | 755 | case US_SC_8020: |
677 | us->protocol_name = "8020i"; | 756 | us->protocol_name = "8020i"; |
678 | us->proto_handler = usb_stor_ATAPI_command; | 757 | us->proto_handler = usb_stor_pad12_command; |
679 | us->max_lun = 0; | 758 | us->max_lun = 0; |
680 | break; | 759 | break; |
681 | 760 | ||
682 | case US_SC_QIC: | 761 | case US_SC_QIC: |
683 | us->protocol_name = "QIC-157"; | 762 | us->protocol_name = "QIC-157"; |
684 | us->proto_handler = usb_stor_qic157_command; | 763 | us->proto_handler = usb_stor_pad12_command; |
685 | us->max_lun = 0; | 764 | us->max_lun = 0; |
686 | break; | 765 | break; |
687 | 766 | ||
688 | case US_SC_8070: | 767 | case US_SC_8070: |
689 | us->protocol_name = "8070i"; | 768 | us->protocol_name = "8070i"; |
690 | us->proto_handler = usb_stor_ATAPI_command; | 769 | us->proto_handler = usb_stor_pad12_command; |
691 | us->max_lun = 0; | 770 | us->max_lun = 0; |
692 | break; | 771 | break; |
693 | 772 | ||
@@ -840,8 +919,6 @@ static void dissociate_dev(struct us_data *us) | |||
840 | { | 919 | { |
841 | US_DEBUGP("-- %s\n", __func__); | 920 | US_DEBUGP("-- %s\n", __func__); |
842 | 921 | ||
843 | kfree(us->sensebuf); | ||
844 | |||
845 | /* Free the device-related DMA-mapped buffers */ | 922 | /* Free the device-related DMA-mapped buffers */ |
846 | if (us->cr) | 923 | if (us->cr) |
847 | usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr, | 924 | usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr, |
@@ -1064,6 +1141,7 @@ static struct usb_driver usb_storage_driver = { | |||
1064 | static int __init usb_stor_init(void) | 1141 | static int __init usb_stor_init(void) |
1065 | { | 1142 | { |
1066 | int retval; | 1143 | int retval; |
1144 | |||
1067 | printk(KERN_INFO "Initializing USB Mass Storage driver...\n"); | 1145 | printk(KERN_INFO "Initializing USB Mass Storage driver...\n"); |
1068 | 1146 | ||
1069 | /* register the driver, return usb_register return code if error */ | 1147 | /* register the driver, return usb_register return code if error */ |