aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/storage
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r--drivers/usb/storage/Kconfig52
-rw-r--r--drivers/usb/storage/Makefile13
-rw-r--r--drivers/usb/storage/alauda.c125
-rw-r--r--drivers/usb/storage/cypress_atacb.c36
-rw-r--r--drivers/usb/storage/datafab.c77
-rw-r--r--drivers/usb/storage/debug.c36
-rw-r--r--drivers/usb/storage/debug.h23
-rw-r--r--drivers/usb/storage/ene_ub6250.c2420
-rw-r--r--drivers/usb/storage/freecom.c103
-rw-r--r--drivers/usb/storage/initializers.c10
-rw-r--r--drivers/usb/storage/isd200.c321
-rw-r--r--drivers/usb/storage/jumpshot.c87
-rw-r--r--drivers/usb/storage/karma.c24
-rw-r--r--drivers/usb/storage/libusual.c243
-rw-r--r--drivers/usb/storage/onetouch.c23
-rw-r--r--drivers/usb/storage/option_ms.c24
-rw-r--r--drivers/usb/storage/protocol.c95
-rw-r--r--drivers/usb/storage/realtek_cr.c1071
-rw-r--r--drivers/usb/storage/scsiglue.c156
-rw-r--r--drivers/usb/storage/sddr09.c170
-rw-r--r--drivers/usb/storage/sddr55.c104
-rw-r--r--drivers/usb/storage/shuttle_usbat.c141
-rw-r--r--drivers/usb/storage/sierra_ms.c51
-rw-r--r--drivers/usb/storage/transport.c244
-rw-r--r--drivers/usb/storage/transport.h39
-rw-r--r--drivers/usb/storage/uas-detect.h96
-rw-r--r--drivers/usb/storage/uas.c1059
-rw-r--r--drivers/usb/storage/unusual_cypress.h5
-rw-r--r--drivers/usb/storage/unusual_devs.h207
-rw-r--r--drivers/usb/storage/unusual_ene_ub6250.h26
-rw-r--r--drivers/usb/storage/unusual_realtek.h41
-rw-r--r--drivers/usb/storage/unusual_uas.h52
-rw-r--r--drivers/usb/storage/usb.c341
-rw-r--r--drivers/usb/storage/usb.h12
-rw-r--r--drivers/usb/storage/usual-tables.c35
35 files changed, 5820 insertions, 1742 deletions
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 49a489e0371..13b5bfbaf95 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -4,11 +4,10 @@
comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may"
comment "also be needed; see USB_STORAGE Help for more info"
- depends on USB
config USB_STORAGE
tristate "USB Mass Storage support"
- depends on USB && SCSI
+ depends on SCSI
---help---
Say Y here if you want to connect USB mass storage devices to your
computer's USB port. This is the driver you need for USB
@@ -19,7 +18,9 @@ config USB_STORAGE
This option depends on 'SCSI' support being enabled, but you
probably also need 'SCSI device support: SCSI disk support'
- (BLK_DEV_SD) for most USB storage devices.
+ (BLK_DEV_SD) for most USB storage devices. Some devices also
+ will require 'Probe all LUNs on each SCSI device'
+ (SCSI_MULTI_LUN).
To compile this driver as a module, choose M here: the
module will be called usb-storage.
@@ -31,6 +32,20 @@ config USB_STORAGE_DEBUG
Say Y here in order to have the USB Mass Storage code generate
verbose debugging messages.
+config USB_STORAGE_REALTEK
+ tristate "Realtek Card Reader support"
+ depends on USB_STORAGE
+ help
+ Say Y here to include additional code to support the power-saving function
+ for Realtek RTS51xx USB card readers.
+
+ If this driver is compiled as a module, it will be named ums-realtek.
+
+config REALTEK_AUTOPM
+ bool "Realtek Card Reader autosuspend support"
+ depends on USB_STORAGE_REALTEK && PM_RUNTIME
+ default y
+
config USB_STORAGE_DATAFAB
tristate "Datafab Compact Flash Reader support"
depends on USB_STORAGE
@@ -172,9 +187,24 @@ config USB_STORAGE_CYPRESS_ATACB
If this driver is compiled as a module, it will be named ums-cypress.
+config USB_STORAGE_ENE_UB6250
+ tristate "USB ENE card reader support"
+ depends on SCSI
+ depends on USB_STORAGE
+ ---help---
+ Say Y here if you wish to control a ENE SD/MS Card reader.
+ To use SM card, please build driver/staging/keucr/keucr.ko
+
+ This option depends on 'SCSI' support being enabled, but you
+ probably also need 'SCSI device support: SCSI disk support'
+ (BLK_DEV_SD) for most USB storage devices.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ums-eneub6250.
+
config USB_UAS
tristate "USB Attached SCSI"
- depends on USB && SCSI
+ depends on SCSI && USB_STORAGE
help
The USB Attached SCSI protocol is supported by some USB
storage devices. It permits higher performance by supporting
@@ -184,17 +214,3 @@ config USB_UAS
say 'Y' or 'M' here and the kernel will use the right driver.
If you compile this driver as a module, it will be named uas.
-
-config USB_LIBUSUAL
- bool "The shared table of common (or usual) storage devices"
- depends on USB
- help
- This module contains a table of common (or usual) devices
- for usb-storage and ub drivers, and allows to switch binding
- of these devices without rebuilding modules.
-
- Typical syntax of /etc/modprobe.conf is:
-
- options libusual bias="ub"
-
- If unsure, say N.
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index fcf14cdc4a0..4cd55481b30 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -12,24 +12,19 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o
usb-storage-y := scsiglue.o protocol.o transport.o usb.o
usb-storage-y += initializers.o sierra_ms.o option_ms.o
-
+usb-storage-y += usual-tables.o
usb-storage-$(CONFIG_USB_STORAGE_DEBUG) += debug.o
-ifeq ($(CONFIG_USB_LIBUSUAL),)
- usb-storage-y += usual-tables.o
-else
- obj-$(CONFIG_USB) += usb-libusual.o
- usb-libusual-y := libusual.o usual-tables.o
-endif
-
obj-$(CONFIG_USB_STORAGE_ALAUDA) += ums-alauda.o
obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o
obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o
+obj-$(CONFIG_USB_STORAGE_ENE_UB6250) += ums-eneub6250.o
obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o
obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o
obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += ums-jumpshot.o
obj-$(CONFIG_USB_STORAGE_KARMA) += ums-karma.o
obj-$(CONFIG_USB_STORAGE_ONETOUCH) += ums-onetouch.o
+obj-$(CONFIG_USB_STORAGE_REALTEK) += ums-realtek.o
obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o
obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o
obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o
@@ -37,11 +32,13 @@ obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o
ums-alauda-y := alauda.o
ums-cypress-y := cypress_atacb.o
ums-datafab-y := datafab.o
+ums-eneub6250-y := ene_ub6250.o
ums-freecom-y := freecom.o
ums-isd200-y := isd200.o
ums-jumpshot-y := jumpshot.o
ums-karma-y := karma.o
ums-onetouch-y := onetouch.o
+ums-realtek-y := realtek_cr.o
ums-sddr09-y := sddr09.o
ums-sddr55-y := sddr55.o
ums-usbat-y := shuttle_usbat.o
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
index 42d0eaed4a0..6636a583da1 100644
--- a/drivers/usb/storage/alauda.c
+++ b/drivers/usb/storage/alauda.c
@@ -137,9 +137,9 @@ static int init_alauda(struct us_data *us);
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
- .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ .driver_info = (flags) }
-struct usb_device_id alauda_usb_ids[] = {
+static struct usb_device_id alauda_usb_ids[] = {
# include "unusual_alauda.h"
{ } /* Terminating entry */
};
@@ -249,11 +249,7 @@ static void nand_init_ecc(void) {
/* compute 3-byte ecc on 256 bytes */
static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) {
int i, j, a;
- unsigned char par, bit, bits[8];
-
- par = 0;
- for (j = 0; j < 8; j++)
- bits[j] = 0;
+ unsigned char par = 0, bit, bits[8] = {0};
/* collect 16 checksum bits */
for (i = 0; i < 256; i++) {
@@ -326,8 +322,7 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data)
rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
command, 0xc0, 0, 1, data, 2);
- US_DEBUGP("alauda_get_media_status: Media status %02X %02X\n",
- data[0], data[1]);
+ usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
return rc;
}
@@ -402,7 +397,7 @@ static int alauda_init_media(struct us_data *us)
ready = 1;
}
- US_DEBUGP("alauda_init_media: We are ready for action!\n");
+ usb_stor_dbg(us, "We are ready for action!\n");
if (alauda_ack_media(us) != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -413,15 +408,15 @@ static int alauda_init_media(struct us_data *us)
return USB_STOR_TRANSPORT_ERROR;
if (data[0] != 0x14) {
- US_DEBUGP("alauda_init_media: Media not ready after ack\n");
+ usb_stor_dbg(us, "Media not ready after ack\n");
return USB_STOR_TRANSPORT_ERROR;
}
if (alauda_get_media_signature(us, data) != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("alauda_init_media: Media signature: %02X %02X %02X %02X\n",
- data[0], data[1], data[2], data[3]);
+ usb_stor_dbg(us, "Media signature: %02X %02X %02X %02X\n",
+ data[0], data[1], data[2], data[3]);
media_info = alauda_card_find_id(data[1]);
if (media_info == NULL) {
printk(KERN_WARNING
@@ -432,8 +427,8 @@ static int alauda_init_media(struct us_data *us)
}
MEDIA_INFO(us).capacity = 1 << media_info->chipshift;
- US_DEBUGP("Found media with capacity: %ldMB\n",
- MEDIA_INFO(us).capacity >> 20);
+ usb_stor_dbg(us, "Found media with capacity: %ldMB\n",
+ MEDIA_INFO(us).capacity >> 20);
MEDIA_INFO(us).pageshift = media_info->pageshift;
MEDIA_INFO(us).blockshift = media_info->blockshift;
@@ -472,7 +467,7 @@ static int alauda_check_media(struct us_data *us)
/* Check for no media or door open */
if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)
|| ((status[1] & 0x01) == 0)) {
- US_DEBUGP("alauda_check_media: No media, or door open\n");
+ usb_stor_dbg(us, "No media, or door open\n");
alauda_free_maps(&MEDIA_INFO(us));
info->sense_key = 0x02;
info->sense_asc = 0x3A;
@@ -482,7 +477,7 @@ static int alauda_check_media(struct us_data *us)
/* Check for media change */
if (status[0] & 0x08) {
- US_DEBUGP("alauda_check_media: Media change detected\n");
+ usb_stor_dbg(us, "Media change detected\n");
alauda_free_maps(&MEDIA_INFO(us));
alauda_init_media(us);
@@ -518,7 +513,7 @@ static int alauda_check_status2(struct us_data *us)
if (rc != USB_STOR_XFER_GOOD)
return rc;
- US_DEBUGP("alauda_check_status2: %02X %02X %02X\n", data[0], data[1], data[2]);
+ usb_stor_dbg(us, "%02X %02X %02X\n", data[0], data[1], data[2]);
if (data[0] & ALAUDA_STATUS_ERROR)
return USB_STOR_XFER_ERROR;
@@ -584,7 +579,7 @@ static int alauda_read_map(struct us_data *us, unsigned int zone)
goto error;
}
- US_DEBUGP("alauda_read_map: Mapping blocks for zone %d\n", zone);
+ usb_stor_dbg(us, "Mapping blocks for zone %d\n", zone);
/* 1024 PBA's per zone */
for (i = 0; i < zonesize; i++)
@@ -604,7 +599,7 @@ static int alauda_read_map(struct us_data *us, unsigned int zone)
if (data[j] != 0)
goto nonz;
pba_to_lba[i] = UNUSABLE;
- US_DEBUGP("alauda_read_map: PBA %d has no logical mapping\n", blocknum);
+ usb_stor_dbg(us, "PBA %d has no logical mapping\n", blocknum);
continue;
nonz:
@@ -617,19 +612,18 @@ static int alauda_read_map(struct us_data *us, unsigned int zone)
nonff:
/* normal PBAs start with six FFs */
if (j < 6) {
- US_DEBUGP("alauda_read_map: PBA %d has no logical mapping: "
- "reserved area = %02X%02X%02X%02X "
- "data status %02X block status %02X\n",
- blocknum, data[0], data[1], data[2], data[3],
- data[4], data[5]);
+ usb_stor_dbg(us, "PBA %d has no logical mapping: reserved area = %02X%02X%02X%02X data status %02X block status %02X\n",
+ blocknum,
+ data[0], data[1], data[2], data[3],
+ data[4], data[5]);
pba_to_lba[i] = UNUSABLE;
continue;
}
if ((data[6] >> 4) != 0x01) {
- US_DEBUGP("alauda_read_map: PBA %d has invalid address "
- "field %02X%02X/%02X%02X\n",
- blocknum, data[6], data[7], data[11], data[12]);
+ usb_stor_dbg(us, "PBA %d has invalid address field %02X%02X/%02X%02X\n",
+ blocknum, data[6], data[7],
+ data[11], data[12]);
pba_to_lba[i] = UNUSABLE;
continue;
}
@@ -711,7 +705,7 @@ static int alauda_erase_block(struct us_data *us, u16 pba)
};
unsigned char buf[2];
- US_DEBUGP("alauda_erase_block: Erasing PBA %d\n", pba);
+ usb_stor_dbg(us, "Erasing PBA %d\n", pba);
rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
command, 9, NULL);
@@ -723,8 +717,7 @@ static int alauda_erase_block(struct us_data *us, u16 pba)
if (rc != USB_STOR_XFER_GOOD)
return rc;
- US_DEBUGP("alauda_erase_block: Erase result: %02X %02X\n",
- buf[0], buf[1]);
+ usb_stor_dbg(us, "Erase result: %02X %02X\n", buf[0], buf[1]);
return rc;
}
@@ -741,8 +734,7 @@ static int alauda_read_block_raw(struct us_data *us, u16 pba,
PBA_ZONE(pba), 0, PBA_LO(pba) + page, pages, 0, MEDIA_PORT(us)
};
- US_DEBUGP("alauda_read_block: pba %d page %d count %d\n",
- pba, page, pages);
+ usb_stor_dbg(us, "pba %d page %d count %d\n", pba, page, pages);
rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
command, 9, NULL);
@@ -793,7 +785,7 @@ static int alauda_write_block(struct us_data *us, u16 pba, unsigned char *data)
PBA_ZONE(pba), 0, PBA_LO(pba), 32, 0, MEDIA_PORT(us)
};
- US_DEBUGP("alauda_write_block: pba %d\n", pba);
+ usb_stor_dbg(us, "pba %d\n", pba);
rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
command, 9, NULL);
@@ -866,14 +858,14 @@ static int alauda_write_lba(struct us_data *us, u16 lba,
cptr = bptr + pagesize;
nand_compute_ecc(bptr, ecc);
if (!nand_compare_ecc(cptr+13, ecc)) {
- US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n",
- i, pba);
+ usb_stor_dbg(us, "Warning: bad ecc in page %d- of pba %d\n",
+ i, pba);
nand_store_ecc(cptr+13, ecc);
}
nand_compute_ecc(bptr + (pagesize / 2), ecc);
if (!nand_compare_ecc(cptr+8, ecc)) {
- US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n",
- i, pba);
+ usb_stor_dbg(us, "Warning: bad ecc in page %d+ of pba %d\n",
+ i, pba);
nand_store_ecc(cptr+8, ecc);
}
cptr[6] = cptr[11] = MSB_of(lbap);
@@ -900,8 +892,7 @@ static int alauda_write_lba(struct us_data *us, u16 lba,
new_pba_offset = new_pba - (zone * zonesize);
MEDIA_INFO(us).pba_to_lba[zone][new_pba_offset] = lba;
MEDIA_INFO(us).lba_to_pba[zone][lba_offset] = new_pba;
- US_DEBUGP("alauda_write_lba: Remapped LBA %d to PBA %d\n",
- lba, new_pba);
+ usb_stor_dbg(us, "Remapped LBA %d to PBA %d\n", lba, new_pba);
if (pba != UNDEF) {
unsigned int pba_offset = pba - (zone * zonesize);
@@ -964,8 +955,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
/* Not overflowing capacity? */
if (lba >= max_lba) {
- US_DEBUGP("Error: Requested lba %u exceeds "
- "maximum %u\n", lba, max_lba);
+ usb_stor_dbg(us, "Error: Requested lba %u exceeds maximum %u\n",
+ lba, max_lba);
result = USB_STOR_TRANSPORT_ERROR;
break;
}
@@ -978,8 +969,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset];
if (pba == UNDEF) { /* this lba was never written */
- US_DEBUGP("Read %d zero pages (LBA %d) page %d\n",
- pages, lba, page);
+ usb_stor_dbg(us, "Read %d zero pages (LBA %d) page %d\n",
+ pages, lba, page);
/* This is not really an error. It just means
that the block has never been written.
@@ -988,9 +979,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
memset(buffer, 0, len);
} else {
- US_DEBUGP("Read %d pages, from PBA %d"
- " (LBA %d) page %d\n",
- pages, pba, lba, page);
+ usb_stor_dbg(us, "Read %d pages, from PBA %d (LBA %d) page %d\n",
+ pages, pba, lba, page);
result = alauda_read_block(us, pba, page, pages, buffer);
if (result != USB_STOR_TRANSPORT_GOOD)
@@ -1066,8 +1056,8 @@ static int alauda_write_data(struct us_data *us, unsigned long address,
/* Not overflowing capacity? */
if (lba >= max_lba) {
- US_DEBUGP("alauda_write_data: Requested lba %u exceeds "
- "maximum %u\n", lba, max_lba);
+ usb_stor_dbg(us, "Requested lba %u exceeds maximum %u\n",
+ lba, max_lba);
result = USB_STOR_TRANSPORT_ERROR;
break;
}
@@ -1122,11 +1112,9 @@ static int init_alauda(struct us_data *us)
nand_init_ecc();
us->extra = kzalloc(sizeof(struct alauda_info), GFP_NOIO);
- if (!us->extra) {
- US_DEBUGP("init_alauda: Gah! Can't allocate storage for"
- "alauda info struct!\n");
+ if (!us->extra)
return USB_STOR_TRANSPORT_ERROR;
- }
+
info = (struct alauda_info *) us->extra;
us->extra_destructor = alauda_info_destructor;
@@ -1147,15 +1135,14 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
};
if (srb->cmnd[0] == INQUIRY) {
- US_DEBUGP("alauda_transport: INQUIRY. "
- "Returning bogus response.\n");
+ usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
memcpy(ptr, inquiry_response, sizeof(inquiry_response));
fill_inquiry_response(us, ptr, 36);
return USB_STOR_TRANSPORT_GOOD;
}
if (srb->cmnd[0] == TEST_UNIT_READY) {
- US_DEBUGP("alauda_transport: TEST_UNIT_READY.\n");
+ usb_stor_dbg(us, "TEST_UNIT_READY\n");
return alauda_check_media(us);
}
@@ -1193,8 +1180,7 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
- US_DEBUGP("alauda_transport: READ_10: page %d pagect %d\n",
- page, pages);
+ usb_stor_dbg(us, "READ_10: page %d pagect %d\n", page, pages);
return alauda_read_data(us, page, pages);
}
@@ -1211,14 +1197,13 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
- US_DEBUGP("alauda_transport: WRITE_10: page %d pagect %d\n",
- page, pages);
+ usb_stor_dbg(us, "WRITE_10: page %d pagect %d\n", page, pages);
return alauda_write_data(us, page, pages);
}
if (srb->cmnd[0] == REQUEST_SENSE) {
- US_DEBUGP("alauda_transport: REQUEST_SENSE.\n");
+ usb_stor_dbg(us, "REQUEST_SENSE\n");
memset(ptr, 0, 18);
ptr[0] = 0xF0;
@@ -1237,8 +1222,8 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
return USB_STOR_TRANSPORT_GOOD;
}
- US_DEBUGP("alauda_transport: Gah! Unknown command: %d (0x%x)\n",
- srb->cmnd[0], srb->cmnd[0]);
+ usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
+ srb->cmnd[0], srb->cmnd[0]);
info->sense_key = 0x05;
info->sense_asc = 0x20;
info->sense_ascq = 0x00;
@@ -1276,17 +1261,7 @@ static struct usb_driver alauda_driver = {
.post_reset = usb_stor_post_reset,
.id_table = alauda_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
-static int __init alauda_init(void)
-{
- return usb_register(&alauda_driver);
-}
-
-static void __exit alauda_exit(void)
-{
- usb_deregister(&alauda_driver);
-}
-
-module_init(alauda_init);
-module_exit(alauda_exit);
+module_usb_driver(alauda_driver);
diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
index c8447182118..8514a2d82b7 100644
--- a/drivers/usb/storage/cypress_atacb.c
+++ b/drivers/usb/storage/cypress_atacb.c
@@ -41,9 +41,9 @@ MODULE_LICENSE("GPL");
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
- .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ .driver_info = (flags) }
-struct usb_device_id cypress_usb_ids[] = {
+static struct usb_device_id cypress_usb_ids[] = {
# include "unusual_cypress.h"
{ } /* Terminating entry */
};
@@ -159,7 +159,7 @@ static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
if (srb->result == SAM_STAT_CHECK_CONDITION &&
memcmp(srb->sense_buffer, usb_stor_sense_invalidCDB,
sizeof(usb_stor_sense_invalidCDB)) == 0) {
- US_DEBUGP("cypress atacb not supported ???\n");
+ usb_stor_dbg(us, "cypress atacb not supported ???\n");
goto end;
}
@@ -248,14 +248,26 @@ static int cypress_probe(struct usb_interface *intf,
{
struct us_data *us;
int result;
+ struct usb_device *device;
result = usb_stor_probe1(&us, intf, id,
(id - cypress_usb_ids) + cypress_unusual_dev_list);
if (result)
return result;
- us->protocol_name = "Transparent SCSI with Cypress ATACB";
- us->proto_handler = cypress_atacb_passthrough;
+ /* Among CY7C68300 chips, the A revision does not support Cypress ATACB
+ * Filter out this revision from EEPROM default descriptor values
+ */
+ device = interface_to_usbdev(intf);
+ if (device->descriptor.iManufacturer != 0x38 ||
+ device->descriptor.iProduct != 0x4e ||
+ device->descriptor.iSerialNumber != 0x64) {
+ us->protocol_name = "Transparent SCSI with Cypress ATACB";
+ us->proto_handler = cypress_atacb_passthrough;
+ } else {
+ us->protocol_name = "Transparent SCSI";
+ us->proto_handler = usb_stor_transparent_scsi_command;
+ }
result = usb_stor_probe2(us);
return result;
@@ -272,17 +284,7 @@ static struct usb_driver cypress_driver = {
.post_reset = usb_stor_post_reset,
.id_table = cypress_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
-static int __init cypress_init(void)
-{
- return usb_register(&cypress_driver);
-}
-
-static void __exit cypress_exit(void)
-{
- usb_deregister(&cypress_driver);
-}
-
-module_init(cypress_init);
-module_exit(cypress_exit);
+module_usb_driver(cypress_driver);
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index ded836b02d7..7b17c216981 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -86,9 +86,9 @@ static int datafab_determine_lun(struct us_data *us,
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
- .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ .driver_info = (flags) }
-struct usb_device_id datafab_usb_ids[] = {
+static struct usb_device_id datafab_usb_ids[] = {
# include "unusual_datafab.h"
{ } /* Terminating entry */
};
@@ -123,7 +123,7 @@ datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) {
if (len == 0)
return USB_STOR_XFER_GOOD;
- US_DEBUGP("datafab_bulk_read: len = %d\n", len);
+ usb_stor_dbg(us, "len = %d\n", len);
return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
data, len, NULL);
}
@@ -134,7 +134,7 @@ datafab_bulk_write(struct us_data *us, unsigned char *data, unsigned int len) {
if (len == 0)
return USB_STOR_XFER_GOOD;
- US_DEBUGP("datafab_bulk_write: len = %d\n", len);
+ usb_stor_dbg(us, "len = %d\n", len);
return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
data, len, NULL);
}
@@ -300,9 +300,8 @@ static int datafab_write_data(struct us_data *us,
goto leave;
if (reply[0] != 0x50 && reply[1] != 0) {
- US_DEBUGP("datafab_write_data: Gah! "
- "write return code: %02x %02x\n",
- reply[0], reply[1]);
+ usb_stor_dbg(us, "Gah! write return code: %02x %02x\n",
+ reply[0], reply[1]);
result = USB_STOR_TRANSPORT_ERROR;
goto leave;
}
@@ -342,7 +341,7 @@ static int datafab_determine_lun(struct us_data *us,
if (!buf)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("datafab_determine_lun: locating...\n");
+ usb_stor_dbg(us, "locating...\n");
// we'll try 3 times before giving up...
//
@@ -474,16 +473,16 @@ static int datafab_handle_mode_sense(struct us_data *us,
switch (pc) {
case 0x0:
- US_DEBUGP("datafab_handle_mode_sense: Current values\n");
+ usb_stor_dbg(us, "Current values\n");
break;
case 0x1:
- US_DEBUGP("datafab_handle_mode_sense: Changeable values\n");
+ usb_stor_dbg(us, "Changeable values\n");
break;
case 0x2:
- US_DEBUGP("datafab_handle_mode_sense: Default values\n");
+ usb_stor_dbg(us, "Default values\n");
break;
case 0x3:
- US_DEBUGP("datafab_handle_mode_sense: Saves values\n");
+ usb_stor_dbg(us, "Saves values\n");
break;
}
@@ -566,11 +565,9 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
if (!us->extra) {
us->extra = kzalloc(sizeof(struct datafab_info), GFP_NOIO);
- if (!us->extra) {
- US_DEBUGP("datafab_transport: Gah! "
- "Can't allocate storage for Datafab info struct!\n");
+ if (!us->extra)
return USB_STOR_TRANSPORT_ERROR;
- }
+
us->extra_destructor = datafab_info_destructor;
((struct datafab_info *)us->extra)->lun = -1;
}
@@ -578,7 +575,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
info = (struct datafab_info *) (us->extra);
if (srb->cmnd[0] == INQUIRY) {
- US_DEBUGP("datafab_transport: INQUIRY. Returning bogus response");
+ usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
memcpy(ptr, inquiry_reply, sizeof(inquiry_reply));
fill_inquiry_response(us, ptr, 36);
return USB_STOR_TRANSPORT_GOOD;
@@ -590,8 +587,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("datafab_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
- info->sectors, info->ssize);
+ usb_stor_dbg(us, "READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
+ info->sectors, info->ssize);
// build the reply
// we need the last sector, not the number of sectors
@@ -603,7 +600,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
}
if (srb->cmnd[0] == MODE_SELECT_10) {
- US_DEBUGP("datafab_transport: Gah! MODE_SELECT_10.\n");
+ usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -615,7 +612,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
- US_DEBUGP("datafab_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "READ_10: read block 0x%04lx count %ld\n",
+ block, blocks);
return datafab_read_data(us, info, block, blocks);
}
@@ -628,7 +626,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
- US_DEBUGP("datafab_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "READ_12: read block 0x%04lx count %ld\n",
+ block, blocks);
return datafab_read_data(us, info, block, blocks);
}
@@ -638,7 +637,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
- US_DEBUGP("datafab_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "WRITE_10: write block 0x%04lx count %ld\n",
+ block, blocks);
return datafab_write_data(us, info, block, blocks);
}
@@ -651,17 +651,18 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
- US_DEBUGP("datafab_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "WRITE_12: write block 0x%04lx count %ld\n",
+ block, blocks);
return datafab_write_data(us, info, block, blocks);
}
if (srb->cmnd[0] == TEST_UNIT_READY) {
- US_DEBUGP("datafab_transport: TEST_UNIT_READY.\n");
+ usb_stor_dbg(us, "TEST_UNIT_READY\n");
return datafab_id_device(us, info);
}
if (srb->cmnd[0] == REQUEST_SENSE) {
- US_DEBUGP("datafab_transport: REQUEST_SENSE. Returning faked response\n");
+ usb_stor_dbg(us, "REQUEST_SENSE - Returning faked response\n");
// this response is pretty bogus right now. eventually if necessary
// we can set the correct sense data. so far though it hasn't been
@@ -679,12 +680,12 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
}
if (srb->cmnd[0] == MODE_SENSE) {
- US_DEBUGP("datafab_transport: MODE_SENSE_6 detected\n");
+ usb_stor_dbg(us, "MODE_SENSE_6 detected\n");
return datafab_handle_mode_sense(us, srb, 1);
}
if (srb->cmnd[0] == MODE_SENSE_10) {
- US_DEBUGP("datafab_transport: MODE_SENSE_10 detected\n");
+ usb_stor_dbg(us, "MODE_SENSE_10 detected\n");
return datafab_handle_mode_sense(us, srb, 0);
}
@@ -698,7 +699,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
if (srb->cmnd[0] == START_STOP) {
/* this is used by sd.c'check_scsidisk_media_change to detect
media change */
- US_DEBUGP("datafab_transport: START_STOP.\n");
+ usb_stor_dbg(us, "START_STOP\n");
/* the first datafab_id_device after a media change returns
an error (determined experimentally) */
rc = datafab_id_device(us, info);
@@ -712,8 +713,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
return rc;
}
- US_DEBUGP("datafab_transport: Gah! Unknown command: %d (0x%x)\n",
- srb->cmnd[0], srb->cmnd[0]);
+ usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
+ srb->cmnd[0], srb->cmnd[0]);
info->sense_key = 0x05;
info->sense_asc = 0x20;
info->sense_ascq = 0x00;
@@ -751,17 +752,7 @@ static struct usb_driver datafab_driver = {
.post_reset = usb_stor_post_reset,
.id_table = datafab_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
-static int __init datafab_init(void)
-{
- return usb_register(&datafab_driver);
-}
-
-static void __exit datafab_exit(void)
-{
- usb_deregister(&datafab_driver);
-}
-
-module_init(datafab_init);
-module_exit(datafab_exit);
+module_usb_driver(datafab_driver);
diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
index a2b5526c9fa..e08f64780e3 100644
--- a/drivers/usb/storage/debug.c
+++ b/drivers/usb/storage/debug.c
@@ -42,16 +42,19 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/device.h>
#include <linux/cdrom.h>
+#include <linux/export.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_dbg.h>
+#include "usb.h"
#include "debug.h"
#include "scsi.h"
-void usb_stor_show_command(struct scsi_cmnd *srb)
+void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb)
{
char *what = NULL;
int i;
@@ -149,18 +152,18 @@ void usb_stor_show_command(struct scsi_cmnd *srb)
case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
default: what = "(unknown command)"; break;
}
- US_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len);
- US_DEBUGP("");
+ usb_stor_dbg(us, "Command %s (%d bytes)\n", what, srb->cmd_len);
+ usb_stor_dbg(us, "bytes: ");
for (i = 0; i < srb->cmd_len && i < 16; i++)
US_DEBUGPX(" %02x", srb->cmnd[i]);
US_DEBUGPX("\n");
}
-void usb_stor_show_sense(
- unsigned char key,
- unsigned char asc,
- unsigned char ascq) {
-
+void usb_stor_show_sense(const struct us_data *us,
+ unsigned char key,
+ unsigned char asc,
+ unsigned char ascq)
+{
const char *what, *keystr;
keystr = scsi_sense_key_string(key);
@@ -171,7 +174,22 @@ void usb_stor_show_sense(
if (what == NULL)
what = "(unknown ASC/ASCQ)";
- US_DEBUGP("%s: ", keystr);
+ usb_stor_dbg(us, "%s: ", keystr);
US_DEBUGPX(what, ascq);
US_DEBUGPX("\n");
}
+
+int usb_stor_dbg(const struct us_data *us, const char *fmt, ...)
+{
+ va_list args;
+ int r;
+
+ va_start(args, fmt);
+
+ r = dev_vprintk_emit(7, &us->pusb_dev->dev, fmt, args);
+
+ va_end(args);
+
+ return r;
+}
+EXPORT_SYMBOL_GPL(usb_stor_dbg);
diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
index dbb985d5242..b1273f03e22 100644
--- a/drivers/usb/storage/debug.h
+++ b/drivers/usb/storage/debug.h
@@ -47,15 +47,22 @@
#define USB_STORAGE "usb-storage: "
#ifdef CONFIG_USB_STORAGE_DEBUG
-void usb_stor_show_command(struct scsi_cmnd *srb);
-void usb_stor_show_sense( unsigned char key,
- unsigned char asc, unsigned char ascq );
-#define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE x )
-#define US_DEBUGPX(x...) printk( x )
-#define US_DEBUG(x) x
+void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb);
+void usb_stor_show_sense(const struct us_data *us, unsigned char key,
+ unsigned char asc, unsigned char ascq);
+__printf(2, 3) int usb_stor_dbg(const struct us_data *us,
+ const char *fmt, ...);
+
+#define US_DEBUGPX(fmt, ...) printk(fmt, ##__VA_ARGS__)
+#define US_DEBUG(x) x
#else
-#define US_DEBUGP(x...)
-#define US_DEBUGPX(x...)
+__printf(2, 3)
+static inline int _usb_stor_dbg(const struct us_data *us,
+ const char *fmt, ...) {return 1;}
+#define usb_stor_dbg(us, fmt, ...) \
+ do { if (0) _usb_stor_dbg(us, fmt, ##__VA_ARGS__); } while (0)
+#define US_DEBUGPX(fmt, ...) \
+ do { if (0) printk(fmt, ##__VA_ARGS__); } while (0)
#define US_DEBUG(x)
#endif
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
new file mode 100644
index 00000000000..ef6efb55dc3
--- /dev/null
+++ b/drivers/usb/storage/ene_ub6250.c
@@ -0,0 +1,2420 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
+#include <linux/firmware.h>
+
+#include "usb.h"
+#include "transport.h"
+#include "protocol.h"
+#include "debug.h"
+
+#define SD_INIT1_FIRMWARE "ene-ub6250/sd_init1.bin"
+#define SD_INIT2_FIRMWARE "ene-ub6250/sd_init2.bin"
+#define SD_RW_FIRMWARE "ene-ub6250/sd_rdwr.bin"
+#define MS_INIT_FIRMWARE "ene-ub6250/ms_init.bin"
+#define MSP_RW_FIRMWARE "ene-ub6250/msp_rdwr.bin"
+#define MS_RW_FIRMWARE "ene-ub6250/ms_rdwr.bin"
+
+MODULE_DESCRIPTION("Driver for ENE UB6250 reader");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(SD_INIT1_FIRMWARE);
+MODULE_FIRMWARE(SD_INIT2_FIRMWARE);
+MODULE_FIRMWARE(SD_RW_FIRMWARE);
+MODULE_FIRMWARE(MS_INIT_FIRMWARE);
+MODULE_FIRMWARE(MSP_RW_FIRMWARE);
+MODULE_FIRMWARE(MS_RW_FIRMWARE);
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+ vendorName, productName, useProtocol, useTransport, \
+ initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+ .driver_info = (flags)}
+
+static struct usb_device_id ene_ub6250_usb_ids[] = {
+# include "unusual_ene_ub6250.h"
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, ene_ub6250_usb_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+ vendor_name, product_name, use_protocol, use_transport, \
+ init_function, Flags) \
+{ \
+ .vendorName = vendor_name, \
+ .productName = product_name, \
+ .useProtocol = use_protocol, \
+ .useTransport = use_transport, \
+ .initFunction = init_function, \
+}
+
+static struct us_unusual_dev ene_ub6250_unusual_dev_list[] = {
+# include "unusual_ene_ub6250.h"
+ { } /* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
+
+
+/* ENE bin code len */
+#define ENE_BIN_CODE_LEN 0x800
+/* EnE HW Register */
+#define REG_CARD_STATUS 0xFF83
+#define REG_HW_TRAP1 0xFF89
+
+/* SRB Status */
+#define SS_SUCCESS 0x00 /* No Sense */
+#define SS_NOT_READY 0x02
+#define SS_MEDIUM_ERR 0x03
+#define SS_HW_ERR 0x04
+#define SS_ILLEGAL_REQUEST 0x05
+#define SS_UNIT_ATTENTION 0x06
+
+/* ENE Load FW Pattern */
+#define SD_INIT1_PATTERN 1
+#define SD_INIT2_PATTERN 2
+#define SD_RW_PATTERN 3
+#define MS_INIT_PATTERN 4
+#define MSP_RW_PATTERN 5
+#define MS_RW_PATTERN 6
+#define SM_INIT_PATTERN 7
+#define SM_RW_PATTERN 8
+
+#define FDIR_WRITE 0
+#define FDIR_READ 1
+
+/* For MS Card */
+
+/* Status Register 1 */
+#define MS_REG_ST1_MB 0x80 /* media busy */
+#define MS_REG_ST1_FB1 0x40 /* flush busy 1 */
+#define MS_REG_ST1_DTER 0x20 /* error on data(corrected) */
+#define MS_REG_ST1_UCDT 0x10 /* unable to correct data */
+#define MS_REG_ST1_EXER 0x08 /* error on extra(corrected) */
+#define MS_REG_ST1_UCEX 0x04 /* unable to correct extra */
+#define MS_REG_ST1_FGER 0x02 /* error on overwrite flag(corrected) */
+#define MS_REG_ST1_UCFG 0x01 /* unable to correct overwrite flag */
+#define MS_REG_ST1_DEFAULT (MS_REG_ST1_MB | MS_REG_ST1_FB1 | MS_REG_ST1_DTER | MS_REG_ST1_UCDT | MS_REG_ST1_EXER | MS_REG_ST1_UCEX | MS_REG_ST1_FGER | MS_REG_ST1_UCFG)
+
+/* Overwrite Area */
+#define MS_REG_OVR_BKST 0x80 /* block status */
+#define MS_REG_OVR_BKST_OK MS_REG_OVR_BKST /* OK */
+#define MS_REG_OVR_BKST_NG 0x00 /* NG */
+#define MS_REG_OVR_PGST0 0x40 /* page status */
+#define MS_REG_OVR_PGST1 0x20
+#define MS_REG_OVR_PGST_MASK (MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1)
+#define MS_REG_OVR_PGST_OK (MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1) /* OK */
+#define MS_REG_OVR_PGST_NG MS_REG_OVR_PGST1 /* NG */
+#define MS_REG_OVR_PGST_DATA_ERROR 0x00 /* data error */
+#define MS_REG_OVR_UDST 0x10 /* update status */
+#define MS_REG_OVR_UDST_UPDATING 0x00 /* updating */
+#define MS_REG_OVR_UDST_NO_UPDATE MS_REG_OVR_UDST
+#define MS_REG_OVR_RESERVED 0x08
+#define MS_REG_OVR_DEFAULT (MS_REG_OVR_BKST_OK | MS_REG_OVR_PGST_OK | MS_REG_OVR_UDST_NO_UPDATE | MS_REG_OVR_RESERVED)
+
+/* Management Flag */
+#define MS_REG_MNG_SCMS0 0x20 /* serial copy management system */
+#define MS_REG_MNG_SCMS1 0x10
+#define MS_REG_MNG_SCMS_MASK (MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1)
+#define MS_REG_MNG_SCMS_COPY_OK (MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1)
+#define MS_REG_MNG_SCMS_ONE_COPY MS_REG_MNG_SCMS1
+#define MS_REG_MNG_SCMS_NO_COPY 0x00
+#define MS_REG_MNG_ATFLG 0x08 /* address transfer table flag */
+#define MS_REG_MNG_ATFLG_OTHER MS_REG_MNG_ATFLG /* other */
+#define MS_REG_MNG_ATFLG_ATTBL 0x00 /* address transfer table */
+#define MS_REG_MNG_SYSFLG 0x04 /* system flag */
+#define MS_REG_MNG_SYSFLG_USER MS_REG_MNG_SYSFLG /* user block */
+#define MS_REG_MNG_SYSFLG_BOOT 0x00 /* system block */
+#define MS_REG_MNG_RESERVED 0xc3
+#define MS_REG_MNG_DEFAULT (MS_REG_MNG_SCMS_COPY_OK | MS_REG_MNG_ATFLG_OTHER | MS_REG_MNG_SYSFLG_USER | MS_REG_MNG_RESERVED)
+
+
+#define MS_MAX_PAGES_PER_BLOCK 32
+#define MS_MAX_INITIAL_ERROR_BLOCKS 10
+#define MS_LIB_BITS_PER_BYTE 8
+
+#define MS_SYSINF_FORMAT_FAT 1
+#define MS_SYSINF_USAGE_GENERAL 0
+
+#define MS_SYSINF_MSCLASS_TYPE_1 1
+#define MS_SYSINF_PAGE_SIZE MS_BYTES_PER_PAGE /* fixed */
+
+#define MS_SYSINF_CARDTYPE_RDONLY 1
+#define MS_SYSINF_CARDTYPE_RDWR 2
+#define MS_SYSINF_CARDTYPE_HYBRID 3
+#define MS_SYSINF_SECURITY 0x01
+#define MS_SYSINF_SECURITY_NO_SUPPORT MS_SYSINF_SECURITY
+#define MS_SYSINF_SECURITY_SUPPORT 0
+
+#define MS_SYSINF_RESERVED1 1
+#define MS_SYSINF_RESERVED2 1
+
+#define MS_SYSENT_TYPE_INVALID_BLOCK 0x01
+#define MS_SYSENT_TYPE_CIS_IDI 0x0a /* CIS/IDI */
+
+#define SIZE_OF_KIRO 1024
+#define BYTE_MASK 0xff
+
+/* ms error code */
+#define MS_STATUS_WRITE_PROTECT 0x0106
+#define MS_STATUS_SUCCESS 0x0000
+#define MS_ERROR_FLASH_READ 0x8003
+#define MS_ERROR_FLASH_ERASE 0x8005
+#define MS_LB_ERROR 0xfff0
+#define MS_LB_BOOT_BLOCK 0xfff1
+#define MS_LB_INITIAL_ERROR 0xfff2
+#define MS_STATUS_SUCCESS_WITH_ECC 0xfff3
+#define MS_LB_ACQUIRED_ERROR 0xfff4
+#define MS_LB_NOT_USED_ERASED 0xfff5
+#define MS_NOCARD_ERROR 0xfff8
+#define MS_NO_MEMORY_ERROR 0xfff9
+#define MS_STATUS_INT_ERROR 0xfffa
+#define MS_STATUS_ERROR 0xfffe
+#define MS_LB_NOT_USED 0xffff
+
+#define MS_REG_MNG_SYSFLG 0x04 /* system flag */
+#define MS_REG_MNG_SYSFLG_USER MS_REG_MNG_SYSFLG /* user block */
+
+#define MS_BOOT_BLOCK_ID 0x0001
+#define MS_BOOT_BLOCK_FORMAT_VERSION 0x0100
+#define MS_BOOT_BLOCK_DATA_ENTRIES 2
+
+#define MS_NUMBER_OF_SYSTEM_ENTRY 4
+#define MS_NUMBER_OF_BOOT_BLOCK 2
+#define MS_BYTES_PER_PAGE 512
+#define MS_LOGICAL_BLOCKS_PER_SEGMENT 496
+#define MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT 494
+
+#define MS_PHYSICAL_BLOCKS_PER_SEGMENT 0x200 /* 512 */
+#define MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK 0x1ff
+
+/* overwrite area */
+#define MS_REG_OVR_BKST 0x80 /* block status */
+#define MS_REG_OVR_BKST_OK MS_REG_OVR_BKST /* OK */
+#define MS_REG_OVR_BKST_NG 0x00 /* NG */
+
+/* Status Register 1 */
+#define MS_REG_ST1_DTER 0x20 /* error on data(corrected) */
+#define MS_REG_ST1_EXER 0x08 /* error on extra(corrected) */
+#define MS_REG_ST1_FGER 0x02 /* error on overwrite flag(corrected) */
+
+/* MemoryStick Register */
+/* Status Register 0 */
+#define MS_REG_ST0_WP 0x01 /* write protected */
+#define MS_REG_ST0_WP_ON MS_REG_ST0_WP
+
+#define MS_LIB_CTRL_RDONLY 0
+#define MS_LIB_CTRL_WRPROTECT 1
+
+/*dphy->log table */
+#define ms_libconv_to_logical(pdx, PhyBlock) (((PhyBlock) >= (pdx)->MS_Lib.NumberOfPhyBlock) ? MS_STATUS_ERROR : (pdx)->MS_Lib.Phy2LogMap[PhyBlock])
+#define ms_libconv_to_physical(pdx, LogBlock) (((LogBlock) >= (pdx)->MS_Lib.NumberOfLogBlock) ? MS_STATUS_ERROR : (pdx)->MS_Lib.Log2PhyMap[LogBlock])
+
+#define ms_lib_ctrl_set(pdx, Flag) ((pdx)->MS_Lib.flags |= (1 << (Flag)))
+#define ms_lib_ctrl_reset(pdx, Flag) ((pdx)->MS_Lib.flags &= ~(1 << (Flag)))
+#define ms_lib_ctrl_check(pdx, Flag) ((pdx)->MS_Lib.flags & (1 << (Flag)))
+
+#define ms_lib_iswritable(pdx) ((ms_lib_ctrl_check((pdx), MS_LIB_CTRL_RDONLY) == 0) && (ms_lib_ctrl_check(pdx, MS_LIB_CTRL_WRPROTECT) == 0))
+#define ms_lib_clear_pagemap(pdx) memset((pdx)->MS_Lib.pagemap, 0, sizeof((pdx)->MS_Lib.pagemap))
+#define memstick_logaddr(logadr1, logadr0) ((((u16)(logadr1)) << 8) | (logadr0))
+
+
+struct SD_STATUS {
+ u8 Insert:1;
+ u8 Ready:1;
+ u8 MediaChange:1;
+ u8 IsMMC:1;
+ u8 HiCapacity:1;
+ u8 HiSpeed:1;
+ u8 WtP:1;
+ u8 Reserved:1;
+};
+
+struct MS_STATUS {
+ u8 Insert:1;
+ u8 Ready:1;
+ u8 MediaChange:1;
+ u8 IsMSPro:1;
+ u8 IsMSPHG:1;
+ u8 Reserved1:1;
+ u8 WtP:1;
+ u8 Reserved2:1;
+};
+
+struct SM_STATUS {
+ u8 Insert:1;
+ u8 Ready:1;
+ u8 MediaChange:1;
+ u8 Reserved:3;
+ u8 WtP:1;
+ u8 IsMS:1;
+};
+
+struct ms_bootblock_cis {
+ u8 bCistplDEVICE[6]; /* 0 */
+ u8 bCistplDEVICE0C[6]; /* 6 */
+ u8 bCistplJEDECC[4]; /* 12 */
+ u8 bCistplMANFID[6]; /* 16 */
+ u8 bCistplVER1[32]; /* 22 */
+ u8 bCistplFUNCID[4]; /* 54 */
+ u8 bCistplFUNCE0[4]; /* 58 */
+ u8 bCistplFUNCE1[5]; /* 62 */
+ u8 bCistplCONF[7]; /* 67 */
+ u8 bCistplCFTBLENT0[10];/* 74 */
+ u8 bCistplCFTBLENT1[8]; /* 84 */
+ u8 bCistplCFTBLENT2[12];/* 92 */
+ u8 bCistplCFTBLENT3[8]; /* 104 */
+ u8 bCistplCFTBLENT4[17];/* 112 */
+ u8 bCistplCFTBLENT5[8]; /* 129 */
+ u8 bCistplCFTBLENT6[17];/* 137 */
+ u8 bCistplCFTBLENT7[8]; /* 154 */
+ u8 bCistplNOLINK[3]; /* 162 */
+} ;
+
+struct ms_bootblock_idi {
+#define MS_IDI_GENERAL_CONF 0x848A
+ u16 wIDIgeneralConfiguration; /* 0 */
+ u16 wIDInumberOfCylinder; /* 1 */
+ u16 wIDIreserved0; /* 2 */
+ u16 wIDInumberOfHead; /* 3 */
+ u16 wIDIbytesPerTrack; /* 4 */
+ u16 wIDIbytesPerSector; /* 5 */
+ u16 wIDIsectorsPerTrack; /* 6 */
+ u16 wIDItotalSectors[2]; /* 7-8 high,low */
+ u16 wIDIreserved1[11]; /* 9-19 */
+ u16 wIDIbufferType; /* 20 */
+ u16 wIDIbufferSize; /* 21 */
+ u16 wIDIlongCmdECC; /* 22 */
+ u16 wIDIfirmVersion[4]; /* 23-26 */
+ u16 wIDImodelName[20]; /* 27-46 */
+ u16 wIDIreserved2; /* 47 */
+ u16 wIDIlongWordSupported; /* 48 */
+ u16 wIDIdmaSupported; /* 49 */
+ u16 wIDIreserved3; /* 50 */
+ u16 wIDIpioTiming; /* 51 */
+ u16 wIDIdmaTiming; /* 52 */
+ u16 wIDItransferParameter; /* 53 */
+ u16 wIDIformattedCylinder; /* 54 */
+ u16 wIDIformattedHead; /* 55 */
+ u16 wIDIformattedSectorsPerTrack;/* 56 */
+ u16 wIDIformattedTotalSectors[2];/* 57-58 */
+ u16 wIDImultiSector; /* 59 */
+ u16 wIDIlbaSectors[2]; /* 60-61 */
+ u16 wIDIsingleWordDMA; /* 62 */
+ u16 wIDImultiWordDMA; /* 63 */
+ u16 wIDIreserved4[192]; /* 64-255 */
+};
+
+struct ms_bootblock_sysent_rec {
+ u32 dwStart;
+ u32 dwSize;
+ u8 bType;
+ u8 bReserved[3];
+};
+
+struct ms_bootblock_sysent {
+ struct ms_bootblock_sysent_rec entry[MS_NUMBER_OF_SYSTEM_ENTRY];
+};
+
+struct ms_bootblock_sysinf {
+ u8 bMsClass; /* must be 1 */
+ u8 bCardType; /* see below */
+ u16 wBlockSize; /* n KB */
+ u16 wBlockNumber; /* number of physical block */
+ u16 wTotalBlockNumber; /* number of logical block */
+ u16 wPageSize; /* must be 0x200 */
+ u8 bExtraSize; /* 0x10 */
+ u8 bSecuritySupport;
+ u8 bAssemblyDate[8];
+ u8 bFactoryArea[4];
+ u8 bAssemblyMakerCode;
+ u8 bAssemblyMachineCode[3];
+ u16 wMemoryMakerCode;
+ u16 wMemoryDeviceCode;
+ u16 wMemorySize;
+ u8 bReserved1;
+ u8 bReserved2;
+ u8 bVCC;
+ u8 bVPP;
+ u16 wControllerChipNumber;
+ u16 wControllerFunction; /* New MS */
+ u8 bReserved3[9]; /* New MS */
+ u8 bParallelSupport; /* New MS */
+ u16 wFormatValue; /* New MS */
+ u8 bFormatType;
+ u8 bUsage;
+ u8 bDeviceType;
+ u8 bReserved4[22];
+ u8 bFUValue3;
+ u8 bFUValue4;
+ u8 bReserved5[15];
+};
+
+struct ms_bootblock_header {
+ u16 wBlockID;
+ u16 wFormatVersion;
+ u8 bReserved1[184];
+ u8 bNumberOfDataEntry;
+ u8 bReserved2[179];
+};
+
+struct ms_bootblock_page0 {
+ struct ms_bootblock_header header;
+ struct ms_bootblock_sysent sysent;
+ struct ms_bootblock_sysinf sysinf;
+};
+
+struct ms_bootblock_cis_idi {
+ union {
+ struct ms_bootblock_cis cis;
+ u8 dmy[256];
+ } cis;
+
+ union {
+ struct ms_bootblock_idi idi;
+ u8 dmy[256];
+ } idi;
+
+};
+
+/* ENE MS Lib struct */
+struct ms_lib_type_extdat {
+ u8 reserved;
+ u8 intr;
+ u8 status0;
+ u8 status1;
+ u8 ovrflg;
+ u8 mngflg;
+ u16 logadr;
+};
+
+struct ms_lib_ctrl {
+ u32 flags;
+ u32 BytesPerSector;
+ u32 NumberOfCylinder;
+ u32 SectorsPerCylinder;
+ u16 cardType; /* R/W, RO, Hybrid */
+ u16 blockSize;
+ u16 PagesPerBlock;
+ u16 NumberOfPhyBlock;
+ u16 NumberOfLogBlock;
+ u16 NumberOfSegment;
+ u16 *Phy2LogMap; /* phy2log table */
+ u16 *Log2PhyMap; /* log2phy table */
+ u16 wrtblk;
+ unsigned char *pagemap[(MS_MAX_PAGES_PER_BLOCK + (MS_LIB_BITS_PER_BYTE-1)) / MS_LIB_BITS_PER_BYTE];
+ unsigned char *blkpag;
+ struct ms_lib_type_extdat *blkext;
+ unsigned char copybuf[512];
+};
+
+
+/* SD Block Length */
+/* 2^9 = 512 Bytes, The HW maximum read/write data length */
+#define SD_BLOCK_LEN 9
+
+struct ene_ub6250_info {
+ /* for 6250 code */
+ struct SD_STATUS SD_Status;
+ struct MS_STATUS MS_Status;
+ struct SM_STATUS SM_Status;
+
+ /* ----- SD Control Data ---------------- */
+ /*SD_REGISTER SD_Regs; */
+ u16 SD_Block_Mult;
+ u8 SD_READ_BL_LEN;
+ u16 SD_C_SIZE;
+ u8 SD_C_SIZE_MULT;
+
+ /* SD/MMC New spec. */
+ u8 SD_SPEC_VER;
+ u8 SD_CSD_VER;
+ u8 SD20_HIGH_CAPACITY;
+ u32 HC_C_SIZE;
+ u8 MMC_SPEC_VER;
+ u8 MMC_BusWidth;
+ u8 MMC_HIGH_CAPACITY;
+
+ /*----- MS Control Data ---------------- */
+ bool MS_SWWP;
+ u32 MSP_TotalBlock;
+ struct ms_lib_ctrl MS_Lib;
+ bool MS_IsRWPage;
+ u16 MS_Model;
+
+ /*----- SM Control Data ---------------- */
+ u8 SM_DeviceID;
+ u8 SM_CardID;
+
+ unsigned char *testbuf;
+ u8 BIN_FLAG;
+ u32 bl_num;
+ int SrbStatus;
+
+ /*------Power Managerment ---------------*/
+ bool Power_IsResum;
+};
+
+static int ene_sd_init(struct us_data *us);
+static int ene_ms_init(struct us_data *us);
+static int ene_load_bincode(struct us_data *us, unsigned char flag);
+
+static void ene_ub6250_info_destructor(void *extra)
+{
+ if (!extra)
+ return;
+}
+
+static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
+{
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
+
+ int result;
+ unsigned int residue;
+ unsigned int cswlen = 0, partial = 0;
+ unsigned int transfer_length = bcb->DataTransferLength;
+
+ /* usb_stor_dbg(us, "transport --- ene_send_scsi_cmd\n"); */
+ /* send cmd to out endpoint */
+ result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ bcb, US_BULK_CB_WRAP_LEN, NULL);
+ if (result != USB_STOR_XFER_GOOD) {
+ usb_stor_dbg(us, "send cmd to out endpoint fail ---\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ if (buf) {
+ unsigned int pipe = fDir;
+
+ if (fDir == FDIR_READ)
+ pipe = us->recv_bulk_pipe;
+ else
+ pipe = us->send_bulk_pipe;
+
+ /* Bulk */
+ if (use_sg) {
+ result = usb_stor_bulk_srb(us, pipe, us->srb);
+ } else {
+ result = usb_stor_bulk_transfer_sg(us, pipe, buf,
+ transfer_length, 0, &partial);
+ }
+ if (result != USB_STOR_XFER_GOOD) {
+ usb_stor_dbg(us, "data transfer fail ---\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ }
+
+ /* Get CSW for device status */
+ result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
+ US_BULK_CS_WRAP_LEN, &cswlen);
+
+ if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
+ usb_stor_dbg(us, "Received 0-length CSW; retrying...\n");
+ result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ bcs, US_BULK_CS_WRAP_LEN, &cswlen);
+ }
+
+ if (result == USB_STOR_XFER_STALLED) {
+ /* get the status again */
+ usb_stor_dbg(us, "Attempting to get CSW (2nd try)...\n");
+ result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ bcs, US_BULK_CS_WRAP_LEN, NULL);
+ }
+
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ /* check bulk status */
+ residue = le32_to_cpu(bcs->Residue);
+
+ /* try to compute the actual residue, based on how much data
+ * was really transferred and what the device tells us */
+ if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) {
+ residue = min(residue, transfer_length);
+ if (us->srb != NULL)
+ scsi_set_resid(us->srb, max(scsi_get_resid(us->srb),
+ (int)residue));
+ }
+
+ if (bcs->Status != US_BULK_STAT_OK)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ if (info->SD_Status.Insert && info->SD_Status.Ready)
+ return USB_STOR_TRANSPORT_GOOD;
+ else {
+ ene_sd_init(us);
+ return USB_STOR_TRANSPORT_GOOD;
+ }
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int sd_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb)
+{
+ unsigned char data_ptr[36] = {
+ 0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55,
+ 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61,
+ 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30 };
+
+ usb_stor_set_xfer_buf(data_ptr, 36, srb);
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int sd_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+ unsigned char mediaNoWP[12] = {
+ 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 };
+ unsigned char mediaWP[12] = {
+ 0x0b, 0x00, 0x80, 0x08, 0x00, 0x00,
+ 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 };
+
+ if (info->SD_Status.WtP)
+ usb_stor_set_xfer_buf(mediaWP, 12, srb);
+ else
+ usb_stor_set_xfer_buf(mediaNoWP, 12, srb);
+
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
+{
+ u32 bl_num;
+ u32 bl_len;
+ unsigned int offset = 0;
+ unsigned char buf[8];
+ struct scatterlist *sg = NULL;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ usb_stor_dbg(us, "sd_scsi_read_capacity\n");
+ if (info->SD_Status.HiCapacity) {
+ bl_len = 0x200;
+ if (info->SD_Status.IsMMC)
+ bl_num = info->HC_C_SIZE-1;
+ else
+ bl_num = (info->HC_C_SIZE + 1) * 1024 - 1;
+ } else {
+ bl_len = 1 << (info->SD_READ_BL_LEN);
+ bl_num = info->SD_Block_Mult * (info->SD_C_SIZE + 1)
+ * (1 << (info->SD_C_SIZE_MULT + 2)) - 1;
+ }
+ info->bl_num = bl_num;
+ usb_stor_dbg(us, "bl_len = %x\n", bl_len);
+ usb_stor_dbg(us, "bl_num = %x\n", bl_num);
+
+ /*srb->request_bufflen = 8; */
+ buf[0] = (bl_num >> 24) & 0xff;
+ buf[1] = (bl_num >> 16) & 0xff;
+ buf[2] = (bl_num >> 8) & 0xff;
+ buf[3] = (bl_num >> 0) & 0xff;
+ buf[4] = (bl_len >> 24) & 0xff;
+ buf[5] = (bl_len >> 16) & 0xff;
+ buf[6] = (bl_len >> 8) & 0xff;
+ buf[7] = (bl_len >> 0) & 0xff;
+
+ usb_stor_access_xfer_buf(buf, 8, srb, &sg, &offset, TO_XFER_BUF);
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
+{
+ int result;
+ unsigned char *cdb = srb->cmnd;
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) |
+ ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff);
+ u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff);
+ u32 bnByte = bn * 0x200;
+ u32 blenByte = blen * 0x200;
+
+ if (bn > info->bl_num)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ result = ene_load_bincode(us, SD_RW_PATTERN);
+ if (result != USB_STOR_XFER_GOOD) {
+ usb_stor_dbg(us, "Load SD RW pattern Fail !!\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ if (info->SD_Status.HiCapacity)
+ bnByte = bn;
+
+ /* set up the command wrapper */
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = blenByte;
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xF1;
+ bcb->CDB[5] = (unsigned char)(bnByte);
+ bcb->CDB[4] = (unsigned char)(bnByte>>8);
+ bcb->CDB[3] = (unsigned char)(bnByte>>16);
+ bcb->CDB[2] = (unsigned char)(bnByte>>24);
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, scsi_sglist(srb), 1);
+ return result;
+}
+
+static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
+{
+ int result;
+ unsigned char *cdb = srb->cmnd;
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) |
+ ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff);
+ u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff);
+ u32 bnByte = bn * 0x200;
+ u32 blenByte = blen * 0x200;
+
+ if (bn > info->bl_num)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ result = ene_load_bincode(us, SD_RW_PATTERN);
+ if (result != USB_STOR_XFER_GOOD) {
+ usb_stor_dbg(us, "Load SD RW pattern Fail !!\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ if (info->SD_Status.HiCapacity)
+ bnByte = bn;
+
+ /* set up the command wrapper */
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = blenByte;
+ bcb->Flags = 0x00;
+ bcb->CDB[0] = 0xF0;
+ bcb->CDB[5] = (unsigned char)(bnByte);
+ bcb->CDB[4] = (unsigned char)(bnByte>>8);
+ bcb->CDB[3] = (unsigned char)(bnByte>>16);
+ bcb->CDB[2] = (unsigned char)(bnByte>>24);
+
+ result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
+ return result;
+}
+
+/*
+ * ENE MS Card
+ */
+
+static int ms_lib_set_logicalpair(struct us_data *us, u16 logblk, u16 phyblk)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ if ((logblk >= info->MS_Lib.NumberOfLogBlock) || (phyblk >= info->MS_Lib.NumberOfPhyBlock))
+ return (u32)-1;
+
+ info->MS_Lib.Phy2LogMap[phyblk] = logblk;
+ info->MS_Lib.Log2PhyMap[logblk] = phyblk;
+
+ return 0;
+}
+
+static int ms_lib_set_logicalblockmark(struct us_data *us, u16 phyblk, u16 mark)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ if (phyblk >= info->MS_Lib.NumberOfPhyBlock)
+ return (u32)-1;
+
+ info->MS_Lib.Phy2LogMap[phyblk] = mark;
+
+ return 0;
+}
+
+static int ms_lib_set_initialerrorblock(struct us_data *us, u16 phyblk)
+{
+ return ms_lib_set_logicalblockmark(us, phyblk, MS_LB_INITIAL_ERROR);
+}
+
+static int ms_lib_set_bootblockmark(struct us_data *us, u16 phyblk)
+{
+ return ms_lib_set_logicalblockmark(us, phyblk, MS_LB_BOOT_BLOCK);
+}
+
+static int ms_lib_free_logicalmap(struct us_data *us)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ kfree(info->MS_Lib.Phy2LogMap);
+ info->MS_Lib.Phy2LogMap = NULL;
+
+ kfree(info->MS_Lib.Log2PhyMap);
+ info->MS_Lib.Log2PhyMap = NULL;
+
+ return 0;
+}
+
+static int ms_lib_alloc_logicalmap(struct us_data *us)
+{
+ u32 i;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ info->MS_Lib.Phy2LogMap = kmalloc(info->MS_Lib.NumberOfPhyBlock * sizeof(u16), GFP_KERNEL);
+ info->MS_Lib.Log2PhyMap = kmalloc(info->MS_Lib.NumberOfLogBlock * sizeof(u16), GFP_KERNEL);
+
+ if ((info->MS_Lib.Phy2LogMap == NULL) || (info->MS_Lib.Log2PhyMap == NULL)) {
+ ms_lib_free_logicalmap(us);
+ return (u32)-1;
+ }
+
+ for (i = 0; i < info->MS_Lib.NumberOfPhyBlock; i++)
+ info->MS_Lib.Phy2LogMap[i] = MS_LB_NOT_USED;
+
+ for (i = 0; i < info->MS_Lib.NumberOfLogBlock; i++)
+ info->MS_Lib.Log2PhyMap[i] = MS_LB_NOT_USED;
+
+ return 0;
+}
+
+static void ms_lib_clear_writebuf(struct us_data *us)
+{
+ int i;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ info->MS_Lib.wrtblk = (u16)-1;
+ ms_lib_clear_pagemap(info);
+
+ if (info->MS_Lib.blkpag)
+ memset(info->MS_Lib.blkpag, 0xff, info->MS_Lib.PagesPerBlock * info->MS_Lib.BytesPerSector);
+
+ if (info->MS_Lib.blkext) {
+ for (i = 0; i < info->MS_Lib.PagesPerBlock; i++) {
+ info->MS_Lib.blkext[i].status1 = MS_REG_ST1_DEFAULT;
+ info->MS_Lib.blkext[i].ovrflg = MS_REG_OVR_DEFAULT;
+ info->MS_Lib.blkext[i].mngflg = MS_REG_MNG_DEFAULT;
+ info->MS_Lib.blkext[i].logadr = MS_LB_NOT_USED;
+ }
+ }
+}
+
+static int ms_count_freeblock(struct us_data *us, u16 PhyBlock)
+{
+ u32 Ende, Count;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ Ende = PhyBlock + MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+ for (Count = 0; PhyBlock < Ende; PhyBlock++) {
+ switch (info->MS_Lib.Phy2LogMap[PhyBlock]) {
+ case MS_LB_NOT_USED:
+ case MS_LB_NOT_USED_ERASED:
+ Count++;
+ default:
+ break;
+ }
+ }
+
+ return Count;
+}
+
+static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr,
+ u8 PageNum, u32 *PageBuf, struct ms_lib_type_extdat *ExtraDat)
+{
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ int result;
+ u8 ExtBuf[4];
+ u32 bn = PhyBlockAddr * 0x20 + PageNum;
+
+ /* printk(KERN_INFO "MS --- MS_ReaderReadPage,
+ PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum); */
+
+ result = ene_load_bincode(us, MS_RW_PATTERN);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ /* Read Page Data */
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = 0x200;
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xF1;
+
+ bcb->CDB[1] = 0x02; /* in init.c ENE_MSInit() is 0x01 */
+
+ bcb->CDB[5] = (unsigned char)(bn);
+ bcb->CDB[4] = (unsigned char)(bn>>8);
+ bcb->CDB[3] = (unsigned char)(bn>>16);
+ bcb->CDB[2] = (unsigned char)(bn>>24);
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, PageBuf, 0);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+
+ /* Read Extra Data */
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = 0x4;
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xF1;
+ bcb->CDB[1] = 0x03;
+
+ bcb->CDB[5] = (unsigned char)(PageNum);
+ bcb->CDB[4] = (unsigned char)(PhyBlockAddr);
+ bcb->CDB[3] = (unsigned char)(PhyBlockAddr>>8);
+ bcb->CDB[2] = (unsigned char)(PhyBlockAddr>>16);
+ bcb->CDB[6] = 0x01;
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ ExtraDat->reserved = 0;
+ ExtraDat->intr = 0x80; /* Not yet,fireware support */
+ ExtraDat->status0 = 0x10; /* Not yet,fireware support */
+
+ ExtraDat->status1 = 0x00; /* Not yet,fireware support */
+ ExtraDat->ovrflg = ExtBuf[0];
+ ExtraDat->mngflg = ExtBuf[1];
+ ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]);
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_lib_process_bootblock(struct us_data *us, u16 PhyBlock, u8 *PageData)
+{
+ struct ms_bootblock_sysent *SysEntry;
+ struct ms_bootblock_sysinf *SysInfo;
+ u32 i, result;
+ u8 PageNumber;
+ u8 *PageBuffer;
+ struct ms_lib_type_extdat ExtraData;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ PageBuffer = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
+ if (PageBuffer == NULL)
+ return (u32)-1;
+
+ result = (u32)-1;
+
+ SysInfo = &(((struct ms_bootblock_page0 *)PageData)->sysinf);
+
+ if ((SysInfo->bMsClass != MS_SYSINF_MSCLASS_TYPE_1) ||
+ (be16_to_cpu(SysInfo->wPageSize) != MS_SYSINF_PAGE_SIZE) ||
+ ((SysInfo->bSecuritySupport & MS_SYSINF_SECURITY) == MS_SYSINF_SECURITY_SUPPORT) ||
+ (SysInfo->bReserved1 != MS_SYSINF_RESERVED1) ||
+ (SysInfo->bReserved2 != MS_SYSINF_RESERVED2) ||
+ (SysInfo->bFormatType != MS_SYSINF_FORMAT_FAT) ||
+ (SysInfo->bUsage != MS_SYSINF_USAGE_GENERAL))
+ goto exit;
+ /* */
+ switch (info->MS_Lib.cardType = SysInfo->bCardType) {
+ case MS_SYSINF_CARDTYPE_RDONLY:
+ ms_lib_ctrl_set(info, MS_LIB_CTRL_RDONLY);
+ break;
+ case MS_SYSINF_CARDTYPE_RDWR:
+ ms_lib_ctrl_reset(info, MS_LIB_CTRL_RDONLY);
+ break;
+ case MS_SYSINF_CARDTYPE_HYBRID:
+ default:
+ goto exit;
+ }
+
+ info->MS_Lib.blockSize = be16_to_cpu(SysInfo->wBlockSize);
+ info->MS_Lib.NumberOfPhyBlock = be16_to_cpu(SysInfo->wBlockNumber);
+ info->MS_Lib.NumberOfLogBlock = be16_to_cpu(SysInfo->wTotalBlockNumber)-2;
+ info->MS_Lib.PagesPerBlock = info->MS_Lib.blockSize * SIZE_OF_KIRO / MS_BYTES_PER_PAGE;
+ info->MS_Lib.NumberOfSegment = info->MS_Lib.NumberOfPhyBlock / MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+ info->MS_Model = be16_to_cpu(SysInfo->wMemorySize);
+
+ /*Allocate to all number of logicalblock and physicalblock */
+ if (ms_lib_alloc_logicalmap(us))
+ goto exit;
+
+ /* Mark the book block */
+ ms_lib_set_bootblockmark(us, PhyBlock);
+
+ SysEntry = &(((struct ms_bootblock_page0 *)PageData)->sysent);
+
+ for (i = 0; i < MS_NUMBER_OF_SYSTEM_ENTRY; i++) {
+ u32 EntryOffset, EntrySize;
+
+ EntryOffset = be32_to_cpu(SysEntry->entry[i].dwStart);
+
+ if (EntryOffset == 0xffffff)
+ continue;
+ EntrySize = be32_to_cpu(SysEntry->entry[i].dwSize);
+
+ if (EntrySize == 0)
+ continue;
+
+ if (EntryOffset + MS_BYTES_PER_PAGE + EntrySize > info->MS_Lib.blockSize * (u32)SIZE_OF_KIRO)
+ continue;
+
+ if (i == 0) {
+ u8 PrevPageNumber = 0;
+ u16 phyblk;
+
+ if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_INVALID_BLOCK)
+ goto exit;
+
+ while (EntrySize > 0) {
+
+ PageNumber = (u8)(EntryOffset / MS_BYTES_PER_PAGE + 1);
+ if (PageNumber != PrevPageNumber) {
+ switch (ms_read_readpage(us, PhyBlock, PageNumber, (u32 *)PageBuffer, &ExtraData)) {
+ case MS_STATUS_SUCCESS:
+ break;
+ case MS_STATUS_WRITE_PROTECT:
+ case MS_ERROR_FLASH_READ:
+ case MS_STATUS_ERROR:
+ default:
+ goto exit;
+ }
+
+ PrevPageNumber = PageNumber;
+ }
+
+ phyblk = be16_to_cpu(*(u16 *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)));
+ if (phyblk < 0x0fff)
+ ms_lib_set_initialerrorblock(us, phyblk);
+
+ EntryOffset += 2;
+ EntrySize -= 2;
+ }
+ } else if (i == 1) { /* CIS/IDI */
+ struct ms_bootblock_idi *idi;
+
+ if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_CIS_IDI)
+ goto exit;
+
+ switch (ms_read_readpage(us, PhyBlock, (u8)(EntryOffset / MS_BYTES_PER_PAGE + 1), (u32 *)PageBuffer, &ExtraData)) {
+ case MS_STATUS_SUCCESS:
+ break;
+ case MS_STATUS_WRITE_PROTECT:
+ case MS_ERROR_FLASH_READ:
+ case MS_STATUS_ERROR:
+ default:
+ goto exit;
+ }
+
+ idi = &((struct ms_bootblock_cis_idi *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)))->idi.idi;
+ if (le16_to_cpu(idi->wIDIgeneralConfiguration) != MS_IDI_GENERAL_CONF)
+ goto exit;
+
+ info->MS_Lib.BytesPerSector = le16_to_cpu(idi->wIDIbytesPerSector);
+ if (info->MS_Lib.BytesPerSector != MS_BYTES_PER_PAGE)
+ goto exit;
+ }
+ } /* End for .. */
+
+ result = 0;
+
+exit:
+ if (result)
+ ms_lib_free_logicalmap(us);
+
+ kfree(PageBuffer);
+
+ result = 0;
+ return result;
+}
+
+static void ms_lib_free_writebuf(struct us_data *us)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+ info->MS_Lib.wrtblk = (u16)-1; /* set to -1 */
+
+ /* memset((fdoExt)->MS_Lib.pagemap, 0, sizeof((fdoExt)->MS_Lib.pagemap)) */
+
+ ms_lib_clear_pagemap(info); /* (pdx)->MS_Lib.pagemap memset 0 in ms.h */
+
+ if (info->MS_Lib.blkpag) {
+ kfree((u8 *)(info->MS_Lib.blkpag)); /* Arnold test ... */
+ info->MS_Lib.blkpag = NULL;
+ }
+
+ if (info->MS_Lib.blkext) {
+ kfree((u8 *)(info->MS_Lib.blkext)); /* Arnold test ... */
+ info->MS_Lib.blkext = NULL;
+ }
+}
+
+
+static void ms_lib_free_allocatedarea(struct us_data *us)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ ms_lib_free_writebuf(us); /* Free MS_Lib.pagemap */
+ ms_lib_free_logicalmap(us); /* kfree MS_Lib.Phy2LogMap and MS_Lib.Log2PhyMap */
+
+ /* set struct us point flag to 0 */
+ info->MS_Lib.flags = 0;
+ info->MS_Lib.BytesPerSector = 0;
+ info->MS_Lib.SectorsPerCylinder = 0;
+
+ info->MS_Lib.cardType = 0;
+ info->MS_Lib.blockSize = 0;
+ info->MS_Lib.PagesPerBlock = 0;
+
+ info->MS_Lib.NumberOfPhyBlock = 0;
+ info->MS_Lib.NumberOfLogBlock = 0;
+}
+
+
+static int ms_lib_alloc_writebuf(struct us_data *us)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ info->MS_Lib.wrtblk = (u16)-1;
+
+ info->MS_Lib.blkpag = kmalloc(info->MS_Lib.PagesPerBlock * info->MS_Lib.BytesPerSector, GFP_KERNEL);
+ info->MS_Lib.blkext = kmalloc(info->MS_Lib.PagesPerBlock * sizeof(struct ms_lib_type_extdat), GFP_KERNEL);
+
+ if ((info->MS_Lib.blkpag == NULL) || (info->MS_Lib.blkext == NULL)) {
+ ms_lib_free_writebuf(us);
+ return (u32)-1;
+ }
+
+ ms_lib_clear_writebuf(us);
+
+return 0;
+}
+
+static int ms_lib_force_setlogical_pair(struct us_data *us, u16 logblk, u16 phyblk)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ if (logblk == MS_LB_NOT_USED)
+ return 0;
+
+ if ((logblk >= info->MS_Lib.NumberOfLogBlock) ||
+ (phyblk >= info->MS_Lib.NumberOfPhyBlock))
+ return (u32)-1;
+
+ info->MS_Lib.Phy2LogMap[phyblk] = logblk;
+ info->MS_Lib.Log2PhyMap[logblk] = phyblk;
+
+ return 0;
+}
+
+static int ms_read_copyblock(struct us_data *us, u16 oldphy, u16 newphy,
+ u16 PhyBlockAddr, u8 PageNum, unsigned char *buf, u16 len)
+{
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ int result;
+
+ /* printk(KERN_INFO "MS_ReaderCopyBlock --- PhyBlockAddr = %x,
+ PageNum = %x\n", PhyBlockAddr, PageNum); */
+ result = ene_load_bincode(us, MS_RW_PATTERN);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = 0x200*len;
+ bcb->Flags = 0x00;
+ bcb->CDB[0] = 0xF0;
+ bcb->CDB[1] = 0x08;
+ bcb->CDB[4] = (unsigned char)(oldphy);
+ bcb->CDB[3] = (unsigned char)(oldphy>>8);
+ bcb->CDB[2] = 0; /* (BYTE)(oldphy>>16) */
+ bcb->CDB[7] = (unsigned char)(newphy);
+ bcb->CDB[6] = (unsigned char)(newphy>>8);
+ bcb->CDB[5] = 0; /* (BYTE)(newphy>>16) */
+ bcb->CDB[9] = (unsigned char)(PhyBlockAddr);
+ bcb->CDB[8] = (unsigned char)(PhyBlockAddr>>8);
+ bcb->CDB[10] = PageNum;
+
+ result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_read_eraseblock(struct us_data *us, u32 PhyBlockAddr)
+{
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ int result;
+ u32 bn = PhyBlockAddr;
+
+ /* printk(KERN_INFO "MS --- ms_read_eraseblock,
+ PhyBlockAddr = %x\n", PhyBlockAddr); */
+ result = ene_load_bincode(us, MS_RW_PATTERN);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = 0x200;
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xF2;
+ bcb->CDB[1] = 0x06;
+ bcb->CDB[4] = (unsigned char)(bn);
+ bcb->CDB[3] = (unsigned char)(bn>>8);
+ bcb->CDB[2] = (unsigned char)(bn>>16);
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_lib_check_disableblock(struct us_data *us, u16 PhyBlock)
+{
+ unsigned char *PageBuf = NULL;
+ u16 result = MS_STATUS_SUCCESS;
+ u16 blk, index = 0;
+ struct ms_lib_type_extdat extdat;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ PageBuf = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
+ if (PageBuf == NULL) {
+ result = MS_NO_MEMORY_ERROR;
+ goto exit;
+ }
+
+ ms_read_readpage(us, PhyBlock, 1, (u32 *)PageBuf, &extdat);
+ do {
+ blk = be16_to_cpu(PageBuf[index]);
+ if (blk == MS_LB_NOT_USED)
+ break;
+ if (blk == info->MS_Lib.Log2PhyMap[0]) {
+ result = MS_ERROR_FLASH_READ;
+ break;
+ }
+ index++;
+ } while (1);
+
+exit:
+ kfree(PageBuf);
+ return result;
+}
+
+static int ms_lib_setacquired_errorblock(struct us_data *us, u16 phyblk)
+{
+ u16 log;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ if (phyblk >= info->MS_Lib.NumberOfPhyBlock)
+ return (u32)-1;
+
+ log = info->MS_Lib.Phy2LogMap[phyblk];
+
+ if (log < info->MS_Lib.NumberOfLogBlock)
+ info->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED;
+
+ if (info->MS_Lib.Phy2LogMap[phyblk] != MS_LB_INITIAL_ERROR)
+ info->MS_Lib.Phy2LogMap[phyblk] = MS_LB_ACQUIRED_ERROR;
+
+ return 0;
+}
+
+static int ms_lib_overwrite_extra(struct us_data *us, u32 PhyBlockAddr,
+ u8 PageNum, u8 OverwriteFlag)
+{
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ int result;
+
+ /* printk("MS --- MS_LibOverwriteExtra,
+ PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum); */
+ result = ene_load_bincode(us, MS_RW_PATTERN);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = 0x4;
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xF2;
+ bcb->CDB[1] = 0x05;
+ bcb->CDB[5] = (unsigned char)(PageNum);
+ bcb->CDB[4] = (unsigned char)(PhyBlockAddr);
+ bcb->CDB[3] = (unsigned char)(PhyBlockAddr>>8);
+ bcb->CDB[2] = (unsigned char)(PhyBlockAddr>>16);
+ bcb->CDB[6] = OverwriteFlag;
+ bcb->CDB[7] = 0xFF;
+ bcb->CDB[8] = 0xFF;
+ bcb->CDB[9] = 0xFF;
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_lib_error_phyblock(struct us_data *us, u16 phyblk)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ if (phyblk >= info->MS_Lib.NumberOfPhyBlock)
+ return MS_STATUS_ERROR;
+
+ ms_lib_setacquired_errorblock(us, phyblk);
+
+ if (ms_lib_iswritable(info))
+ return ms_lib_overwrite_extra(us, phyblk, 0, (u8)(~MS_REG_OVR_BKST & BYTE_MASK));
+
+ return MS_STATUS_SUCCESS;
+}
+
+static int ms_lib_erase_phyblock(struct us_data *us, u16 phyblk)
+{
+ u16 log;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ if (phyblk >= info->MS_Lib.NumberOfPhyBlock)
+ return MS_STATUS_ERROR;
+
+ log = info->MS_Lib.Phy2LogMap[phyblk];
+
+ if (log < info->MS_Lib.NumberOfLogBlock)
+ info->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED;
+
+ info->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED;
+
+ if (ms_lib_iswritable(info)) {
+ switch (ms_read_eraseblock(us, phyblk)) {
+ case MS_STATUS_SUCCESS:
+ info->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED_ERASED;
+ return MS_STATUS_SUCCESS;
+ case MS_ERROR_FLASH_ERASE:
+ case MS_STATUS_INT_ERROR:
+ ms_lib_error_phyblock(us, phyblk);
+ return MS_ERROR_FLASH_ERASE;
+ case MS_STATUS_ERROR:
+ default:
+ ms_lib_ctrl_set(info, MS_LIB_CTRL_RDONLY); /* MS_LibCtrlSet will used by ENE_MSInit ,need check, and why us to info*/
+ ms_lib_setacquired_errorblock(us, phyblk);
+ return MS_STATUS_ERROR;
+ }
+ }
+
+ ms_lib_setacquired_errorblock(us, phyblk);
+
+ return MS_STATUS_SUCCESS;
+}
+
+static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock,
+ u8 PageNum, struct ms_lib_type_extdat *ExtraDat)
+{
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ int result;
+ u8 ExtBuf[4];
+
+ /* printk("MS_LibReadExtra --- PhyBlock = %x, PageNum = %x\n", PhyBlock, PageNum); */
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = 0x4;
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xF1;
+ bcb->CDB[1] = 0x03;
+ bcb->CDB[5] = (unsigned char)(PageNum);
+ bcb->CDB[4] = (unsigned char)(PhyBlock);
+ bcb->CDB[3] = (unsigned char)(PhyBlock>>8);
+ bcb->CDB[2] = (unsigned char)(PhyBlock>>16);
+ bcb->CDB[6] = 0x01;
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ ExtraDat->reserved = 0;
+ ExtraDat->intr = 0x80; /* Not yet, waiting for fireware support */
+ ExtraDat->status0 = 0x10; /* Not yet, waiting for fireware support */
+ ExtraDat->status1 = 0x00; /* Not yet, waiting for fireware support */
+ ExtraDat->ovrflg = ExtBuf[0];
+ ExtraDat->mngflg = ExtBuf[1];
+ ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]);
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_libsearch_block_from_physical(struct us_data *us, u16 phyblk)
+{
+ u16 Newblk;
+ u16 blk;
+ struct ms_lib_type_extdat extdat; /* need check */
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+
+ if (phyblk >= info->MS_Lib.NumberOfPhyBlock)
+ return MS_LB_ERROR;
+
+ for (blk = phyblk + 1; blk != phyblk; blk++) {
+ if ((blk & MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK) == 0)
+ blk -= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+
+ Newblk = info->MS_Lib.Phy2LogMap[blk];
+ if (info->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED_ERASED) {
+ return blk;
+ } else if (info->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED) {
+ switch (ms_lib_read_extra(us, blk, 0, &extdat)) {
+ case MS_STATUS_SUCCESS:
+ case MS_STATUS_SUCCESS_WITH_ECC:
+ break;
+ case MS_NOCARD_ERROR:
+ return MS_NOCARD_ERROR;
+ case MS_STATUS_INT_ERROR:
+ return MS_LB_ERROR;
+ case MS_ERROR_FLASH_READ:
+ default:
+ ms_lib_setacquired_errorblock(us, blk);
+ continue;
+ } /* End switch */
+
+ if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) {
+ ms_lib_setacquired_errorblock(us, blk);
+ continue;
+ }
+
+ switch (ms_lib_erase_phyblock(us, blk)) {
+ case MS_STATUS_SUCCESS:
+ return blk;
+ case MS_STATUS_ERROR:
+ return MS_LB_ERROR;
+ case MS_ERROR_FLASH_ERASE:
+ default:
+ ms_lib_error_phyblock(us, blk);
+ break;
+ }
+ }
+ } /* End for */
+
+ return MS_LB_ERROR;
+}
+static int ms_libsearch_block_from_logical(struct us_data *us, u16 logblk)
+{
+ u16 phyblk;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ phyblk = ms_libconv_to_physical(info, logblk);
+ if (phyblk >= MS_LB_ERROR) {
+ if (logblk >= info->MS_Lib.NumberOfLogBlock)
+ return MS_LB_ERROR;
+
+ phyblk = (logblk + MS_NUMBER_OF_BOOT_BLOCK) / MS_LOGICAL_BLOCKS_PER_SEGMENT;
+ phyblk *= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+ phyblk += MS_PHYSICAL_BLOCKS_PER_SEGMENT - 1;
+ }
+
+ return ms_libsearch_block_from_physical(us, phyblk);
+}
+
+static int ms_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+ /* pr_info("MS_SCSI_Test_Unit_Ready\n"); */
+ if (info->MS_Status.Insert && info->MS_Status.Ready) {
+ return USB_STOR_TRANSPORT_GOOD;
+ } else {
+ ene_ms_init(us);
+ return USB_STOR_TRANSPORT_GOOD;
+ }
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb)
+{
+ /* pr_info("MS_SCSI_Inquiry\n"); */
+ unsigned char data_ptr[36] = {
+ 0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55,
+ 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61,
+ 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
+
+ usb_stor_set_xfer_buf(data_ptr, 36, srb);
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+ unsigned char mediaNoWP[12] = {
+ 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 };
+ unsigned char mediaWP[12] = {
+ 0x0b, 0x00, 0x80, 0x08, 0x00, 0x00,
+ 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 };
+
+ if (info->MS_Status.WtP)
+ usb_stor_set_xfer_buf(mediaWP, 12, srb);
+ else
+ usb_stor_set_xfer_buf(mediaNoWP, 12, srb);
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
+{
+ u32 bl_num;
+ u16 bl_len;
+ unsigned int offset = 0;
+ unsigned char buf[8];
+ struct scatterlist *sg = NULL;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ usb_stor_dbg(us, "ms_scsi_read_capacity\n");
+ bl_len = 0x200;
+ if (info->MS_Status.IsMSPro)
+ bl_num = info->MSP_TotalBlock - 1;
+ else
+ bl_num = info->MS_Lib.NumberOfLogBlock * info->MS_Lib.blockSize * 2 - 1;
+
+ info->bl_num = bl_num;
+ usb_stor_dbg(us, "bl_len = %x\n", bl_len);
+ usb_stor_dbg(us, "bl_num = %x\n", bl_num);
+
+ /*srb->request_bufflen = 8; */
+ buf[0] = (bl_num >> 24) & 0xff;
+ buf[1] = (bl_num >> 16) & 0xff;
+ buf[2] = (bl_num >> 8) & 0xff;
+ buf[3] = (bl_num >> 0) & 0xff;
+ buf[4] = (bl_len >> 24) & 0xff;
+ buf[5] = (bl_len >> 16) & 0xff;
+ buf[6] = (bl_len >> 8) & 0xff;
+ buf[7] = (bl_len >> 0) & 0xff;
+
+ usb_stor_access_xfer_buf(buf, 8, srb, &sg, &offset, TO_XFER_BUF);
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static void ms_lib_phy_to_log_range(u16 PhyBlock, u16 *LogStart, u16 *LogEnde)
+{
+ PhyBlock /= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+
+ if (PhyBlock) {
+ *LogStart = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT + (PhyBlock - 1) * MS_LOGICAL_BLOCKS_PER_SEGMENT;/*496*/
+ *LogEnde = *LogStart + MS_LOGICAL_BLOCKS_PER_SEGMENT;/*496*/
+ } else {
+ *LogStart = 0;
+ *LogEnde = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT;/*494*/
+ }
+}
+
+static int ms_lib_read_extrablock(struct us_data *us, u32 PhyBlock,
+ u8 PageNum, u8 blen, void *buf)
+{
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ int result;
+
+ /* printk("MS_LibReadExtraBlock --- PhyBlock = %x,
+ PageNum = %x, blen = %x\n", PhyBlock, PageNum, blen); */
+
+ /* Read Extra Data */
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = 0x4 * blen;
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xF1;
+ bcb->CDB[1] = 0x03;
+ bcb->CDB[5] = (unsigned char)(PageNum);
+ bcb->CDB[4] = (unsigned char)(PhyBlock);
+ bcb->CDB[3] = (unsigned char)(PhyBlock>>8);
+ bcb->CDB[2] = (unsigned char)(PhyBlock>>16);
+ bcb->CDB[6] = blen;
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, buf, 0);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st)
+{
+ u16 PhyBlock, newblk, i;
+ u16 LogStart, LogEnde;
+ struct ms_lib_type_extdat extdat;
+ u8 buf[0x200];
+ u32 count = 0, index = 0;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ for (PhyBlock = 0; PhyBlock < info->MS_Lib.NumberOfPhyBlock;) {
+ ms_lib_phy_to_log_range(PhyBlock, &LogStart, &LogEnde);
+
+ for (i = 0; i < MS_PHYSICAL_BLOCKS_PER_SEGMENT; i++, PhyBlock++) {
+ switch (ms_libconv_to_logical(info, PhyBlock)) {
+ case MS_STATUS_ERROR:
+ continue;
+ default:
+ break;
+ }
+
+ if (count == PhyBlock) {
+ ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, &buf);
+ count += 0x80;
+ }
+ index = (PhyBlock % 0x80) * 4;
+
+ extdat.ovrflg = buf[index];
+ extdat.mngflg = buf[index+1];
+ extdat.logadr = memstick_logaddr(buf[index+2], buf[index+3]);
+
+ if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) {
+ ms_lib_setacquired_errorblock(us, PhyBlock);
+ continue;
+ }
+
+ if ((extdat.mngflg & MS_REG_MNG_ATFLG) == MS_REG_MNG_ATFLG_ATTBL) {
+ ms_lib_erase_phyblock(us, PhyBlock);
+ continue;
+ }
+
+ if (extdat.logadr != MS_LB_NOT_USED) {
+ if ((extdat.logadr < LogStart) || (LogEnde <= extdat.logadr)) {
+ ms_lib_erase_phyblock(us, PhyBlock);
+ continue;
+ }
+
+ newblk = ms_libconv_to_physical(info, extdat.logadr);
+
+ if (newblk != MS_LB_NOT_USED) {
+ if (extdat.logadr == 0) {
+ ms_lib_set_logicalpair(us, extdat.logadr, PhyBlock);
+ if (ms_lib_check_disableblock(us, btBlk1st)) {
+ ms_lib_set_logicalpair(us, extdat.logadr, newblk);
+ continue;
+ }
+ }
+
+ ms_lib_read_extra(us, newblk, 0, &extdat);
+ if ((extdat.ovrflg & MS_REG_OVR_UDST) == MS_REG_OVR_UDST_UPDATING) {
+ ms_lib_erase_phyblock(us, PhyBlock);
+ continue;
+ } else {
+ ms_lib_erase_phyblock(us, newblk);
+ }
+ }
+
+ ms_lib_set_logicalpair(us, extdat.logadr, PhyBlock);
+ }
+ }
+ } /* End for ... */
+
+ return MS_STATUS_SUCCESS;
+}
+
+
+static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
+{
+ int result;
+ unsigned char *cdb = srb->cmnd;
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) |
+ ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff);
+ u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff);
+ u32 blenByte = blen * 0x200;
+
+ if (bn > info->bl_num)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ if (info->MS_Status.IsMSPro) {
+ result = ene_load_bincode(us, MSP_RW_PATTERN);
+ if (result != USB_STOR_XFER_GOOD) {
+ usb_stor_dbg(us, "Load MPS RW pattern Fail !!\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ /* set up the command wrapper */
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = blenByte;
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xF1;
+ bcb->CDB[1] = 0x02;
+ bcb->CDB[5] = (unsigned char)(bn);
+ bcb->CDB[4] = (unsigned char)(bn>>8);
+ bcb->CDB[3] = (unsigned char)(bn>>16);
+ bcb->CDB[2] = (unsigned char)(bn>>24);
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, scsi_sglist(srb), 1);
+ } else {
+ void *buf;
+ int offset = 0;
+ u16 phyblk, logblk;
+ u8 PageNum;
+ u16 len;
+ u32 blkno;
+
+ buf = kmalloc(blenByte, GFP_KERNEL);
+ if (buf == NULL)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ result = ene_load_bincode(us, MS_RW_PATTERN);
+ if (result != USB_STOR_XFER_GOOD) {
+ pr_info("Load MS RW pattern Fail !!\n");
+ result = USB_STOR_TRANSPORT_ERROR;
+ goto exit;
+ }
+
+ logblk = (u16)(bn / info->MS_Lib.PagesPerBlock);
+ PageNum = (u8)(bn % info->MS_Lib.PagesPerBlock);
+
+ while (1) {
+ if (blen > (info->MS_Lib.PagesPerBlock-PageNum))
+ len = info->MS_Lib.PagesPerBlock-PageNum;
+ else
+ len = blen;
+
+ phyblk = ms_libconv_to_physical(info, logblk);
+ blkno = phyblk * 0x20 + PageNum;
+
+ /* set up the command wrapper */
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = 0x200 * len;
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xF1;
+ bcb->CDB[1] = 0x02;
+ bcb->CDB[5] = (unsigned char)(blkno);
+ bcb->CDB[4] = (unsigned char)(blkno>>8);
+ bcb->CDB[3] = (unsigned char)(blkno>>16);
+ bcb->CDB[2] = (unsigned char)(blkno>>24);
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, buf+offset, 0);
+ if (result != USB_STOR_XFER_GOOD) {
+ pr_info("MS_SCSI_Read --- result = %x\n", result);
+ result = USB_STOR_TRANSPORT_ERROR;
+ goto exit;
+ }
+
+ blen -= len;
+ if (blen <= 0)
+ break;
+ logblk++;
+ PageNum = 0;
+ offset += MS_BYTES_PER_PAGE*len;
+ }
+ usb_stor_set_xfer_buf(buf, blenByte, srb);
+exit:
+ kfree(buf);
+ }
+ return result;
+}
+
+static int ms_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
+{
+ int result;
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ unsigned char *cdb = srb->cmnd;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ u32 bn = ((cdb[2] << 24) & 0xff000000) |
+ ((cdb[3] << 16) & 0x00ff0000) |
+ ((cdb[4] << 8) & 0x0000ff00) |
+ ((cdb[5] << 0) & 0x000000ff);
+ u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff);
+ u32 blenByte = blen * 0x200;
+
+ if (bn > info->bl_num)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ if (info->MS_Status.IsMSPro) {
+ result = ene_load_bincode(us, MSP_RW_PATTERN);
+ if (result != USB_STOR_XFER_GOOD) {
+ pr_info("Load MSP RW pattern Fail !!\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ /* set up the command wrapper */
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = blenByte;
+ bcb->Flags = 0x00;
+ bcb->CDB[0] = 0xF0;
+ bcb->CDB[1] = 0x04;
+ bcb->CDB[5] = (unsigned char)(bn);
+ bcb->CDB[4] = (unsigned char)(bn>>8);
+ bcb->CDB[3] = (unsigned char)(bn>>16);
+ bcb->CDB[2] = (unsigned char)(bn>>24);
+
+ result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
+ } else {
+ void *buf;
+ int offset = 0;
+ u16 PhyBlockAddr;
+ u8 PageNum;
+ u16 len, oldphy, newphy;
+
+ buf = kmalloc(blenByte, GFP_KERNEL);
+ if (buf == NULL)
+ return USB_STOR_TRANSPORT_ERROR;
+ usb_stor_set_xfer_buf(buf, blenByte, srb);
+
+ result = ene_load_bincode(us, MS_RW_PATTERN);
+ if (result != USB_STOR_XFER_GOOD) {
+ pr_info("Load MS RW pattern Fail !!\n");
+ result = USB_STOR_TRANSPORT_ERROR;
+ goto exit;
+ }
+
+ PhyBlockAddr = (u16)(bn / info->MS_Lib.PagesPerBlock);
+ PageNum = (u8)(bn % info->MS_Lib.PagesPerBlock);
+
+ while (1) {
+ if (blen > (info->MS_Lib.PagesPerBlock-PageNum))
+ len = info->MS_Lib.PagesPerBlock-PageNum;
+ else
+ len = blen;
+
+ oldphy = ms_libconv_to_physical(info, PhyBlockAddr); /* need check us <-> info */
+ newphy = ms_libsearch_block_from_logical(us, PhyBlockAddr);
+
+ result = ms_read_copyblock(us, oldphy, newphy, PhyBlockAddr, PageNum, buf+offset, len);
+
+ if (result != USB_STOR_XFER_GOOD) {
+ pr_info("MS_SCSI_Write --- result = %x\n", result);
+ result = USB_STOR_TRANSPORT_ERROR;
+ goto exit;
+ }
+
+ info->MS_Lib.Phy2LogMap[oldphy] = MS_LB_NOT_USED_ERASED;
+ ms_lib_force_setlogical_pair(us, PhyBlockAddr, newphy);
+
+ blen -= len;
+ if (blen <= 0)
+ break;
+ PhyBlockAddr++;
+ PageNum = 0;
+ offset += MS_BYTES_PER_PAGE*len;
+ }
+exit:
+ kfree(buf);
+ }
+ return result;
+}
+
+/*
+ * ENE MS Card
+ */
+
+static int ene_get_card_type(struct us_data *us, u16 index, void *buf)
+{
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ int result;
+
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = 0x01;
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xED;
+ bcb->CDB[2] = (unsigned char)(index>>8);
+ bcb->CDB[3] = (unsigned char)index;
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, buf, 0);
+ return result;
+}
+
+static int ene_get_card_status(struct us_data *us, u8 *buf)
+{
+ u16 tmpreg;
+ u32 reg4b;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ /*usb_stor_dbg(us, "transport --- ENE_ReadSDReg\n");*/
+ reg4b = *(u32 *)&buf[0x18];
+ info->SD_READ_BL_LEN = (u8)((reg4b >> 8) & 0x0f);
+
+ tmpreg = (u16) reg4b;
+ reg4b = *(u32 *)(&buf[0x14]);
+ if (info->SD_Status.HiCapacity && !info->SD_Status.IsMMC)
+ info->HC_C_SIZE = (reg4b >> 8) & 0x3fffff;
+
+ info->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (u16)(reg4b >> 22);
+ info->SD_C_SIZE_MULT = (u8)(reg4b >> 7) & 0x07;
+ if (info->SD_Status.HiCapacity && info->SD_Status.IsMMC)
+ info->HC_C_SIZE = *(u32 *)(&buf[0x100]);
+
+ if (info->SD_READ_BL_LEN > SD_BLOCK_LEN) {
+ info->SD_Block_Mult = 1 << (info->SD_READ_BL_LEN-SD_BLOCK_LEN);
+ info->SD_READ_BL_LEN = SD_BLOCK_LEN;
+ } else {
+ info->SD_Block_Mult = 1;
+ }
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ene_load_bincode(struct us_data *us, unsigned char flag)
+{
+ int err;
+ char *fw_name = NULL;
+ unsigned char *buf = NULL;
+ const struct firmware *sd_fw = NULL;
+ int result = USB_STOR_TRANSPORT_ERROR;
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ if (info->BIN_FLAG == flag)
+ return USB_STOR_TRANSPORT_GOOD;
+
+ switch (flag) {
+ /* For SD */
+ case SD_INIT1_PATTERN:
+ usb_stor_dbg(us, "SD_INIT1_PATTERN\n");
+ fw_name = SD_INIT1_FIRMWARE;
+ break;
+ case SD_INIT2_PATTERN:
+ usb_stor_dbg(us, "SD_INIT2_PATTERN\n");
+ fw_name = SD_INIT2_FIRMWARE;
+ break;
+ case SD_RW_PATTERN:
+ usb_stor_dbg(us, "SD_RW_PATTERN\n");
+ fw_name = SD_RW_FIRMWARE;
+ break;
+ /* For MS */
+ case MS_INIT_PATTERN:
+ usb_stor_dbg(us, "MS_INIT_PATTERN\n");
+ fw_name = MS_INIT_FIRMWARE;
+ break;
+ case MSP_RW_PATTERN:
+ usb_stor_dbg(us, "MSP_RW_PATTERN\n");
+ fw_name = MSP_RW_FIRMWARE;
+ break;
+ case MS_RW_PATTERN:
+ usb_stor_dbg(us, "MS_RW_PATTERN\n");
+ fw_name = MS_RW_FIRMWARE;
+ break;
+ default:
+ usb_stor_dbg(us, "----------- Unknown PATTERN ----------\n");
+ goto nofw;
+ }
+
+ err = request_firmware(&sd_fw, fw_name, &us->pusb_dev->dev);
+ if (err) {
+ usb_stor_dbg(us, "load firmware %s failed\n", fw_name);
+ goto nofw;
+ }
+ buf = kmemdup(sd_fw->data, sd_fw->size, GFP_KERNEL);
+ if (buf == NULL)
+ goto nofw;
+
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = sd_fw->size;
+ bcb->Flags = 0x00;
+ bcb->CDB[0] = 0xEF;
+
+ result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0);
+ info->BIN_FLAG = flag;
+ kfree(buf);
+
+nofw:
+ release_firmware(sd_fw);
+ return result;
+}
+
+static int ms_card_init(struct us_data *us)
+{
+ u32 result;
+ u16 TmpBlock;
+ unsigned char *PageBuffer0 = NULL, *PageBuffer1 = NULL;
+ struct ms_lib_type_extdat extdat;
+ u16 btBlk1st, btBlk2nd;
+ u32 btBlk1stErred;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ printk(KERN_INFO "MS_CardInit start\n");
+
+ ms_lib_free_allocatedarea(us); /* Clean buffer and set struct us_data flag to 0 */
+
+ /* get two PageBuffer */
+ PageBuffer0 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
+ PageBuffer1 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
+ if ((PageBuffer0 == NULL) || (PageBuffer1 == NULL)) {
+ result = MS_NO_MEMORY_ERROR;
+ goto exit;
+ }
+
+ btBlk1st = btBlk2nd = MS_LB_NOT_USED;
+ btBlk1stErred = 0;
+
+ for (TmpBlock = 0; TmpBlock < MS_MAX_INITIAL_ERROR_BLOCKS+2; TmpBlock++) {
+
+ switch (ms_read_readpage(us, TmpBlock, 0, (u32 *)PageBuffer0, &extdat)) {
+ case MS_STATUS_SUCCESS:
+ break;
+ case MS_STATUS_INT_ERROR:
+ break;
+ case MS_STATUS_ERROR:
+ default:
+ continue;
+ }
+
+ if ((extdat.ovrflg & MS_REG_OVR_BKST) == MS_REG_OVR_BKST_NG)
+ continue;
+
+ if (((extdat.mngflg & MS_REG_MNG_SYSFLG) == MS_REG_MNG_SYSFLG_USER) ||
+ (be16_to_cpu(((struct ms_bootblock_page0 *)PageBuffer0)->header.wBlockID) != MS_BOOT_BLOCK_ID) ||
+ (be16_to_cpu(((struct ms_bootblock_page0 *)PageBuffer0)->header.wFormatVersion) != MS_BOOT_BLOCK_FORMAT_VERSION) ||
+ (((struct ms_bootblock_page0 *)PageBuffer0)->header.bNumberOfDataEntry != MS_BOOT_BLOCK_DATA_ENTRIES))
+ continue;
+
+ if (btBlk1st != MS_LB_NOT_USED) {
+ btBlk2nd = TmpBlock;
+ break;
+ }
+
+ btBlk1st = TmpBlock;
+ memcpy(PageBuffer1, PageBuffer0, MS_BYTES_PER_PAGE);
+ if (extdat.status1 & (MS_REG_ST1_DTER | MS_REG_ST1_EXER | MS_REG_ST1_FGER))
+ btBlk1stErred = 1;
+ }
+
+ if (btBlk1st == MS_LB_NOT_USED) {
+ result = MS_STATUS_ERROR;
+ goto exit;
+ }
+
+ /* write protect */
+ if ((extdat.status0 & MS_REG_ST0_WP) == MS_REG_ST0_WP_ON)
+ ms_lib_ctrl_set(info, MS_LIB_CTRL_WRPROTECT);
+
+ result = MS_STATUS_ERROR;
+ /* 1st Boot Block */
+ if (btBlk1stErred == 0)
+ result = ms_lib_process_bootblock(us, btBlk1st, PageBuffer1);
+ /* 1st */
+ /* 2nd Boot Block */
+ if (result && (btBlk2nd != MS_LB_NOT_USED))
+ result = ms_lib_process_bootblock(us, btBlk2nd, PageBuffer0);
+
+ if (result) {
+ result = MS_STATUS_ERROR;
+ goto exit;
+ }
+
+ for (TmpBlock = 0; TmpBlock < btBlk1st; TmpBlock++)
+ info->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR;
+
+ info->MS_Lib.Phy2LogMap[btBlk1st] = MS_LB_BOOT_BLOCK;
+
+ if (btBlk2nd != MS_LB_NOT_USED) {
+ for (TmpBlock = btBlk1st + 1; TmpBlock < btBlk2nd; TmpBlock++)
+ info->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR;
+
+ info->MS_Lib.Phy2LogMap[btBlk2nd] = MS_LB_BOOT_BLOCK;
+ }
+
+ result = ms_lib_scan_logicalblocknumber(us, btBlk1st);
+ if (result)
+ goto exit;
+
+ for (TmpBlock = MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+ TmpBlock < info->MS_Lib.NumberOfPhyBlock;
+ TmpBlock += MS_PHYSICAL_BLOCKS_PER_SEGMENT) {
+ if (ms_count_freeblock(us, TmpBlock) == 0) {
+ ms_lib_ctrl_set(info, MS_LIB_CTRL_WRPROTECT);
+ break;
+ }
+ }
+
+ /* write */
+ if (ms_lib_alloc_writebuf(us)) {
+ result = MS_NO_MEMORY_ERROR;
+ goto exit;
+ }
+
+ result = MS_STATUS_SUCCESS;
+
+exit:
+ kfree(PageBuffer1);
+ kfree(PageBuffer0);
+
+ printk(KERN_INFO "MS_CardInit end\n");
+ return result;
+}
+
+static int ene_ms_init(struct us_data *us)
+{
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ int result;
+ u8 buf[0x200];
+ u16 MSP_BlockSize, MSP_UserAreaBlocks;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ printk(KERN_INFO "transport --- ENE_MSInit\n");
+
+ /* the same part to test ENE */
+
+ result = ene_load_bincode(us, MS_INIT_PATTERN);
+ if (result != USB_STOR_XFER_GOOD) {
+ printk(KERN_ERR "Load MS Init Code Fail !!\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = 0x200;
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xF1;
+ bcb->CDB[1] = 0x01;
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
+ if (result != USB_STOR_XFER_GOOD) {
+ printk(KERN_ERR "Execution MS Init Code Fail !!\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ /* the same part to test ENE */
+ info->MS_Status = *(struct MS_STATUS *)&buf[0];
+
+ if (info->MS_Status.Insert && info->MS_Status.Ready) {
+ printk(KERN_INFO "Insert = %x\n", info->MS_Status.Insert);
+ printk(KERN_INFO "Ready = %x\n", info->MS_Status.Ready);
+ printk(KERN_INFO "IsMSPro = %x\n", info->MS_Status.IsMSPro);
+ printk(KERN_INFO "IsMSPHG = %x\n", info->MS_Status.IsMSPHG);
+ printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP);
+ if (info->MS_Status.IsMSPro) {
+ MSP_BlockSize = (buf[6] << 8) | buf[7];
+ MSP_UserAreaBlocks = (buf[10] << 8) | buf[11];
+ info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks;
+ } else {
+ ms_card_init(us); /* Card is MS (to ms.c)*/
+ }
+ usb_stor_dbg(us, "MS Init Code OK !!\n");
+ } else {
+ usb_stor_dbg(us, "MS Card Not Ready --- %x\n", buf[0]);
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ene_sd_init(struct us_data *us)
+{
+ int result;
+ u8 buf[0x200];
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ usb_stor_dbg(us, "transport --- ENE_SDInit\n");
+ /* SD Init Part-1 */
+ result = ene_load_bincode(us, SD_INIT1_PATTERN);
+ if (result != USB_STOR_XFER_GOOD) {
+ usb_stor_dbg(us, "Load SD Init Code Part-1 Fail !!\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xF2;
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);
+ if (result != USB_STOR_XFER_GOOD) {
+ usb_stor_dbg(us, "Execution SD Init Code Fail !!\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ /* SD Init Part-2 */
+ result = ene_load_bincode(us, SD_INIT2_PATTERN);
+ if (result != USB_STOR_XFER_GOOD) {
+ usb_stor_dbg(us, "Load SD Init Code Part-2 Fail !!\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = 0x200;
+ bcb->Flags = US_BULK_FLAG_IN;
+ bcb->CDB[0] = 0xF1;
+
+ result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
+ if (result != USB_STOR_XFER_GOOD) {
+ usb_stor_dbg(us, "Execution SD Init Code Fail !!\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ info->SD_Status = *(struct SD_STATUS *)&buf[0];
+ if (info->SD_Status.Insert && info->SD_Status.Ready) {
+ struct SD_STATUS *s = &info->SD_Status;
+
+ ene_get_card_status(us, (unsigned char *)&buf);
+ usb_stor_dbg(us, "Insert = %x\n", s->Insert);
+ usb_stor_dbg(us, "Ready = %x\n", s->Ready);
+ usb_stor_dbg(us, "IsMMC = %x\n", s->IsMMC);
+ usb_stor_dbg(us, "HiCapacity = %x\n", s->HiCapacity);
+ usb_stor_dbg(us, "HiSpeed = %x\n", s->HiSpeed);
+ usb_stor_dbg(us, "WtP = %x\n", s->WtP);
+ } else {
+ usb_stor_dbg(us, "SD Card Not Ready --- %x\n", buf[0]);
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+
+static int ene_init(struct us_data *us)
+{
+ int result;
+ u8 misc_reg03 = 0;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+ result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ if (misc_reg03 & 0x01) {
+ if (!info->SD_Status.Ready) {
+ result = ene_sd_init(us);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ }
+ if (misc_reg03 & 0x02) {
+ if (!info->MS_Status.Ready) {
+ result = ene_ms_init(us);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ }
+ return result;
+}
+
+/*----- sd_scsi_irp() ---------*/
+static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+{
+ int result;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra;
+
+ info->SrbStatus = SS_SUCCESS;
+ switch (srb->cmnd[0]) {
+ case TEST_UNIT_READY:
+ result = sd_scsi_test_unit_ready(us, srb);
+ break; /* 0x00 */
+ case INQUIRY:
+ result = sd_scsi_inquiry(us, srb);
+ break; /* 0x12 */
+ case MODE_SENSE:
+ result = sd_scsi_mode_sense(us, srb);
+ break; /* 0x1A */
+ /*
+ case START_STOP:
+ result = SD_SCSI_Start_Stop(us, srb);
+ break; //0x1B
+ */
+ case READ_CAPACITY:
+ result = sd_scsi_read_capacity(us, srb);
+ break; /* 0x25 */
+ case READ_10:
+ result = sd_scsi_read(us, srb);
+ break; /* 0x28 */
+ case WRITE_10:
+ result = sd_scsi_write(us, srb);
+ break; /* 0x2A */
+ default:
+ info->SrbStatus = SS_ILLEGAL_REQUEST;
+ result = USB_STOR_TRANSPORT_FAILED;
+ break;
+ }
+ return result;
+}
+
+/*
+ * ms_scsi_irp()
+ */
+static int ms_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+{
+ int result;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra;
+ info->SrbStatus = SS_SUCCESS;
+ switch (srb->cmnd[0]) {
+ case TEST_UNIT_READY:
+ result = ms_scsi_test_unit_ready(us, srb);
+ break; /* 0x00 */
+ case INQUIRY:
+ result = ms_scsi_inquiry(us, srb);
+ break; /* 0x12 */
+ case MODE_SENSE:
+ result = ms_scsi_mode_sense(us, srb);
+ break; /* 0x1A */
+ case READ_CAPACITY:
+ result = ms_scsi_read_capacity(us, srb);
+ break; /* 0x25 */
+ case READ_10:
+ result = ms_scsi_read(us, srb);
+ break; /* 0x28 */
+ case WRITE_10:
+ result = ms_scsi_write(us, srb);
+ break; /* 0x2A */
+ default:
+ info->SrbStatus = SS_ILLEGAL_REQUEST;
+ result = USB_STOR_TRANSPORT_FAILED;
+ break;
+ }
+ return result;
+}
+
+static int ene_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+ int result = 0;
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+ /*US_DEBUG(usb_stor_show_command(us, srb)); */
+ scsi_set_resid(srb, 0);
+ if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready))) {
+ result = ene_init(us);
+ } else {
+ if (info->SD_Status.Ready)
+ result = sd_scsi_irp(us, srb);
+
+ if (info->MS_Status.Ready)
+ result = ms_scsi_irp(us, srb);
+ }
+ return 0;
+}
+
+
+static int ene_ub6250_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ int result;
+ u8 misc_reg03 = 0;
+ struct us_data *us;
+
+ result = usb_stor_probe1(&us, intf, id,
+ (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list);
+ if (result)
+ return result;
+
+ /* FIXME: where should the code alloc extra buf ? */
+ if (!us->extra) {
+ us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL);
+ if (!us->extra)
+ return -ENOMEM;
+ us->extra_destructor = ene_ub6250_info_destructor;
+ }
+
+ us->transport_name = "ene_ub6250";
+ us->transport = ene_transport;
+ us->max_lun = 0;
+
+ result = usb_stor_probe2(us);
+ if (result)
+ return result;
+
+ /* probe card type */
+ result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
+ if (result != USB_STOR_XFER_GOOD) {
+ usb_stor_disconnect(intf);
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ if (!(misc_reg03 & 0x01)) {
+ pr_info("ums_eneub6250: The driver only supports SD/MS card. "
+ "To use SM card, please build driver/staging/keucr\n");
+ }
+
+ return result;
+}
+
+
+#ifdef CONFIG_PM
+
+static int ene_ub6250_resume(struct usb_interface *iface)
+{
+ u8 tmp = 0;
+ struct us_data *us = usb_get_intfdata(iface);
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+ mutex_lock(&us->dev_mutex);
+
+ if (us->suspend_resume_hook)
+ (us->suspend_resume_hook)(us, US_RESUME);
+
+ mutex_unlock(&us->dev_mutex);
+
+ info->Power_IsResum = true;
+ /*info->SD_Status.Ready = 0; */
+ info->SD_Status = *(struct SD_STATUS *)&tmp;
+ info->MS_Status = *(struct MS_STATUS *)&tmp;
+ info->SM_Status = *(struct SM_STATUS *)&tmp;
+
+ return 0;
+}
+
+static int ene_ub6250_reset_resume(struct usb_interface *iface)
+{
+ u8 tmp = 0;
+ struct us_data *us = usb_get_intfdata(iface);
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+ /* Report the reset to the SCSI core */
+ usb_stor_reset_resume(iface);
+
+ /* FIXME: Notify the subdrivers that they need to reinitialize
+ * the device */
+ info->Power_IsResum = true;
+ /*info->SD_Status.Ready = 0; */
+ info->SD_Status = *(struct SD_STATUS *)&tmp;
+ info->MS_Status = *(struct MS_STATUS *)&tmp;
+ info->SM_Status = *(struct SM_STATUS *)&tmp;
+
+ return 0;
+}
+
+#else
+
+#define ene_ub6250_resume NULL
+#define ene_ub6250_reset_resume NULL
+
+#endif
+
+static struct usb_driver ene_ub6250_driver = {
+ .name = "ums_eneub6250",
+ .probe = ene_ub6250_probe,
+ .disconnect = usb_stor_disconnect,
+ .suspend = usb_stor_suspend,
+ .resume = ene_ub6250_resume,
+ .reset_resume = ene_ub6250_reset_resume,
+ .pre_reset = usb_stor_pre_reset,
+ .post_reset = usb_stor_post_reset,
+ .id_table = ene_ub6250_usb_ids,
+ .soft_unbind = 1,
+ .no_dynamic_id = 1,
+};
+
+module_usb_driver(ene_ub6250_driver);
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index 6542ca40d50..ef16068b708 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -40,7 +40,7 @@ MODULE_AUTHOR("David Brown <usb-storage@davidb.org>");
MODULE_LICENSE("GPL");
#ifdef CONFIG_USB_STORAGE_DEBUG
-static void pdump (void *, int);
+static void pdump(struct us_data *us, void *ibuffer, int length);
#endif
/* Bits of HD_STATUS */
@@ -117,9 +117,9 @@ static int init_freecom(struct us_data *us);
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
- .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ .driver_info = (flags) }
-struct usb_device_id freecom_usb_ids[] = {
+static struct usb_device_id freecom_usb_ids[] = {
# include "unusual_freecom.h"
{ } /* Terminating entry */
};
@@ -161,20 +161,20 @@ freecom_readdata (struct scsi_cmnd *srb, struct us_data *us,
fxfr->Count = cpu_to_le32 (count);
memset (fxfr->Pad, 0, sizeof (fxfr->Pad));
- US_DEBUGP("Read data Freecom! (c=%d)\n", count);
+ usb_stor_dbg(us, "Read data Freecom! (c=%d)\n", count);
/* Issue the transfer command. */
result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,
FCM_PACKET_LENGTH, NULL);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP ("Freecom readdata transport error\n");
+ usb_stor_dbg(us, "Freecom readdata transport error\n");
return USB_STOR_TRANSPORT_ERROR;
}
/* Now transfer all of our blocks. */
- US_DEBUGP("Start of read\n");
+ usb_stor_dbg(us, "Start of read\n");
result = usb_stor_bulk_srb(us, ipipe, srb);
- US_DEBUGP("freecom_readdata done!\n");
+ usb_stor_dbg(us, "freecom_readdata done!\n");
if (result > USB_STOR_XFER_SHORT)
return USB_STOR_TRANSPORT_ERROR;
@@ -194,21 +194,21 @@ freecom_writedata (struct scsi_cmnd *srb, struct us_data *us,
fxfr->Count = cpu_to_le32 (count);
memset (fxfr->Pad, 0, sizeof (fxfr->Pad));
- US_DEBUGP("Write data Freecom! (c=%d)\n", count);
+ usb_stor_dbg(us, "Write data Freecom! (c=%d)\n", count);
/* Issue the transfer command. */
result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,
FCM_PACKET_LENGTH, NULL);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP ("Freecom writedata transport error\n");
+ usb_stor_dbg(us, "Freecom writedata transport error\n");
return USB_STOR_TRANSPORT_ERROR;
}
/* Now transfer all of our blocks. */
- US_DEBUGP("Start of write\n");
+ usb_stor_dbg(us, "Start of write\n");
result = usb_stor_bulk_srb(us, opipe, srb);
- US_DEBUGP("freecom_writedata done!\n");
+ usb_stor_dbg(us, "freecom_writedata done!\n");
if (result > USB_STOR_XFER_SHORT)
return USB_STOR_TRANSPORT_ERROR;
return USB_STOR_TRANSPORT_GOOD;
@@ -230,7 +230,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
fcb = (struct freecom_cb_wrap *) us->iobuf;
fst = (struct freecom_status *) us->iobuf;
- US_DEBUGP("Freecom TRANSPORT STARTED\n");
+ usb_stor_dbg(us, "Freecom TRANSPORT STARTED\n");
/* Get handles for both transports. */
opipe = us->send_bulk_pipe;
@@ -242,7 +242,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
memcpy (fcb->Atapi, srb->cmnd, 12);
memset (fcb->Filler, 0, sizeof (fcb->Filler));
- US_DEBUG(pdump (srb->cmnd, 12));
+ US_DEBUG(pdump(us, srb->cmnd, 12));
/* Send it out. */
result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
@@ -252,7 +252,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
* USB land. It returns the status in its own registers, which
* come back in the bulk pipe. */
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP ("freecom transport error\n");
+ usb_stor_dbg(us, "freecom transport error\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -260,11 +260,11 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
* doesn't hurt us to always do it now. */
result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
FCM_STATUS_PACKET_LENGTH, &partial);
- US_DEBUGP("foo Status result %d %u\n", result, partial);
+ usb_stor_dbg(us, "foo Status result %d %u\n", result, partial);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUG(pdump ((void *) fst, partial));
+ US_DEBUG(pdump(us, (void *)fst, partial));
/* The firmware will time-out commands after 20 seconds. Some commands
* can legitimately take longer than this, so we use a different
@@ -275,8 +275,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
* may not work, but that is a condition that should never happen.
*/
while (fst->Status & FCM_STATUS_BUSY) {
- US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occurred!\n");
- US_DEBUGP("fst->Status is %x\n", fst->Status);
+ usb_stor_dbg(us, "20 second USB/ATAPI bridge TIMEOUT occurred!\n");
+ usb_stor_dbg(us, "fst->Status is %x\n", fst->Status);
/* Get the status again */
fcb->Type = FCM_PACKET_STATUS;
@@ -293,7 +293,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
* registers, which come back in the bulk pipe.
*/
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP ("freecom transport error\n");
+ usb_stor_dbg(us, "freecom transport error\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -301,26 +301,26 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
FCM_STATUS_PACKET_LENGTH, &partial);
- US_DEBUGP("bar Status result %d %u\n", result, partial);
+ usb_stor_dbg(us, "bar Status result %d %u\n", result, partial);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUG(pdump ((void *) fst, partial));
+ US_DEBUG(pdump(us, (void *)fst, partial));
}
if (partial != 4)
return USB_STOR_TRANSPORT_ERROR;
if ((fst->Status & 1) != 0) {
- US_DEBUGP("operation failed\n");
+ usb_stor_dbg(us, "operation failed\n");
return USB_STOR_TRANSPORT_FAILED;
}
/* The device might not have as much data available as we
* requested. If you ask for more than the device has, this reads
* and such will hang. */
- US_DEBUGP("Device indicates that it has %d bytes available\n",
- le16_to_cpu (fst->Count));
- US_DEBUGP("SCSI requested %d\n", scsi_bufflen(srb));
+ usb_stor_dbg(us, "Device indicates that it has %d bytes available\n",
+ le16_to_cpu(fst->Count));
+ usb_stor_dbg(us, "SCSI requested %d\n", scsi_bufflen(srb));
/* Find the length we desire to read. */
switch (srb->cmnd[0]) {
@@ -337,7 +337,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
/* verify that this amount is legal */
if (length > scsi_bufflen(srb)) {
length = scsi_bufflen(srb);
- US_DEBUGP("Truncating request to match buffer length: %d\n", length);
+ usb_stor_dbg(us, "Truncating request to match buffer length: %d\n",
+ length);
}
/* What we do now depends on what direction the data is supposed to
@@ -351,29 +352,29 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
/* Make sure that the status indicates that the device
* wants data as well. */
if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) {
- US_DEBUGP("SCSI wants data, drive doesn't have any\n");
+ usb_stor_dbg(us, "SCSI wants data, drive doesn't have any\n");
return USB_STOR_TRANSPORT_FAILED;
}
result = freecom_readdata (srb, us, ipipe, opipe, length);
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
- US_DEBUGP("FCM: Waiting for status\n");
+ usb_stor_dbg(us, "Waiting for status\n");
result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
FCM_PACKET_LENGTH, &partial);
- US_DEBUG(pdump ((void *) fst, partial));
+ US_DEBUG(pdump(us, (void *)fst, partial));
if (partial != 4 || result > USB_STOR_XFER_SHORT)
return USB_STOR_TRANSPORT_ERROR;
if ((fst->Status & ERR_STAT) != 0) {
- US_DEBUGP("operation failed\n");
+ usb_stor_dbg(us, "operation failed\n");
return USB_STOR_TRANSPORT_FAILED;
}
if ((fst->Reason & 3) != 3) {
- US_DEBUGP("Drive seems still hungry\n");
+ usb_stor_dbg(us, "Drive seems still hungry\n");
return USB_STOR_TRANSPORT_FAILED;
}
- US_DEBUGP("Transfer happy\n");
+ usb_stor_dbg(us, "Transfer happy\n");
break;
case DMA_TO_DEVICE:
@@ -387,22 +388,22 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
- US_DEBUGP("FCM: Waiting for status\n");
+ usb_stor_dbg(us, "Waiting for status\n");
result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
FCM_PACKET_LENGTH, &partial);
if (partial != 4 || result > USB_STOR_XFER_SHORT)
return USB_STOR_TRANSPORT_ERROR;
if ((fst->Status & ERR_STAT) != 0) {
- US_DEBUGP("operation failed\n");
+ usb_stor_dbg(us, "operation failed\n");
return USB_STOR_TRANSPORT_FAILED;
}
if ((fst->Reason & 3) != 3) {
- US_DEBUGP("Drive seems still hungry\n");
+ usb_stor_dbg(us, "Drive seems still hungry\n");
return USB_STOR_TRANSPORT_FAILED;
}
- US_DEBUGP("Transfer happy\n");
+ usb_stor_dbg(us, "Transfer happy\n");
break;
@@ -412,8 +413,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
default:
/* should never hit here -- filtered in usb.c */
- US_DEBUGP ("freecom unimplemented direction: %d\n",
- us->srb->sc_data_direction);
+ usb_stor_dbg(us, "freecom unimplemented direction: %d\n",
+ us->srb->sc_data_direction);
/* Return fail, SCSI seems to handle this better. */
return USB_STOR_TRANSPORT_FAILED;
break;
@@ -434,7 +435,7 @@ static int init_freecom(struct us_data *us)
result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);
buffer[32] = '\0';
- US_DEBUGP("String returned from FC init is: %s\n", buffer);
+ usb_stor_dbg(us, "String returned from FC init is: %s\n", buffer);
/* Special thanks to the people at Freecom for providing me with
* this "magic sequence", which they use in their Windows and MacOS
@@ -445,7 +446,7 @@ static int init_freecom(struct us_data *us)
/* send reset */
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ);
- US_DEBUGP("result from activate reset is %d\n", result);
+ usb_stor_dbg(us, "result from activate reset is %d\n", result);
/* wait 250ms */
mdelay(250);
@@ -453,7 +454,7 @@ static int init_freecom(struct us_data *us)
/* clear reset */
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ);
- US_DEBUGP("result from clear reset is %d\n", result);
+ usb_stor_dbg(us, "result from clear reset is %d\n", result);
/* wait 3 seconds */
mdelay(3 * 1000);
@@ -470,7 +471,7 @@ static int usb_stor_freecom_reset(struct us_data *us)
}
#ifdef CONFIG_USB_STORAGE_DEBUG
-static void pdump (void *ibuffer, int length)
+static void pdump(struct us_data *us, void *ibuffer, int length)
{
static char line[80];
int offset = 0;
@@ -490,7 +491,7 @@ static void pdump (void *ibuffer, int length)
line[offset++] = '.';
}
line[offset] = 0;
- US_DEBUGP("%s\n", line);
+ usb_stor_dbg(us, "%s\n", line);
offset = 0;
}
offset += sprintf (line+offset, "%08x:", i);
@@ -517,7 +518,7 @@ static void pdump (void *ibuffer, int length)
line[offset++] = '.';
}
line[offset] = 0;
- US_DEBUGP("%s\n", line);
+ usb_stor_dbg(us, "%s\n", line);
offset = 0;
}
#endif
@@ -553,17 +554,7 @@ static struct usb_driver freecom_driver = {
.post_reset = usb_stor_post_reset,
.id_table = freecom_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
-static int __init freecom_init(void)
-{
- return usb_register(&freecom_driver);
-}
-
-static void __exit freecom_exit(void)
-{
- usb_deregister(&freecom_driver);
-}
-
-module_init(freecom_init);
-module_exit(freecom_exit);
+module_usb_driver(freecom_driver);
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index 105d900150c..5a8b5ff1e45 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -48,12 +48,12 @@ int usb_stor_euscsi_init(struct us_data *us)
{
int result;
- US_DEBUGP("Attempting to init eUSCSI bridge...\n");
+ usb_stor_dbg(us, "Attempting to init eUSCSI bridge...\n");
us->iobuf[0] = 0x1;
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,
0x01, 0x0, us->iobuf, 0x1, 5000);
- US_DEBUGP("-- result is %d\n", result);
+ usb_stor_dbg(us, "-- result is %d\n", result);
return 0;
}
@@ -68,7 +68,7 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
unsigned int partial;
static char init_string[] = "\xec\x0a\x06\x00$PCCHIPS";
- US_DEBUGP("Sending UCR-61S2B initialization packet...\n");
+ usb_stor_dbg(us, "Sending UCR-61S2B initialization packet...\n");
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->Tag = 0;
@@ -83,7 +83,7 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
if (res)
return -EIO;
- US_DEBUGP("Getting status packet...\n");
+ usb_stor_dbg(us, "Getting status packet...\n");
res = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
US_BULK_CS_WRAP_LEN, &partial);
if (res)
@@ -101,6 +101,6 @@ int usb_stor_huawei_e220_init(struct us_data *us)
USB_REQ_SET_FEATURE,
USB_TYPE_STANDARD | USB_RECIP_DEVICE,
0x01, 0x0, NULL, 0x0, 1000);
- US_DEBUGP("Huawei mode set result is %d\n", result);
+ usb_stor_dbg(us, "Huawei mode set result is %d\n", result);
return 0;
}
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 6b9982cd542..599d8bff26c 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -61,7 +61,7 @@
#include "scsiglue.h"
MODULE_DESCRIPTION("Driver for In-System Design, Inc. ISD200 ASIC");
-MODULE_AUTHOR("Björn Stenberg <bjorn@haxx.se>");
+MODULE_AUTHOR("Björn Stenberg <bjorn@haxx.se>");
MODULE_LICENSE("GPL");
static int isd200_Initialization(struct us_data *us);
@@ -74,16 +74,15 @@ static int isd200_Initialization(struct us_data *us);
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
- .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ .driver_info = (flags) }
-struct usb_device_id isd200_usb_ids[] = {
+static struct usb_device_id isd200_usb_ids[] = {
# include "unusual_isd200.h"
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, isd200_usb_ids);
#undef UNUSUAL_DEV
-#undef USUAL_DEV
/*
* The flags table
@@ -105,8 +104,6 @@ static struct us_unusual_dev isd200_unusual_dev_list[] = {
};
#undef UNUSUAL_DEV
-#undef USUAL_DEV
-
/* Timeout defines (in Seconds) */
@@ -499,7 +496,6 @@ static int isd200_action( struct us_data *us, int action,
memset(&ata, 0, sizeof(ata));
srb->cmnd = info->cmnd;
srb->device = &srb_dev;
- ++srb->serial_number;
ata.generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
ata.generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
@@ -507,7 +503,7 @@ static int isd200_action( struct us_data *us, int action,
switch ( action ) {
case ACTION_READ_STATUS:
- US_DEBUGP(" isd200_action(READ_STATUS)\n");
+ usb_stor_dbg(us, " isd200_action(READ_STATUS)\n");
ata.generic.ActionSelect = ACTION_SELECT_0|ACTION_SELECT_2;
ata.generic.RegisterSelect =
REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
@@ -516,7 +512,7 @@ static int isd200_action( struct us_data *us, int action,
break;
case ACTION_ENUM:
- US_DEBUGP(" isd200_action(ENUM,0x%02x)\n",value);
+ usb_stor_dbg(us, " isd200_action(ENUM,0x%02x)\n", value);
ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
ACTION_SELECT_3|ACTION_SELECT_4|
ACTION_SELECT_5;
@@ -526,7 +522,7 @@ static int isd200_action( struct us_data *us, int action,
break;
case ACTION_RESET:
- US_DEBUGP(" isd200_action(RESET)\n");
+ usb_stor_dbg(us, " isd200_action(RESET)\n");
ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
ACTION_SELECT_3|ACTION_SELECT_4;
ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
@@ -535,7 +531,7 @@ static int isd200_action( struct us_data *us, int action,
break;
case ACTION_REENABLE:
- US_DEBUGP(" isd200_action(REENABLE)\n");
+ usb_stor_dbg(us, " isd200_action(REENABLE)\n");
ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
ACTION_SELECT_3|ACTION_SELECT_4;
ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
@@ -544,7 +540,7 @@ static int isd200_action( struct us_data *us, int action,
break;
case ACTION_SOFT_RESET:
- US_DEBUGP(" isd200_action(SOFT_RESET)\n");
+ usb_stor_dbg(us, " isd200_action(SOFT_RESET)\n");
ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_5;
ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND;
ata.write.DeviceHeadByte = info->DeviceHead;
@@ -553,7 +549,7 @@ static int isd200_action( struct us_data *us, int action,
break;
case ACTION_IDENTIFY:
- US_DEBUGP(" isd200_action(IDENTIFY)\n");
+ usb_stor_dbg(us, " isd200_action(IDENTIFY)\n");
ata.generic.RegisterSelect = REG_COMMAND;
ata.write.CommandByte = ATA_CMD_ID_ATA;
isd200_set_srb(info, DMA_FROM_DEVICE, info->id,
@@ -561,7 +557,7 @@ static int isd200_action( struct us_data *us, int action,
break;
default:
- US_DEBUGP("Error: Undefined action %d\n",action);
+ usb_stor_dbg(us, "Error: Undefined action %d\n", action);
return ISD200_ERROR;
}
@@ -571,7 +567,8 @@ static int isd200_action( struct us_data *us, int action,
if (status == USB_STOR_TRANSPORT_GOOD)
status = ISD200_GOOD;
else {
- US_DEBUGP(" isd200_action(0x%02x) error: %d\n",action,status);
+ usb_stor_dbg(us, " isd200_action(0x%02x) error: %d\n",
+ action, status);
status = ISD200_ERROR;
/* need to reset device here */
}
@@ -593,17 +590,17 @@ static int isd200_read_regs( struct us_data *us )
int retStatus = ISD200_GOOD;
int transferStatus;
- US_DEBUGP("Entering isd200_IssueATAReadRegs\n");
+ usb_stor_dbg(us, "Entering isd200_IssueATAReadRegs\n");
transferStatus = isd200_action( us, ACTION_READ_STATUS,
info->RegsBuf, sizeof(info->ATARegs) );
if (transferStatus != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" Error reading ATA registers\n");
+ usb_stor_dbg(us, " Error reading ATA registers\n");
retStatus = ISD200_ERROR;
} else {
memcpy(info->ATARegs, info->RegsBuf, sizeof(info->ATARegs));
- US_DEBUGP(" Got ATA Register[ATA_REG_ERROR_OFFSET] = 0x%x\n",
- info->ATARegs[ATA_REG_ERROR_OFFSET]);
+ usb_stor_dbg(us, " Got ATA Register[ATA_REG_ERROR_OFFSET] = 0x%x\n",
+ info->ATARegs[ATA_REG_ERROR_OFFSET]);
}
return retStatus;
@@ -633,7 +630,7 @@ static void isd200_invoke_transport( struct us_data *us,
* short-circuit all other processing
*/
if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
- US_DEBUGP("-- command was aborted\n");
+ usb_stor_dbg(us, "-- command was aborted\n");
goto Handle_Abort;
}
@@ -645,23 +642,23 @@ static void isd200_invoke_transport( struct us_data *us,
break;
case USB_STOR_TRANSPORT_NO_SENSE:
- US_DEBUGP("-- transport indicates protocol failure\n");
+ usb_stor_dbg(us, "-- transport indicates protocol failure\n");
srb->result = SAM_STAT_CHECK_CONDITION;
return;
case USB_STOR_TRANSPORT_FAILED:
- US_DEBUGP("-- transport indicates command failure\n");
+ usb_stor_dbg(us, "-- transport indicates command failure\n");
need_auto_sense = 1;
break;
case USB_STOR_TRANSPORT_ERROR:
- US_DEBUGP("-- transport indicates transport error\n");
+ usb_stor_dbg(us, "-- transport indicates transport error\n");
srb->result = DID_ERROR << 16;
/* Need reset here */
return;
default:
- US_DEBUGP("-- transport indicates unknown error\n");
+ usb_stor_dbg(us, "-- transport indicates unknown error\n");
srb->result = DID_ERROR << 16;
/* Need reset here */
return;
@@ -673,14 +670,14 @@ static void isd200_invoke_transport( struct us_data *us,
(srb->cmnd[0] == MODE_SENSE) ||
(srb->cmnd[0] == LOG_SENSE) ||
(srb->cmnd[0] == MODE_SENSE_10))) {
- US_DEBUGP("-- unexpectedly short transfer\n");
+ usb_stor_dbg(us, "-- unexpectedly short transfer\n");
need_auto_sense = 1;
}
if (need_auto_sense) {
result = isd200_read_regs(us);
if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
- US_DEBUGP("-- auto-sense aborted\n");
+ usb_stor_dbg(us, "-- auto-sense aborted\n");
goto Handle_Abort;
}
if (result == ISD200_GOOD) {
@@ -714,40 +711,40 @@ static void isd200_invoke_transport( struct us_data *us,
}
#ifdef CONFIG_USB_STORAGE_DEBUG
-static void isd200_log_config( struct isd200_info* info )
+static void isd200_log_config(struct us_data *us, struct isd200_info *info)
{
- US_DEBUGP(" Event Notification: 0x%x\n",
- info->ConfigData.EventNotification);
- US_DEBUGP(" External Clock: 0x%x\n",
- info->ConfigData.ExternalClock);
- US_DEBUGP(" ATA Init Timeout: 0x%x\n",
- info->ConfigData.ATAInitTimeout);
- US_DEBUGP(" ATAPI Command Block Size: 0x%x\n",
- (info->ConfigData.ATAConfig & ATACFG_BLOCKSIZE) >> 6);
- US_DEBUGP(" Master/Slave Selection: 0x%x\n",
- info->ConfigData.ATAConfig & ATACFG_MASTER);
- US_DEBUGP(" ATAPI Reset: 0x%x\n",
- info->ConfigData.ATAConfig & ATACFG_ATAPI_RESET);
- US_DEBUGP(" ATA Timing: 0x%x\n",
- info->ConfigData.ATAConfig & ATACFG_TIMING);
- US_DEBUGP(" ATA Major Command: 0x%x\n",
- info->ConfigData.ATAMajorCommand);
- US_DEBUGP(" ATA Minor Command: 0x%x\n",
- info->ConfigData.ATAMinorCommand);
- US_DEBUGP(" Init Status: 0x%x\n",
- info->ConfigData.ATAExtraConfig & ATACFGE_INIT_STATUS);
- US_DEBUGP(" Config Descriptor 2: 0x%x\n",
- info->ConfigData.ATAExtraConfig & ATACFGE_CONF_DESC2);
- US_DEBUGP(" Skip Device Boot: 0x%x\n",
- info->ConfigData.ATAExtraConfig & ATACFGE_SKIP_BOOT);
- US_DEBUGP(" ATA 3 State Supsend: 0x%x\n",
- info->ConfigData.ATAExtraConfig & ATACFGE_STATE_SUSPEND);
- US_DEBUGP(" Descriptor Override: 0x%x\n",
- info->ConfigData.ATAExtraConfig & ATACFGE_DESC_OVERRIDE);
- US_DEBUGP(" Last LUN Identifier: 0x%x\n",
- info->ConfigData.ATAExtraConfig & ATACFGE_LAST_LUN);
- US_DEBUGP(" SRST Enable: 0x%x\n",
- info->ConfigData.ATAExtraConfig & CFG_CAPABILITY_SRST);
+ usb_stor_dbg(us, " Event Notification: 0x%x\n",
+ info->ConfigData.EventNotification);
+ usb_stor_dbg(us, " External Clock: 0x%x\n",
+ info->ConfigData.ExternalClock);
+ usb_stor_dbg(us, " ATA Init Timeout: 0x%x\n",
+ info->ConfigData.ATAInitTimeout);
+ usb_stor_dbg(us, " ATAPI Command Block Size: 0x%x\n",
+ (info->ConfigData.ATAConfig & ATACFG_BLOCKSIZE) >> 6);
+ usb_stor_dbg(us, " Master/Slave Selection: 0x%x\n",
+ info->ConfigData.ATAConfig & ATACFG_MASTER);
+ usb_stor_dbg(us, " ATAPI Reset: 0x%x\n",
+ info->ConfigData.ATAConfig & ATACFG_ATAPI_RESET);
+ usb_stor_dbg(us, " ATA Timing: 0x%x\n",
+ info->ConfigData.ATAConfig & ATACFG_TIMING);
+ usb_stor_dbg(us, " ATA Major Command: 0x%x\n",
+ info->ConfigData.ATAMajorCommand);
+ usb_stor_dbg(us, " ATA Minor Command: 0x%x\n",
+ info->ConfigData.ATAMinorCommand);
+ usb_stor_dbg(us, " Init Status: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & ATACFGE_INIT_STATUS);
+ usb_stor_dbg(us, " Config Descriptor 2: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & ATACFGE_CONF_DESC2);
+ usb_stor_dbg(us, " Skip Device Boot: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & ATACFGE_SKIP_BOOT);
+ usb_stor_dbg(us, " ATA 3 State Supsend: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & ATACFGE_STATE_SUSPEND);
+ usb_stor_dbg(us, " Descriptor Override: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & ATACFGE_DESC_OVERRIDE);
+ usb_stor_dbg(us, " Last LUN Identifier: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & ATACFGE_LAST_LUN);
+ usb_stor_dbg(us, " SRST Enable: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & CFG_CAPABILITY_SRST);
}
#endif
@@ -766,9 +763,9 @@ static int isd200_write_config( struct us_data *us )
int result;
#ifdef CONFIG_USB_STORAGE_DEBUG
- US_DEBUGP("Entering isd200_write_config\n");
- US_DEBUGP(" Writing the following ISD200 Config Data:\n");
- isd200_log_config(info);
+ usb_stor_dbg(us, "Entering isd200_write_config\n");
+ usb_stor_dbg(us, " Writing the following ISD200 Config Data:\n");
+ isd200_log_config(us, info);
#endif
/* let's send the command via the control pipe */
@@ -783,13 +780,13 @@ static int isd200_write_config( struct us_data *us )
sizeof(info->ConfigData));
if (result >= 0) {
- US_DEBUGP(" ISD200 Config Data was written successfully\n");
+ usb_stor_dbg(us, " ISD200 Config Data was written successfully\n");
} else {
- US_DEBUGP(" Request to write ISD200 Config Data failed!\n");
+ usb_stor_dbg(us, " Request to write ISD200 Config Data failed!\n");
retStatus = ISD200_ERROR;
}
- US_DEBUGP("Leaving isd200_write_config %08X\n", retStatus);
+ usb_stor_dbg(us, "Leaving isd200_write_config %08X\n", retStatus);
return retStatus;
}
@@ -808,7 +805,7 @@ static int isd200_read_config( struct us_data *us )
int retStatus = ISD200_GOOD;
int result;
- US_DEBUGP("Entering isd200_read_config\n");
+ usb_stor_dbg(us, "Entering isd200_read_config\n");
/* read the configuration information from ISD200. Use this to */
/* determine what the special ATA CDB bytes are. */
@@ -825,16 +822,16 @@ static int isd200_read_config( struct us_data *us )
if (result >= 0) {
- US_DEBUGP(" Retrieved the following ISD200 Config Data:\n");
+ usb_stor_dbg(us, " Retrieved the following ISD200 Config Data:\n");
#ifdef CONFIG_USB_STORAGE_DEBUG
- isd200_log_config(info);
+ isd200_log_config(us, info);
#endif
} else {
- US_DEBUGP(" Request to get ISD200 Config Data failed!\n");
+ usb_stor_dbg(us, " Request to get ISD200 Config Data failed!\n");
retStatus = ISD200_ERROR;
}
- US_DEBUGP("Leaving isd200_read_config %08X\n", retStatus);
+ usb_stor_dbg(us, "Leaving isd200_read_config %08X\n", retStatus);
return retStatus;
}
@@ -852,15 +849,15 @@ static int isd200_atapi_soft_reset( struct us_data *us )
int retStatus = ISD200_GOOD;
int transferStatus;
- US_DEBUGP("Entering isd200_atapi_soft_reset\n");
+ usb_stor_dbg(us, "Entering isd200_atapi_soft_reset\n");
transferStatus = isd200_action( us, ACTION_SOFT_RESET, NULL, 0 );
if (transferStatus != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" Error issuing Atapi Soft Reset\n");
+ usb_stor_dbg(us, " Error issuing Atapi Soft Reset\n");
retStatus = ISD200_ERROR;
}
- US_DEBUGP("Leaving isd200_atapi_soft_reset %08X\n", retStatus);
+ usb_stor_dbg(us, "Leaving isd200_atapi_soft_reset %08X\n", retStatus);
return retStatus;
}
@@ -878,13 +875,13 @@ static int isd200_srst( struct us_data *us )
int retStatus = ISD200_GOOD;
int transferStatus;
- US_DEBUGP("Entering isd200_SRST\n");
+ usb_stor_dbg(us, "Entering isd200_SRST\n");
transferStatus = isd200_action( us, ACTION_RESET, NULL, 0 );
/* check to see if this request failed */
if (transferStatus != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" Error issuing SRST\n");
+ usb_stor_dbg(us, " Error issuing SRST\n");
retStatus = ISD200_ERROR;
} else {
/* delay 10ms to give the drive a chance to see it */
@@ -892,7 +889,7 @@ static int isd200_srst( struct us_data *us )
transferStatus = isd200_action( us, ACTION_REENABLE, NULL, 0 );
if (transferStatus != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" Error taking drive out of reset\n");
+ usb_stor_dbg(us, " Error taking drive out of reset\n");
retStatus = ISD200_ERROR;
} else {
/* delay 50ms to give the drive a chance to recover after SRST */
@@ -900,7 +897,7 @@ static int isd200_srst( struct us_data *us )
}
}
- US_DEBUGP("Leaving isd200_srst %08X\n", retStatus);
+ usb_stor_dbg(us, "Leaving isd200_srst %08X\n", retStatus);
return retStatus;
}
@@ -930,10 +927,6 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
/* loop until we detect !BSY or timeout */
while(1) {
-#ifdef CONFIG_USB_STORAGE_DEBUG
- char* mstr = master_slave == ATA_ADDRESS_DEVHEAD_STD ?
- "Master" : "Slave";
-#endif
status = isd200_action( us, ACTION_ENUM, NULL, master_slave );
if ( status != ISD200_GOOD )
@@ -946,9 +939,13 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
if (!detect) {
if (regs[ATA_REG_STATUS_OFFSET] & ATA_BUSY) {
- US_DEBUGP(" %s status is still BSY, try again...\n",mstr);
+ usb_stor_dbg(us, " %s status is still BSY, try again...\n",
+ master_slave == ATA_ADDRESS_DEVHEAD_STD ?
+ "Master" : "Slave");
} else {
- US_DEBUGP(" %s status !BSY, continue with next operation\n",mstr);
+ usb_stor_dbg(us, " %s status !BSY, continue with next operation\n",
+ master_slave == ATA_ADDRESS_DEVHEAD_STD ?
+ "Master" : "Slave");
break;
}
}
@@ -957,11 +954,11 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
/* ATA_ERR (workaround for Archos CD-ROM) */
else if (regs[ATA_REG_STATUS_OFFSET] &
(ATA_BUSY | ATA_DF | ATA_ERR)) {
- US_DEBUGP(" Status indicates it is not ready, try again...\n");
+ usb_stor_dbg(us, " Status indicates it is not ready, try again...\n");
}
/* check for DRDY, ATA devices set DRDY after SRST */
else if (regs[ATA_REG_STATUS_OFFSET] & ATA_DRDY) {
- US_DEBUGP(" Identified ATA device\n");
+ usb_stor_dbg(us, " Identified ATA device\n");
info->DeviceFlags |= DF_ATA_DEVICE;
info->DeviceHead = master_slave;
break;
@@ -982,27 +979,27 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
*/
if ((master_slave & ATA_ADDRESS_DEVHEAD_SLAVE) &&
!recheckAsMaster) {
- US_DEBUGP(" Identified ATAPI device as slave. Rechecking again as master\n");
+ usb_stor_dbg(us, " Identified ATAPI device as slave. Rechecking again as master\n");
recheckAsMaster = 1;
master_slave = ATA_ADDRESS_DEVHEAD_STD;
} else {
- US_DEBUGP(" Identified ATAPI device\n");
+ usb_stor_dbg(us, " Identified ATAPI device\n");
info->DeviceHead = master_slave;
status = isd200_atapi_soft_reset(us);
break;
}
} else {
- US_DEBUGP(" Not ATA, not ATAPI. Weird.\n");
+ usb_stor_dbg(us, " Not ATA, not ATAPI - Weird\n");
break;
}
/* check for timeout on this request */
if (time_after_eq(jiffies, endTime)) {
if (!detect)
- US_DEBUGP(" BSY check timeout, just continue with next operation...\n");
+ usb_stor_dbg(us, " BSY check timeout, just continue with next operation...\n");
else
- US_DEBUGP(" Device detect timeout!\n");
+ usb_stor_dbg(us, " Device detect timeout!\n");
break;
}
}
@@ -1024,7 +1021,7 @@ static int isd200_manual_enum(struct us_data *us)
struct isd200_info *info = (struct isd200_info *)us->extra;
int retStatus = ISD200_GOOD;
- US_DEBUGP("Entering isd200_manual_enum\n");
+ usb_stor_dbg(us, "Entering isd200_manual_enum\n");
retStatus = isd200_read_config(us);
if (retStatus == ISD200_GOOD) {
@@ -1043,14 +1040,15 @@ static int isd200_manual_enum(struct us_data *us)
isslave = (info->DeviceHead & ATA_ADDRESS_DEVHEAD_SLAVE) ? 1 : 0;
if (!(info->ConfigData.ATAConfig & ATACFG_MASTER)) {
- US_DEBUGP(" Setting Master/Slave selection to %d\n", isslave);
+ usb_stor_dbg(us, " Setting Master/Slave selection to %d\n",
+ isslave);
info->ConfigData.ATAConfig &= 0x3f;
info->ConfigData.ATAConfig |= (isslave<<6);
retStatus = isd200_write_config(us);
}
}
- US_DEBUGP("Leaving isd200_manual_enum %08X\n", retStatus);
+ usb_stor_dbg(us, "Leaving isd200_manual_enum %08X\n", retStatus);
return(retStatus);
}
@@ -1068,35 +1066,35 @@ static void isd200_fix_driveid(u16 *id)
#endif
}
-static void isd200_dump_driveid(u16 *id)
+static void isd200_dump_driveid(struct us_data *us, u16 *id)
{
- US_DEBUGP(" Identify Data Structure:\n");
- US_DEBUGP(" config = 0x%x\n", id[ATA_ID_CONFIG]);
- US_DEBUGP(" cyls = 0x%x\n", id[ATA_ID_CYLS]);
- US_DEBUGP(" heads = 0x%x\n", id[ATA_ID_HEADS]);
- US_DEBUGP(" track_bytes = 0x%x\n", id[4]);
- US_DEBUGP(" sector_bytes = 0x%x\n", id[5]);
- US_DEBUGP(" sectors = 0x%x\n", id[ATA_ID_SECTORS]);
- US_DEBUGP(" serial_no[0] = 0x%x\n", *(char *)&id[ATA_ID_SERNO]);
- US_DEBUGP(" buf_type = 0x%x\n", id[20]);
- US_DEBUGP(" buf_size = 0x%x\n", id[ATA_ID_BUF_SIZE]);
- US_DEBUGP(" ecc_bytes = 0x%x\n", id[22]);
- US_DEBUGP(" fw_rev[0] = 0x%x\n", *(char *)&id[ATA_ID_FW_REV]);
- US_DEBUGP(" model[0] = 0x%x\n", *(char *)&id[ATA_ID_PROD]);
- US_DEBUGP(" max_multsect = 0x%x\n", id[ATA_ID_MAX_MULTSECT] & 0xff);
- US_DEBUGP(" dword_io = 0x%x\n", id[ATA_ID_DWORD_IO]);
- US_DEBUGP(" capability = 0x%x\n", id[ATA_ID_CAPABILITY] >> 8);
- US_DEBUGP(" tPIO = 0x%x\n", id[ATA_ID_OLD_PIO_MODES] >> 8);
- US_DEBUGP(" tDMA = 0x%x\n", id[ATA_ID_OLD_DMA_MODES] >> 8);
- US_DEBUGP(" field_valid = 0x%x\n", id[ATA_ID_FIELD_VALID]);
- US_DEBUGP(" cur_cyls = 0x%x\n", id[ATA_ID_CUR_CYLS]);
- US_DEBUGP(" cur_heads = 0x%x\n", id[ATA_ID_CUR_HEADS]);
- US_DEBUGP(" cur_sectors = 0x%x\n", id[ATA_ID_CUR_SECTORS]);
- US_DEBUGP(" cur_capacity = 0x%x\n", ata_id_u32(id, 57));
- US_DEBUGP(" multsect = 0x%x\n", id[ATA_ID_MULTSECT] & 0xff);
- US_DEBUGP(" lba_capacity = 0x%x\n", ata_id_u32(id, ATA_ID_LBA_CAPACITY));
- US_DEBUGP(" command_set_1 = 0x%x\n", id[ATA_ID_COMMAND_SET_1]);
- US_DEBUGP(" command_set_2 = 0x%x\n", id[ATA_ID_COMMAND_SET_2]);
+ usb_stor_dbg(us, " Identify Data Structure:\n");
+ usb_stor_dbg(us, " config = 0x%x\n", id[ATA_ID_CONFIG]);
+ usb_stor_dbg(us, " cyls = 0x%x\n", id[ATA_ID_CYLS]);
+ usb_stor_dbg(us, " heads = 0x%x\n", id[ATA_ID_HEADS]);
+ usb_stor_dbg(us, " track_bytes = 0x%x\n", id[4]);
+ usb_stor_dbg(us, " sector_bytes = 0x%x\n", id[5]);
+ usb_stor_dbg(us, " sectors = 0x%x\n", id[ATA_ID_SECTORS]);
+ usb_stor_dbg(us, " serial_no[0] = 0x%x\n", *(char *)&id[ATA_ID_SERNO]);
+ usb_stor_dbg(us, " buf_type = 0x%x\n", id[20]);
+ usb_stor_dbg(us, " buf_size = 0x%x\n", id[ATA_ID_BUF_SIZE]);
+ usb_stor_dbg(us, " ecc_bytes = 0x%x\n", id[22]);
+ usb_stor_dbg(us, " fw_rev[0] = 0x%x\n", *(char *)&id[ATA_ID_FW_REV]);
+ usb_stor_dbg(us, " model[0] = 0x%x\n", *(char *)&id[ATA_ID_PROD]);
+ usb_stor_dbg(us, " max_multsect = 0x%x\n", id[ATA_ID_MAX_MULTSECT] & 0xff);
+ usb_stor_dbg(us, " dword_io = 0x%x\n", id[ATA_ID_DWORD_IO]);
+ usb_stor_dbg(us, " capability = 0x%x\n", id[ATA_ID_CAPABILITY] >> 8);
+ usb_stor_dbg(us, " tPIO = 0x%x\n", id[ATA_ID_OLD_PIO_MODES] >> 8);
+ usb_stor_dbg(us, " tDMA = 0x%x\n", id[ATA_ID_OLD_DMA_MODES] >> 8);
+ usb_stor_dbg(us, " field_valid = 0x%x\n", id[ATA_ID_FIELD_VALID]);
+ usb_stor_dbg(us, " cur_cyls = 0x%x\n", id[ATA_ID_CUR_CYLS]);
+ usb_stor_dbg(us, " cur_heads = 0x%x\n", id[ATA_ID_CUR_HEADS]);
+ usb_stor_dbg(us, " cur_sectors = 0x%x\n", id[ATA_ID_CUR_SECTORS]);
+ usb_stor_dbg(us, " cur_capacity = 0x%x\n", ata_id_u32(id, 57));
+ usb_stor_dbg(us, " multsect = 0x%x\n", id[ATA_ID_MULTSECT] & 0xff);
+ usb_stor_dbg(us, " lba_capacity = 0x%x\n", ata_id_u32(id, ATA_ID_LBA_CAPACITY));
+ usb_stor_dbg(us, " command_set_1 = 0x%x\n", id[ATA_ID_COMMAND_SET_1]);
+ usb_stor_dbg(us, " command_set_2 = 0x%x\n", id[ATA_ID_COMMAND_SET_2]);
}
/**************************************************************************
@@ -1113,7 +1111,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
int retStatus = ISD200_GOOD;
u16 *id = info->id;
- US_DEBUGP("Entering isd200_get_inquiry_data\n");
+ usb_stor_dbg(us, "Entering isd200_get_inquiry_data\n");
/* set default to Master */
info->DeviceHead = ATA_ADDRESS_DEVHEAD_STD;
@@ -1131,7 +1129,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
id, ATA_ID_WORDS * 2);
if (transferStatus != ISD200_TRANSPORT_GOOD) {
/* Error issuing ATA Command Identify */
- US_DEBUGP(" Error issuing ATA Command Identify\n");
+ usb_stor_dbg(us, " Error issuing ATA Command Identify\n");
retStatus = ISD200_ERROR;
} else {
/* ATA Command Identify successful */
@@ -1140,7 +1138,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
__u16 *dest;
isd200_fix_driveid(id);
- isd200_dump_driveid(id);
+ isd200_dump_driveid(us, id);
memset(&info->InquiryData, 0, sizeof(info->InquiryData));
@@ -1174,7 +1172,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
/* determine if it supports Media Status Notification */
if (id[ATA_ID_COMMAND_SET_2] & COMMANDSET_MEDIA_STATUS) {
- US_DEBUGP(" Device supports Media Status Notification\n");
+ usb_stor_dbg(us, " Device supports Media Status Notification\n");
/* Indicate that it is enabled, even though it is not
* This allows the lock/unlock of the media to work
@@ -1194,7 +1192,8 @@ static int isd200_get_inquiry_data( struct us_data *us )
us->protocol_name = "Transparent SCSI";
us->proto_handler = usb_stor_transparent_scsi_command;
- US_DEBUGP("Protocol changed to: %s\n", us->protocol_name);
+ usb_stor_dbg(us, "Protocol changed to: %s\n",
+ us->protocol_name);
/* Free driver structure */
us->extra_destructor(info);
@@ -1204,7 +1203,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
}
}
- US_DEBUGP("Leaving isd200_get_inquiry_data %08X\n", retStatus);
+ usb_stor_dbg(us, "Leaving isd200_get_inquiry_data %08X\n", retStatus);
return(retStatus);
}
@@ -1235,7 +1234,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
/* SCSI Command */
switch (srb->cmnd[0]) {
case INQUIRY:
- US_DEBUGP(" ATA OUT - INQUIRY\n");
+ usb_stor_dbg(us, " ATA OUT - INQUIRY\n");
/* copy InquiryData */
usb_stor_set_xfer_buf((unsigned char *) &info->InquiryData,
@@ -1245,7 +1244,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
break;
case MODE_SENSE:
- US_DEBUGP(" ATA OUT - SCSIOP_MODE_SENSE\n");
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_MODE_SENSE\n");
/* Initialize the return buffer */
usb_stor_set_xfer_buf(senseData, sizeof(senseData), srb);
@@ -1259,14 +1258,14 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
isd200_srb_set_bufflen(srb, 0);
} else {
- US_DEBUGP(" Media Status not supported, just report okay\n");
+ usb_stor_dbg(us, " Media Status not supported, just report okay\n");
srb->result = SAM_STAT_GOOD;
sendToTransport = 0;
}
break;
case TEST_UNIT_READY:
- US_DEBUGP(" ATA OUT - SCSIOP_TEST_UNIT_READY\n");
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_TEST_UNIT_READY\n");
if (info->DeviceFlags & DF_MEDIA_STATUS_ENABLED)
{
@@ -1277,7 +1276,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
isd200_srb_set_bufflen(srb, 0);
} else {
- US_DEBUGP(" Media Status not supported, just report okay\n");
+ usb_stor_dbg(us, " Media Status not supported, just report okay\n");
srb->result = SAM_STAT_GOOD;
sendToTransport = 0;
}
@@ -1288,7 +1287,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
unsigned long capacity;
struct read_capacity_data readCapacityData;
- US_DEBUGP(" ATA OUT - SCSIOP_READ_CAPACITY\n");
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_READ_CAPACITY\n");
if (ata_id_has_lba(id))
capacity = ata_id_u32(id, ATA_ID_LBA_CAPACITY) - 1;
@@ -1307,7 +1306,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
break;
case READ_10:
- US_DEBUGP(" ATA OUT - SCSIOP_READ\n");
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_READ\n");
lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]);
blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
@@ -1339,7 +1338,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
break;
case WRITE_10:
- US_DEBUGP(" ATA OUT - SCSIOP_WRITE\n");
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_WRITE\n");
lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]);
blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
@@ -1371,10 +1370,11 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
break;
case ALLOW_MEDIUM_REMOVAL:
- US_DEBUGP(" ATA OUT - SCSIOP_MEDIUM_REMOVAL\n");
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_MEDIUM_REMOVAL\n");
if (info->DeviceFlags & DF_REMOVABLE_MEDIA) {
- US_DEBUGP(" srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);
+ usb_stor_dbg(us, " srb->cmnd[4] = 0x%X\n",
+ srb->cmnd[4]);
ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
@@ -1384,25 +1384,25 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
isd200_srb_set_bufflen(srb, 0);
} else {
- US_DEBUGP(" Not removeable media, just report okay\n");
+ usb_stor_dbg(us, " Not removeable media, just report okay\n");
srb->result = SAM_STAT_GOOD;
sendToTransport = 0;
}
break;
case START_STOP:
- US_DEBUGP(" ATA OUT - SCSIOP_START_STOP_UNIT\n");
- US_DEBUGP(" srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_START_STOP_UNIT\n");
+ usb_stor_dbg(us, " srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);
if ((srb->cmnd[4] & 0x3) == 0x2) {
- US_DEBUGP(" Media Eject\n");
+ usb_stor_dbg(us, " Media Eject\n");
ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
ataCdb->generic.TransferBlockSize = 0;
ataCdb->generic.RegisterSelect = REG_COMMAND;
ataCdb->write.CommandByte = ATA_COMMAND_MEDIA_EJECT;
} else if ((srb->cmnd[4] & 0x3) == 0x1) {
- US_DEBUGP(" Get Media Status\n");
+ usb_stor_dbg(us, " Get Media Status\n");
ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
ataCdb->generic.TransferBlockSize = 1;
@@ -1410,14 +1410,15 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
isd200_srb_set_bufflen(srb, 0);
} else {
- US_DEBUGP(" Nothing to do, just report okay\n");
+ usb_stor_dbg(us, " Nothing to do, just report okay\n");
srb->result = SAM_STAT_GOOD;
sendToTransport = 0;
}
break;
default:
- US_DEBUGP("Unsupported SCSI command - 0x%X\n", srb->cmnd[0]);
+ usb_stor_dbg(us, "Unsupported SCSI command - 0x%X\n",
+ srb->cmnd[0]);
srb->result = DID_ERROR << 16;
sendToTransport = 0;
break;
@@ -1461,8 +1462,7 @@ static int isd200_init_info(struct us_data *us)
retStatus = ISD200_ERROR;
else {
info->id = kzalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
- info->RegsBuf = (unsigned char *)
- kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
+ info->RegsBuf = kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
info->srb.sense_buffer =
kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) {
@@ -1475,8 +1475,7 @@ static int isd200_init_info(struct us_data *us)
if (retStatus == ISD200_GOOD) {
us->extra = info;
us->extra_destructor = isd200_free_info_ptrs;
- } else
- US_DEBUGP("ERROR - kmalloc failure\n");
+ }
return retStatus;
}
@@ -1487,19 +1486,19 @@ static int isd200_init_info(struct us_data *us)
static int isd200_Initialization(struct us_data *us)
{
- US_DEBUGP("ISD200 Initialization...\n");
+ usb_stor_dbg(us, "ISD200 Initialization...\n");
/* Initialize ISD200 info struct */
if (isd200_init_info(us) == ISD200_ERROR) {
- US_DEBUGP("ERROR Initializing ISD200 Info struct\n");
+ usb_stor_dbg(us, "ERROR Initializing ISD200 Info struct\n");
} else {
/* Get device specific data */
if (isd200_get_inquiry_data(us) != ISD200_GOOD)
- US_DEBUGP("ISD200 Initialization Failure\n");
+ usb_stor_dbg(us, "ISD200 Initialization Failure\n");
else
- US_DEBUGP("ISD200 Initialization complete\n");
+ usb_stor_dbg(us, "ISD200 Initialization complete\n");
}
return 0;
@@ -1510,7 +1509,7 @@ static int isd200_Initialization(struct us_data *us)
* Protocol and Transport for the ISD200 ASIC
*
* This protocol and transport are for ATA devices connected to an ISD200
- * ASIC. An ATAPI device that is conected as a slave device will be
+ * ASIC. An ATAPI device that is connected as a slave device will be
* detected in the driver initialization function and the protocol will
* be changed to an ATAPI protocol (Transparent SCSI).
*
@@ -1524,7 +1523,7 @@ static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
/* Make sure driver was initialized */
if (us->extra == NULL)
- US_DEBUGP("ERROR Driver not initialized\n");
+ usb_stor_dbg(us, "ERROR Driver not initialized\n");
scsi_set_resid(srb, 0);
/* scsi_bufflen might change in protocol translation to ata */
@@ -1567,17 +1566,7 @@ static struct usb_driver isd200_driver = {
.post_reset = usb_stor_post_reset,
.id_table = isd200_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
-static int __init isd200_init(void)
-{
- return usb_register(&isd200_driver);
-}
-
-static void __exit isd200_exit(void)
-{
- usb_deregister(&isd200_driver);
-}
-
-module_init(isd200_init);
-module_exit(isd200_exit);
+module_usb_driver(isd200_driver);
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index 6168596c5ac..563078be654 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -69,9 +69,9 @@ MODULE_LICENSE("GPL");
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
- .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ .driver_info = (flags) }
-struct usb_device_id jumpshot_usb_ids[] = {
+static struct usb_device_id jumpshot_usb_ids[] = {
# include "unusual_jumpshot.h"
{ } /* Terminating entry */
};
@@ -118,7 +118,7 @@ static inline int jumpshot_bulk_read(struct us_data *us,
if (len == 0)
return USB_STOR_XFER_GOOD;
- US_DEBUGP("jumpshot_bulk_read: len = %d\n", len);
+ usb_stor_dbg(us, "len = %d\n", len);
return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
data, len, NULL);
}
@@ -131,7 +131,7 @@ static inline int jumpshot_bulk_write(struct us_data *us,
if (len == 0)
return USB_STOR_XFER_GOOD;
- US_DEBUGP("jumpshot_bulk_write: len = %d\n", len);
+ usb_stor_dbg(us, "len = %d\n", len);
return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
data, len, NULL);
}
@@ -152,8 +152,7 @@ static int jumpshot_get_status(struct us_data *us)
return USB_STOR_TRANSPORT_ERROR;
if (us->iobuf[0] != 0x50) {
- US_DEBUGP("jumpshot_get_status: 0x%2x\n",
- us->iobuf[0]);
+ usb_stor_dbg(us, "0x%2x\n", us->iobuf[0]);
return USB_STOR_TRANSPORT_ERROR;
}
@@ -218,7 +217,7 @@ static int jumpshot_read_data(struct us_data *us,
if (result != USB_STOR_XFER_GOOD)
goto leave;
- US_DEBUGP("jumpshot_read_data: %d bytes\n", len);
+ usb_stor_dbg(us, "%d bytes\n", len);
// Store the data in the transfer buffer
usb_stor_access_xfer_buf(buffer, len, us->srb,
@@ -314,7 +313,7 @@ static int jumpshot_write_data(struct us_data *us,
} while ((result != USB_STOR_TRANSPORT_GOOD) && (waitcount < 10));
if (result != USB_STOR_TRANSPORT_GOOD)
- US_DEBUGP("jumpshot_write_data: Gah! Waitcount = 10. Bad write!?\n");
+ usb_stor_dbg(us, "Gah! Waitcount = 10. Bad write!?\n");
sector += thistime;
totallen -= len;
@@ -349,8 +348,7 @@ static int jumpshot_id_device(struct us_data *us,
0, 0x20, 0, 6, command, 2);
if (rc != USB_STOR_XFER_GOOD) {
- US_DEBUGP("jumpshot_id_device: Gah! "
- "send_control for read_capacity failed\n");
+ usb_stor_dbg(us, "Gah! send_control for read_capacity failed\n");
rc = USB_STOR_TRANSPORT_ERROR;
goto leave;
}
@@ -400,17 +398,17 @@ static int jumpshot_handle_mode_sense(struct us_data *us,
switch (pc) {
case 0x0:
- US_DEBUGP("jumpshot_handle_mode_sense: Current values\n");
- break;
+ usb_stor_dbg(us, "Current values\n");
+ break;
case 0x1:
- US_DEBUGP("jumpshot_handle_mode_sense: Changeable values\n");
- break;
+ usb_stor_dbg(us, "Changeable values\n");
+ break;
case 0x2:
- US_DEBUGP("jumpshot_handle_mode_sense: Default values\n");
- break;
+ usb_stor_dbg(us, "Default values\n");
+ break;
case 0x3:
- US_DEBUGP("jumpshot_handle_mode_sense: Saves values\n");
- break;
+ usb_stor_dbg(us, "Saves values\n");
+ break;
}
memset(ptr, 0, 8);
@@ -494,17 +492,16 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
if (!us->extra) {
us->extra = kzalloc(sizeof(struct jumpshot_info), GFP_NOIO);
- if (!us->extra) {
- US_DEBUGP("jumpshot_transport: Gah! Can't allocate storage for jumpshot info struct!\n");
+ if (!us->extra)
return USB_STOR_TRANSPORT_ERROR;
- }
+
us->extra_destructor = jumpshot_info_destructor;
}
info = (struct jumpshot_info *) (us->extra);
if (srb->cmnd[0] == INQUIRY) {
- US_DEBUGP("jumpshot_transport: INQUIRY. Returning bogus response.\n");
+ usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
memcpy(ptr, inquiry_response, sizeof(inquiry_response));
fill_inquiry_response(us, ptr, 36);
return USB_STOR_TRANSPORT_GOOD;
@@ -521,8 +518,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("jumpshot_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
- info->sectors, info->ssize);
+ usb_stor_dbg(us, "READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
+ info->sectors, info->ssize);
// build the reply
//
@@ -534,7 +531,7 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
}
if (srb->cmnd[0] == MODE_SELECT_10) {
- US_DEBUGP("jumpshot_transport: Gah! MODE_SELECT_10.\n");
+ usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -544,7 +541,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
- US_DEBUGP("jumpshot_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "READ_10: read block 0x%04lx count %ld\n",
+ block, blocks);
return jumpshot_read_data(us, info, block, blocks);
}
@@ -557,7 +555,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
- US_DEBUGP("jumpshot_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "READ_12: read block 0x%04lx count %ld\n",
+ block, blocks);
return jumpshot_read_data(us, info, block, blocks);
}
@@ -567,7 +566,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
- US_DEBUGP("jumpshot_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "WRITE_10: write block 0x%04lx count %ld\n",
+ block, blocks);
return jumpshot_write_data(us, info, block, blocks);
}
@@ -580,18 +580,19 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
- US_DEBUGP("jumpshot_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "WRITE_12: write block 0x%04lx count %ld\n",
+ block, blocks);
return jumpshot_write_data(us, info, block, blocks);
}
if (srb->cmnd[0] == TEST_UNIT_READY) {
- US_DEBUGP("jumpshot_transport: TEST_UNIT_READY.\n");
+ usb_stor_dbg(us, "TEST_UNIT_READY\n");
return jumpshot_get_status(us);
}
if (srb->cmnd[0] == REQUEST_SENSE) {
- US_DEBUGP("jumpshot_transport: REQUEST_SENSE.\n");
+ usb_stor_dbg(us, "REQUEST_SENSE\n");
memset(ptr, 0, 18);
ptr[0] = 0xF0;
@@ -605,12 +606,12 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
}
if (srb->cmnd[0] == MODE_SENSE) {
- US_DEBUGP("jumpshot_transport: MODE_SENSE_6 detected\n");
+ usb_stor_dbg(us, "MODE_SENSE_6 detected\n");
return jumpshot_handle_mode_sense(us, srb, 1);
}
if (srb->cmnd[0] == MODE_SENSE_10) {
- US_DEBUGP("jumpshot_transport: MODE_SENSE_10 detected\n");
+ usb_stor_dbg(us, "MODE_SENSE_10 detected\n");
return jumpshot_handle_mode_sense(us, srb, 0);
}
@@ -624,7 +625,7 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
if (srb->cmnd[0] == START_STOP) {
/* this is used by sd.c'check_scsidisk_media_change to detect
media change */
- US_DEBUGP("jumpshot_transport: START_STOP.\n");
+ usb_stor_dbg(us, "START_STOP\n");
/* the first jumpshot_id_device after a media change returns
an error (determined experimentally) */
rc = jumpshot_id_device(us, info);
@@ -638,8 +639,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
return rc;
}
- US_DEBUGP("jumpshot_transport: Gah! Unknown command: %d (0x%x)\n",
- srb->cmnd[0], srb->cmnd[0]);
+ usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
+ srb->cmnd[0], srb->cmnd[0]);
info->sense_key = 0x05;
info->sense_asc = 0x20;
info->sense_ascq = 0x00;
@@ -677,17 +678,7 @@ static struct usb_driver jumpshot_driver = {
.post_reset = usb_stor_post_reset,
.id_table = jumpshot_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
-static int __init jumpshot_init(void)
-{
- return usb_register(&jumpshot_driver);
-}
-
-static void __exit jumpshot_exit(void)
-{
- usb_deregister(&jumpshot_driver);
-}
-
-module_init(jumpshot_init);
-module_exit(jumpshot_exit);
+module_usb_driver(jumpshot_driver);
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
index ba1b7890688..94d16ee5e84 100644
--- a/drivers/usb/storage/karma.c
+++ b/drivers/usb/storage/karma.c
@@ -57,9 +57,9 @@ static int rio_karma_init(struct us_data *us);
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
- .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ .driver_info = (flags) }
-struct usb_device_id karma_usb_ids[] = {
+static struct usb_device_id karma_usb_ids[] = {
# include "unusual_karma.h"
{ } /* Terminating entry */
};
@@ -106,7 +106,7 @@ static int rio_karma_send_command(char cmd, struct us_data *us)
static unsigned char seq = 1;
struct karma_data *data = (struct karma_data *) us->extra;
- US_DEBUGP("karma: sending command %04x\n", cmd);
+ usb_stor_dbg(us, "sending command %04x\n", cmd);
memset(us->iobuf, 0, RIO_SEND_LEN);
memcpy(us->iobuf, RIO_PREFIX, RIO_PREFIX_LEN);
us->iobuf[5] = cmd;
@@ -139,10 +139,10 @@ static int rio_karma_send_command(char cmd, struct us_data *us)
if (seq == 0)
seq = 1;
- US_DEBUGP("karma: sent command %04x\n", cmd);
+ usb_stor_dbg(us, "sent command %04x\n", cmd);
return 0;
err:
- US_DEBUGP("karma: command %04x failed\n", cmd);
+ usb_stor_dbg(us, "command %04x failed\n", cmd);
return USB_STOR_TRANSPORT_FAILED;
}
@@ -230,17 +230,7 @@ static struct usb_driver karma_driver = {
.post_reset = usb_stor_post_reset,
.id_table = karma_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
-static int __init karma_init(void)
-{
- return usb_register(&karma_driver);
-}
-
-static void __exit karma_exit(void)
-{
- usb_deregister(&karma_driver);
-}
-
-module_init(karma_init);
-module_exit(karma_exit);
+module_usb_driver(karma_driver);
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
deleted file mode 100644
index fe3ffe1459b..00000000000
--- a/drivers/usb/storage/libusual.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * libusual
- *
- * The libusual contains the table of devices common for ub and usb-storage.
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb_usual.h>
-#include <linux/vmalloc.h>
-#include <linux/kthread.h>
-#include <linux/mutex.h>
-
-/*
- */
-#define USU_MOD_FL_THREAD 1 /* Thread is running */
-#define USU_MOD_FL_PRESENT 2 /* The module is loaded */
-
-struct mod_status {
- unsigned long fls;
-};
-
-static struct mod_status stat[3];
-static DEFINE_SPINLOCK(usu_lock);
-
-/*
- */
-#define USB_US_DEFAULT_BIAS USB_US_TYPE_STOR
-static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS);
-
-#define BIAS_NAME_SIZE (sizeof("usb-storage"))
-static const char *bias_names[3] = { "none", "usb-storage", "ub" };
-
-static DEFINE_MUTEX(usu_probe_mutex);
-static DECLARE_COMPLETION(usu_end_notify);
-static atomic_t total_threads = ATOMIC_INIT(0);
-
-static int usu_probe_thread(void *arg);
-
-/*
- * @type: the module type as an integer
- */
-void usb_usual_set_present(int type)
-{
- struct mod_status *st;
- unsigned long flags;
-
- if (type <= 0 || type >= 3)
- return;
- st = &stat[type];
- spin_lock_irqsave(&usu_lock, flags);
- st->fls |= USU_MOD_FL_PRESENT;
- spin_unlock_irqrestore(&usu_lock, flags);
-}
-EXPORT_SYMBOL_GPL(usb_usual_set_present);
-
-void usb_usual_clear_present(int type)
-{
- struct mod_status *st;
- unsigned long flags;
-
- if (type <= 0 || type >= 3)
- return;
- st = &stat[type];
- spin_lock_irqsave(&usu_lock, flags);
- st->fls &= ~USU_MOD_FL_PRESENT;
- spin_unlock_irqrestore(&usu_lock, flags);
-}
-EXPORT_SYMBOL_GPL(usb_usual_clear_present);
-
-/*
- * Match the calling driver type against the table.
- * Returns: 0 if the device matches.
- */
-int usb_usual_check_type(const struct usb_device_id *id, int caller_type)
-{
- int id_type = USB_US_TYPE(id->driver_info);
-
- if (caller_type <= 0 || caller_type >= 3)
- return -EINVAL;
-
- /* Drivers grab fixed assignment devices */
- if (id_type == caller_type)
- return 0;
- /* Drivers grab devices biased to them */
- if (id_type == USB_US_TYPE_NONE && caller_type == atomic_read(&usu_bias))
- return 0;
- return -ENODEV;
-}
-EXPORT_SYMBOL_GPL(usb_usual_check_type);
-
-/*
- */
-static int usu_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- int rc;
- unsigned long type;
- struct task_struct* task;
- unsigned long flags;
-
- type = USB_US_TYPE(id->driver_info);
- if (type == 0)
- type = atomic_read(&usu_bias);
-
- spin_lock_irqsave(&usu_lock, flags);
- if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) {
- spin_unlock_irqrestore(&usu_lock, flags);
- return -ENXIO;
- }
- stat[type].fls |= USU_MOD_FL_THREAD;
- spin_unlock_irqrestore(&usu_lock, flags);
-
- task = kthread_run(usu_probe_thread, (void*)type, "libusual_%ld", type);
- if (IS_ERR(task)) {
- rc = PTR_ERR(task);
- printk(KERN_WARNING "libusual: "
- "Unable to start the thread for %s: %d\n",
- bias_names[type], rc);
- spin_lock_irqsave(&usu_lock, flags);
- stat[type].fls &= ~USU_MOD_FL_THREAD;
- spin_unlock_irqrestore(&usu_lock, flags);
- return rc; /* Not being -ENXIO causes a message printed */
- }
- atomic_inc(&total_threads);
-
- return -ENXIO;
-}
-
-static void usu_disconnect(struct usb_interface *intf)
-{
- ; /* We should not be here. */
-}
-
-static struct usb_driver usu_driver = {
- .name = "libusual",
- .probe = usu_probe,
- .disconnect = usu_disconnect,
- .id_table = usb_storage_usb_ids,
-};
-
-/*
- * A whole new thread for a purpose of request_module seems quite stupid.
- * The request_module forks once inside again. However, if we attempt
- * to load a storage module from our own modprobe thread, that module
- * references our symbols, which cannot be resolved until our module is
- * initialized. I wish there was a way to wait for the end of initialization.
- * The module notifier reports MODULE_STATE_COMING only.
- * So, we wait until module->init ends as the next best thing.
- */
-static int usu_probe_thread(void *arg)
-{
- int type = (unsigned long) arg;
- struct mod_status *st = &stat[type];
- int rc;
- unsigned long flags;
-
- mutex_lock(&usu_probe_mutex);
- rc = request_module(bias_names[type]);
- spin_lock_irqsave(&usu_lock, flags);
- if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) {
- /*
- * This should not happen, but let us keep tabs on it.
- */
- printk(KERN_NOTICE "libusual: "
- "modprobe for %s succeeded, but module is not present\n",
- bias_names[type]);
- }
- st->fls &= ~USU_MOD_FL_THREAD;
- spin_unlock_irqrestore(&usu_lock, flags);
- mutex_unlock(&usu_probe_mutex);
-
- complete_and_exit(&usu_end_notify, 0);
-}
-
-/*
- */
-static int __init usb_usual_init(void)
-{
- int rc;
-
- mutex_lock(&usu_probe_mutex);
- rc = usb_register(&usu_driver);
- mutex_unlock(&usu_probe_mutex);
- return rc;
-}
-
-static void __exit usb_usual_exit(void)
-{
- /*
- * We do not check for any drivers present, because
- * they keep us pinned with symbol references.
- */
-
- usb_deregister(&usu_driver);
-
- while (atomic_read(&total_threads) > 0) {
- wait_for_completion(&usu_end_notify);
- atomic_dec(&total_threads);
- }
-}
-
-/*
- * Validate and accept the bias parameter.
- */
-static int usu_set_bias(const char *bias_s, struct kernel_param *kp)
-{
- int i;
- int len;
- int bias_n = 0;
-
- len = strlen(bias_s);
- if (len == 0)
- return -EDOM;
- if (bias_s[len-1] == '\n')
- --len;
-
- for (i = 1; i < 3; i++) {
- if (strncmp(bias_s, bias_names[i], len) == 0) {
- bias_n = i;
- break;
- }
- }
- if (bias_n == 0)
- return -EINVAL;
-
- atomic_set(&usu_bias, bias_n);
- return 0;
-}
-
-static int usu_get_bias(char *buffer, struct kernel_param *kp)
-{
- return strlen(strcpy(buffer, bias_names[atomic_read(&usu_bias)]));
-}
-
-module_init(usb_usual_init);
-module_exit(usb_usual_exit);
-
-module_param_call(bias, usu_set_bias, usu_get_bias, NULL, S_IRUGO|S_IWUSR);
-__MODULE_PARM_TYPE(bias, "string");
-MODULE_PARM_DESC(bias, "Bias to usb-storage or ub");
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 1943be5a291..74e2aa23b04 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -30,7 +30,6 @@
#include <linux/kernel.h>
#include <linux/input.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/usb/input.h>
@@ -67,9 +66,9 @@ struct usb_onetouch {
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
- .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ .driver_info = (flags) }
-struct usb_device_id onetouch_usb_ids[] = {
+static struct usb_device_id onetouch_usb_ids[] = {
# include "unusual_onetouch.h"
{ } /* Terminating entry */
};
@@ -195,6 +194,7 @@ static int onetouch_connect_input(struct us_data *ss)
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+ maxp = min(maxp, ONETOUCH_PKT_LEN);
onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL);
input_dev = input_allocate_device();
@@ -245,8 +245,7 @@ static int onetouch_connect_input(struct us_data *ss)
input_dev->open = usb_onetouch_open;
input_dev->close = usb_onetouch_close;
- usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data,
- (maxp > 8 ? 8 : maxp),
+ usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data, maxp,
usb_onetouch_irq, onetouch, endpoint->bInterval);
onetouch->irq->transfer_dma = onetouch->data_dma;
onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -312,17 +311,7 @@ static struct usb_driver onetouch_driver = {
.post_reset = usb_stor_post_reset,
.id_table = onetouch_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
-static int __init onetouch_init(void)
-{
- return usb_register(&onetouch_driver);
-}
-
-static void __exit onetouch_exit(void)
-{
- usb_deregister(&onetouch_driver);
-}
-
-module_init(onetouch_init);
-module_exit(onetouch_exit);
+module_usb_driver(onetouch_driver);
diff --git a/drivers/usb/storage/option_ms.c b/drivers/usb/storage/option_ms.c
index 89460181d12..b2b35b1d7de 100644
--- a/drivers/usb/storage/option_ms.c
+++ b/drivers/usb/storage/option_ms.c
@@ -22,6 +22,7 @@
#include <linux/usb.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "usb.h"
#include "transport.h"
@@ -49,7 +50,7 @@ static int option_rezero(struct us_data *us)
char *buffer;
int result;
- US_DEBUGP("Option MS: %s", "DEVICE MODE SWITCH\n");
+ usb_stor_dbg(us, "Option MS: %s\n", "DEVICE MODE SWITCH");
buffer = kzalloc(RESPONSE_LEN, GFP_KERNEL);
if (buffer == NULL)
@@ -94,7 +95,7 @@ static int option_inquiry(struct us_data *us)
char *buffer;
int result;
- US_DEBUGP("Option MS: %s", "device inquiry for vendor name\n");
+ usb_stor_dbg(us, "Option MS: %s\n", "device inquiry for vendor name");
buffer = kzalloc(0x24, GFP_KERNEL);
if (buffer == NULL)
@@ -137,31 +138,32 @@ int option_ms_init(struct us_data *us)
{
int result;
- US_DEBUGP("Option MS: option_ms_init called\n");
+ usb_stor_dbg(us, "Option MS: %s\n", "option_ms_init called");
/* Additional test for vendor information via INQUIRY,
* because some vendor/product IDs are ambiguous
*/
result = option_inquiry(us);
if (result != 0) {
- US_DEBUGP("Option MS: vendor is not Option or not determinable,"
- " no action taken\n");
+ usb_stor_dbg(us, "Option MS: %s\n",
+ "vendor is not Option or not determinable, no action taken");
return 0;
} else
- US_DEBUGP("Option MS: this is a genuine Option device,"
- " proceeding\n");
+ usb_stor_dbg(us, "Option MS: %s\n",
+ "this is a genuine Option device, proceeding");
/* Force Modem mode */
if (option_zero_cd == ZCD_FORCE_MODEM) {
- US_DEBUGP("Option MS: %s", "Forcing Modem Mode\n");
+ usb_stor_dbg(us, "Option MS: %s\n", "Forcing Modem Mode");
result = option_rezero(us);
if (result != USB_STOR_XFER_GOOD)
- US_DEBUGP("Option MS: Failed to switch to modem mode.\n");
+ usb_stor_dbg(us, "Option MS: %s\n",
+ "Failed to switch to modem mode");
return -EIO;
} else if (option_zero_cd == ZCD_ALLOW_MS) {
/* Allow Mass Storage mode (keep CD-Rom) */
- US_DEBUGP("Option MS: %s", "Allowing Mass Storage Mode if device"
- " requests it\n");
+ usb_stor_dbg(us, "Option MS: %s\n",
+ "Allowing Mass Storage Mode if device requests it");
}
return 0;
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index fc310f75ead..12e3c2fac64 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -43,6 +43,7 @@
*/
#include <linux/highmem.h>
+#include <linux/export.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -58,17 +59,16 @@
void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
{
- /* Pad the SCSI command with zeros out to 12 bytes
+ /*
+ * Pad the SCSI command with zeros out to 12 bytes. If the
+ * command already is 12 bytes or longer, leave it alone.
*
* NOTE: This only works because a scsi_cmnd struct field contains
* a unsigned char cmnd[16], so we know we have storage available
*/
- for (; srb->cmd_len<12; srb->cmd_len++)
+ for (; srb->cmd_len < 12; srb->cmd_len++)
srb->cmnd[srb->cmd_len] = 0;
- /* set command length to 12 bytes */
- srb->cmd_len = 12;
-
/* send the command to the transport layer */
usb_stor_invoke_transport(srb, us);
}
@@ -76,14 +76,14 @@ void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us)
{
/* fix some commands -- this is a form of mode translation
- * UFI devices only accept 12 byte long commands
+ * UFI devices only accept 12 byte long commands
*
* NOTE: This only works because a scsi_cmnd struct field contains
* a unsigned char cmnd[16], so we know we have storage available
*/
/* Pad the ATAPI command with zeros */
- for (; srb->cmd_len<12; srb->cmd_len++)
+ for (; srb->cmd_len < 12; srb->cmd_len++)
srb->cmnd[srb->cmd_len] = 0;
/* set command length to 12 bytes (this affects the transport layer) */
@@ -135,69 +135,42 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
unsigned int *offset, enum xfer_buf_dir dir)
{
- unsigned int cnt;
+ unsigned int cnt = 0;
struct scatterlist *sg = *sgptr;
+ struct sg_mapping_iter miter;
+ unsigned int nents = scsi_sg_count(srb);
- /* We have to go through the list one entry
- * at a time. Each s-g entry contains some number of pages, and
- * each page has to be kmap()'ed separately. If the page is already
- * in kernel-addressable memory then kmap() will return its address.
- * If the page is not directly accessible -- such as a user buffer
- * located in high memory -- then kmap() will map it to a temporary
- * position in the kernel's virtual address space.
- */
-
- if (!sg)
+ if (sg)
+ nents = sg_nents(sg);
+ else
sg = scsi_sglist(srb);
- /* This loop handles a single s-g list entry, which may
- * include multiple pages. Find the initial page structure
- * and the starting offset within the page, and update
- * the *offset and **sgptr values for the next loop.
- */
- cnt = 0;
- while (cnt < buflen && sg) {
- struct page *page = sg_page(sg) +
- ((sg->offset + *offset) >> PAGE_SHIFT);
- unsigned int poff = (sg->offset + *offset) & (PAGE_SIZE-1);
- unsigned int sglen = sg->length - *offset;
-
- if (sglen > buflen - cnt) {
-
- /* Transfer ends within this s-g entry */
- sglen = buflen - cnt;
- *offset += sglen;
- } else {
+ sg_miter_start(&miter, sg, nents, dir == FROM_XFER_BUF ?
+ SG_MITER_FROM_SG: SG_MITER_TO_SG);
- /* Transfer continues to next s-g entry */
- *offset = 0;
- sg = sg_next(sg);
- }
+ if (!sg_miter_skip(&miter, *offset))
+ return cnt;
+
+ while (sg_miter_next(&miter) && cnt < buflen) {
+ unsigned int len = min_t(unsigned int, miter.length,
+ buflen - cnt);
- /* Transfer the data for all the pages in this
- * s-g entry. For each page: call kmap(), do the
- * transfer, and call kunmap() immediately after. */
- while (sglen > 0) {
- unsigned int plen = min(sglen, (unsigned int)
- PAGE_SIZE - poff);
- unsigned char *ptr = kmap(page);
-
- if (dir == TO_XFER_BUF)
- memcpy(ptr + poff, buffer + cnt, plen);
- else
- memcpy(buffer + cnt, ptr + poff, plen);
- kunmap(page);
-
- /* Start at the beginning of the next page */
- poff = 0;
- ++page;
- cnt += plen;
- sglen -= plen;
+ if (dir == FROM_XFER_BUF)
+ memcpy(buffer + cnt, miter.addr, len);
+ else
+ memcpy(miter.addr, buffer + cnt, len);
+
+ if (*offset + len < miter.piter.sg->length) {
+ *offset += len;
+ *sgptr = miter.piter.sg;
+ } else {
+ *offset = 0;
+ *sgptr = sg_next(miter.piter.sg);
}
+ cnt += len;
}
- *sgptr = sg;
+ sg_miter_stop(&miter);
- /* Return the amount actually transferred */
return cnt;
}
EXPORT_SYMBOL_GPL(usb_stor_access_xfer_buf);
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
new file mode 100644
index 00000000000..281be56d564
--- /dev/null
+++ b/drivers/usb/storage/realtek_cr.c
@@ -0,0 +1,1071 @@
+/* Driver for Realtek RTS51xx USB card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ * wwang (wei_wang@realsil.com.cn)
+ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <linux/cdrom.h>
+
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/usb_usual.h>
+
+#include "usb.h"
+#include "transport.h"
+#include "protocol.h"
+#include "debug.h"
+
+MODULE_DESCRIPTION("Driver for Realtek USB Card Reader");
+MODULE_AUTHOR("wwang <wei_wang@realsil.com.cn>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.03");
+
+static int auto_delink_en = 1;
+module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(auto_delink_en, "enable auto delink");
+
+#ifdef CONFIG_REALTEK_AUTOPM
+static int ss_en = 1;
+module_param(ss_en, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ss_en, "enable selective suspend");
+
+static int ss_delay = 50;
+module_param(ss_delay, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ss_delay,
+ "seconds to delay before entering selective suspend");
+
+enum RTS51X_STAT {
+ RTS51X_STAT_INIT,
+ RTS51X_STAT_IDLE,
+ RTS51X_STAT_RUN,
+ RTS51X_STAT_SS
+};
+
+#define POLLING_INTERVAL 50
+
+#define rts51x_set_stat(chip, stat) \
+ ((chip)->state = (enum RTS51X_STAT)(stat))
+#define rts51x_get_stat(chip) ((chip)->state)
+
+#define SET_LUN_READY(chip, lun) ((chip)->lun_ready |= ((u8)1 << (lun)))
+#define CLR_LUN_READY(chip, lun) ((chip)->lun_ready &= ~((u8)1 << (lun)))
+#define TST_LUN_READY(chip, lun) ((chip)->lun_ready & ((u8)1 << (lun)))
+
+#endif
+
+struct rts51x_status {
+ u16 vid;
+ u16 pid;
+ u8 cur_lun;
+ u8 card_type;
+ u8 total_lun;
+ u16 fw_ver;
+ u8 phy_exist;
+ u8 multi_flag;
+ u8 multi_card;
+ u8 log_exist;
+ union {
+ u8 detailed_type1;
+ u8 detailed_type2;
+ } detailed_type;
+ u8 function[2];
+};
+
+struct rts51x_chip {
+ u16 vendor_id;
+ u16 product_id;
+ char max_lun;
+
+ struct rts51x_status *status;
+ int status_len;
+
+ u32 flag;
+ struct us_data *us;
+
+#ifdef CONFIG_REALTEK_AUTOPM
+ struct timer_list rts51x_suspend_timer;
+ unsigned long timer_expires;
+ int pwr_state;
+ u8 lun_ready;
+ enum RTS51X_STAT state;
+ int support_auto_delink;
+#endif
+ /* used to back up the protocal choosen in probe1 phase */
+ proto_cmnd proto_handler_backup;
+};
+
+/* flag definition */
+#define FLIDX_AUTO_DELINK 0x01
+
+#define SCSI_LUN(srb) ((srb)->device->lun)
+
+/* Bit Operation */
+#define SET_BIT(data, idx) ((data) |= 1 << (idx))
+#define CLR_BIT(data, idx) ((data) &= ~(1 << (idx)))
+#define CHK_BIT(data, idx) ((data) & (1 << (idx)))
+
+#define SET_AUTO_DELINK(chip) ((chip)->flag |= FLIDX_AUTO_DELINK)
+#define CLR_AUTO_DELINK(chip) ((chip)->flag &= ~FLIDX_AUTO_DELINK)
+#define CHK_AUTO_DELINK(chip) ((chip)->flag & FLIDX_AUTO_DELINK)
+
+#define RTS51X_GET_VID(chip) ((chip)->vendor_id)
+#define RTS51X_GET_PID(chip) ((chip)->product_id)
+
+#define VENDOR_ID(chip) ((chip)->status[0].vid)
+#define PRODUCT_ID(chip) ((chip)->status[0].pid)
+#define FW_VERSION(chip) ((chip)->status[0].fw_ver)
+#define STATUS_LEN(chip) ((chip)->status_len)
+
+#define STATUS_SUCCESS 0
+#define STATUS_FAIL 1
+
+/* Check card reader function */
+#define SUPPORT_DETAILED_TYPE1(chip) \
+ CHK_BIT((chip)->status[0].function[0], 1)
+#define SUPPORT_OT(chip) \
+ CHK_BIT((chip)->status[0].function[0], 2)
+#define SUPPORT_OC(chip) \
+ CHK_BIT((chip)->status[0].function[0], 3)
+#define SUPPORT_AUTO_DELINK(chip) \
+ CHK_BIT((chip)->status[0].function[0], 4)
+#define SUPPORT_SDIO(chip) \
+ CHK_BIT((chip)->status[0].function[1], 0)
+#define SUPPORT_DETAILED_TYPE2(chip) \
+ CHK_BIT((chip)->status[0].function[1], 1)
+
+#define CHECK_PID(chip, pid) (RTS51X_GET_PID(chip) == (pid))
+#define CHECK_FW_VER(chip, fw_ver) (FW_VERSION(chip) == (fw_ver))
+#define CHECK_ID(chip, pid, fw_ver) \
+ (CHECK_PID((chip), (pid)) && CHECK_FW_VER((chip), (fw_ver)))
+
+static int init_realtek_cr(struct us_data *us);
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+ vendorName, productName, useProtocol, useTransport, \
+ initFunction, flags) \
+{\
+ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+ .driver_info = (flags) \
+}
+
+static const struct usb_device_id realtek_cr_ids[] = {
+# include "unusual_realtek.h"
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, realtek_cr_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+ vendor_name, product_name, use_protocol, use_transport, \
+ init_function, Flags) \
+{ \
+ .vendorName = vendor_name, \
+ .productName = product_name, \
+ .useProtocol = use_protocol, \
+ .useTransport = use_transport, \
+ .initFunction = init_function, \
+}
+
+static struct us_unusual_dev realtek_cr_unusual_dev_list[] = {
+# include "unusual_realtek.h"
+ {} /* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
+static int rts51x_bulk_transport(struct us_data *us, u8 lun,
+ u8 *cmd, int cmd_len, u8 *buf, int buf_len,
+ enum dma_data_direction dir, int *act_len)
+{
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *)us->iobuf;
+ struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *)us->iobuf;
+ int result;
+ unsigned int residue;
+ unsigned int cswlen;
+ unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
+
+ /* set up the command wrapper */
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = cpu_to_le32(buf_len);
+ bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0;
+ bcb->Tag = ++us->tag;
+ bcb->Lun = lun;
+ bcb->Length = cmd_len;
+
+ /* copy the command payload */
+ memset(bcb->CDB, 0, sizeof(bcb->CDB));
+ memcpy(bcb->CDB, cmd, bcb->Length);
+
+ /* send it to out endpoint */
+ result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ bcb, cbwlen, NULL);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ /* DATA STAGE */
+ /* send/receive data payload, if there is any */
+
+ if (buf && buf_len) {
+ unsigned int pipe = (dir == DMA_FROM_DEVICE) ?
+ us->recv_bulk_pipe : us->send_bulk_pipe;
+ result = usb_stor_bulk_transfer_buf(us, pipe,
+ buf, buf_len, NULL);
+ if (result == USB_STOR_XFER_ERROR)
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ /* get CSW for device status */
+ result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ bcs, US_BULK_CS_WRAP_LEN, &cswlen);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ /* check bulk status */
+ if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN)) {
+ usb_stor_dbg(us, "Signature mismatch: got %08X, expecting %08X\n",
+ le32_to_cpu(bcs->Signature), US_BULK_CS_SIGN);
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ residue = bcs->Residue;
+ if (bcs->Tag != us->tag)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ /* try to compute the actual residue, based on how much data
+ * was really transferred and what the device tells us */
+ if (residue)
+ residue = residue < buf_len ? residue : buf_len;
+
+ if (act_len)
+ *act_len = buf_len - residue;
+
+ /* based on the status code, we report good or bad */
+ switch (bcs->Status) {
+ case US_BULK_STAT_OK:
+ /* command good -- note that data could be short */
+ return USB_STOR_TRANSPORT_GOOD;
+
+ case US_BULK_STAT_FAIL:
+ /* command failed */
+ return USB_STOR_TRANSPORT_FAILED;
+
+ case US_BULK_STAT_PHASE:
+ /* phase error -- note that a transport reset will be
+ * invoked by the invoke_transport() function
+ */
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ /* we should never get here, but if we do, we're in trouble */
+ return USB_STOR_TRANSPORT_ERROR;
+}
+
+static int rts51x_bulk_transport_special(struct us_data *us, u8 lun,
+ u8 *cmd, int cmd_len, u8 *buf, int buf_len,
+ enum dma_data_direction dir, int *act_len)
+{
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
+ int result;
+ unsigned int cswlen;
+ unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
+
+ /* set up the command wrapper */
+ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb->DataTransferLength = cpu_to_le32(buf_len);
+ bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0;
+ bcb->Tag = ++us->tag;
+ bcb->Lun = lun;
+ bcb->Length = cmd_len;
+
+ /* copy the command payload */
+ memset(bcb->CDB, 0, sizeof(bcb->CDB));
+ memcpy(bcb->CDB, cmd, bcb->Length);
+
+ /* send it to out endpoint */
+ result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ bcb, cbwlen, NULL);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ /* DATA STAGE */
+ /* send/receive data payload, if there is any */
+
+ if (buf && buf_len) {
+ unsigned int pipe = (dir == DMA_FROM_DEVICE) ?
+ us->recv_bulk_pipe : us->send_bulk_pipe;
+ result = usb_stor_bulk_transfer_buf(us, pipe,
+ buf, buf_len, NULL);
+ if (result == USB_STOR_XFER_ERROR)
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ /* get CSW for device status */
+ result = usb_bulk_msg(us->pusb_dev, us->recv_bulk_pipe, bcs,
+ US_BULK_CS_WRAP_LEN, &cswlen, 250);
+ return result;
+}
+
+/* Determine what the maximum LUN supported is */
+static int rts51x_get_max_lun(struct us_data *us)
+{
+ int result;
+
+ /* issue the command */
+ us->iobuf[0] = 0;
+ result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
+ US_BULK_GET_MAX_LUN,
+ USB_DIR_IN | USB_TYPE_CLASS |
+ USB_RECIP_INTERFACE,
+ 0, us->ifnum, us->iobuf, 1, 10 * HZ);
+
+ usb_stor_dbg(us, "GetMaxLUN command result is %d, data is %d\n",
+ result, us->iobuf[0]);
+
+ /* if we have a successful request, return the result */
+ if (result > 0)
+ return us->iobuf[0];
+
+ return 0;
+}
+
+static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len)
+{
+ int retval;
+ u8 cmnd[12] = { 0 };
+ u8 *buf;
+
+ buf = kmalloc(len, GFP_NOIO);
+ if (buf == NULL)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ usb_stor_dbg(us, "addr = 0x%x, len = %d\n", addr, len);
+
+ cmnd[0] = 0xF0;
+ cmnd[1] = 0x0D;
+ cmnd[2] = (u8) (addr >> 8);
+ cmnd[3] = (u8) addr;
+ cmnd[4] = (u8) (len >> 8);
+ cmnd[5] = (u8) len;
+
+ retval = rts51x_bulk_transport(us, 0, cmnd, 12,
+ buf, len, DMA_FROM_DEVICE, NULL);
+ if (retval != USB_STOR_TRANSPORT_GOOD) {
+ kfree(buf);
+ return -EIO;
+ }
+
+ memcpy(data, buf, len);
+ kfree(buf);
+ return 0;
+}
+
+static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len)
+{
+ int retval;
+ u8 cmnd[12] = { 0 };
+ u8 *buf;
+
+ buf = kmemdup(data, len, GFP_NOIO);
+ if (buf == NULL)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ usb_stor_dbg(us, "addr = 0x%x, len = %d\n", addr, len);
+
+ cmnd[0] = 0xF0;
+ cmnd[1] = 0x0E;
+ cmnd[2] = (u8) (addr >> 8);
+ cmnd[3] = (u8) addr;
+ cmnd[4] = (u8) (len >> 8);
+ cmnd[5] = (u8) len;
+
+ retval = rts51x_bulk_transport(us, 0, cmnd, 12,
+ buf, len, DMA_TO_DEVICE, NULL);
+ kfree(buf);
+ if (retval != USB_STOR_TRANSPORT_GOOD)
+ return -EIO;
+
+ return 0;
+}
+
+static int rts51x_read_status(struct us_data *us,
+ u8 lun, u8 *status, int len, int *actlen)
+{
+ int retval;
+ u8 cmnd[12] = { 0 };
+ u8 *buf;
+
+ buf = kmalloc(len, GFP_NOIO);
+ if (buf == NULL)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ usb_stor_dbg(us, "lun = %d\n", lun);
+
+ cmnd[0] = 0xF0;
+ cmnd[1] = 0x09;
+
+ retval = rts51x_bulk_transport(us, lun, cmnd, 12,
+ buf, len, DMA_FROM_DEVICE, actlen);
+ if (retval != USB_STOR_TRANSPORT_GOOD) {
+ kfree(buf);
+ return -EIO;
+ }
+
+ memcpy(status, buf, len);
+ kfree(buf);
+ return 0;
+}
+
+static int rts51x_check_status(struct us_data *us, u8 lun)
+{
+ struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+ int retval;
+ u8 buf[16];
+
+ retval = rts51x_read_status(us, lun, buf, 16, &(chip->status_len));
+ if (retval != STATUS_SUCCESS)
+ return -EIO;
+
+ usb_stor_dbg(us, "chip->status_len = %d\n", chip->status_len);
+
+ chip->status[lun].vid = ((u16) buf[0] << 8) | buf[1];
+ chip->status[lun].pid = ((u16) buf[2] << 8) | buf[3];
+ chip->status[lun].cur_lun = buf[4];
+ chip->status[lun].card_type = buf[5];
+ chip->status[lun].total_lun = buf[6];
+ chip->status[lun].fw_ver = ((u16) buf[7] << 8) | buf[8];
+ chip->status[lun].phy_exist = buf[9];
+ chip->status[lun].multi_flag = buf[10];
+ chip->status[lun].multi_card = buf[11];
+ chip->status[lun].log_exist = buf[12];
+ if (chip->status_len == 16) {
+ chip->status[lun].detailed_type.detailed_type1 = buf[13];
+ chip->status[lun].function[0] = buf[14];
+ chip->status[lun].function[1] = buf[15];
+ }
+
+ return 0;
+}
+
+static int enable_oscillator(struct us_data *us)
+{
+ int retval;
+ u8 value;
+
+ retval = rts51x_read_mem(us, 0xFE77, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ value |= 0x04;
+ retval = rts51x_write_mem(us, 0xFE77, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ retval = rts51x_read_mem(us, 0xFE77, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ if (!(value & 0x04))
+ return -EIO;
+
+ return 0;
+}
+
+static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len)
+{
+ int retval;
+ u8 cmnd[12] = {0};
+ u8 *buf;
+
+ usb_stor_dbg(us, "addr = 0xfe47, len = %d\n", len);
+
+ buf = kmemdup(data, len, GFP_NOIO);
+ if (!buf)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ cmnd[0] = 0xF0;
+ cmnd[1] = 0x0E;
+ cmnd[2] = 0xfe;
+ cmnd[3] = 0x47;
+ cmnd[4] = (u8)(len >> 8);
+ cmnd[5] = (u8)len;
+
+ retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, buf, len, DMA_TO_DEVICE, NULL);
+ kfree(buf);
+ if (retval != USB_STOR_TRANSPORT_GOOD) {
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int do_config_autodelink(struct us_data *us, int enable, int force)
+{
+ int retval;
+ u8 value;
+
+ retval = rts51x_read_mem(us, 0xFE47, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ if (enable) {
+ if (force)
+ value |= 0x03;
+ else
+ value |= 0x01;
+ } else {
+ value &= ~0x03;
+ }
+
+ usb_stor_dbg(us, "set 0xfe47 to 0x%x\n", value);
+
+ /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */
+ retval = __do_config_autodelink(us, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ return 0;
+}
+
+static int config_autodelink_after_power_on(struct us_data *us)
+{
+ struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+ int retval;
+ u8 value;
+
+ if (!CHK_AUTO_DELINK(chip))
+ return 0;
+
+ retval = rts51x_read_mem(us, 0xFE47, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ if (auto_delink_en) {
+ CLR_BIT(value, 0);
+ CLR_BIT(value, 1);
+ SET_BIT(value, 2);
+
+ if (CHECK_ID(chip, 0x0138, 0x3882))
+ CLR_BIT(value, 2);
+
+ SET_BIT(value, 7);
+
+ /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */
+ retval = __do_config_autodelink(us, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ retval = enable_oscillator(us);
+ if (retval == 0)
+ (void)do_config_autodelink(us, 1, 0);
+ } else {
+ /* Autodelink controlled by firmware */
+
+ SET_BIT(value, 2);
+
+ if (CHECK_ID(chip, 0x0138, 0x3882))
+ CLR_BIT(value, 2);
+
+ if (CHECK_ID(chip, 0x0159, 0x5889) ||
+ CHECK_ID(chip, 0x0138, 0x3880)) {
+ CLR_BIT(value, 0);
+ CLR_BIT(value, 7);
+ }
+
+ /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */
+ retval = __do_config_autodelink(us, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ if (CHECK_ID(chip, 0x0159, 0x5888)) {
+ value = 0xFF;
+ retval = rts51x_write_mem(us, 0xFE79, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ value = 0x01;
+ retval = rts51x_write_mem(us, 0x48, &value, 1);
+ if (retval < 0)
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int config_autodelink_before_power_down(struct us_data *us)
+{
+ struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+ int retval;
+ u8 value;
+
+ if (!CHK_AUTO_DELINK(chip))
+ return 0;
+
+ if (auto_delink_en) {
+ retval = rts51x_read_mem(us, 0xFE77, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ SET_BIT(value, 2);
+ retval = rts51x_write_mem(us, 0xFE77, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ if (CHECK_ID(chip, 0x0159, 0x5888)) {
+ value = 0x01;
+ retval = rts51x_write_mem(us, 0x48, &value, 1);
+ if (retval < 0)
+ return -EIO;
+ }
+
+ retval = rts51x_read_mem(us, 0xFE47, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ SET_BIT(value, 0);
+ if (CHECK_ID(chip, 0x0138, 0x3882))
+ SET_BIT(value, 2);
+ retval = rts51x_write_mem(us, 0xFE77, &value, 1);
+ if (retval < 0)
+ return -EIO;
+ } else {
+ if (CHECK_ID(chip, 0x0159, 0x5889) ||
+ CHECK_ID(chip, 0x0138, 0x3880) ||
+ CHECK_ID(chip, 0x0138, 0x3882)) {
+ retval = rts51x_read_mem(us, 0xFE47, &value, 1);
+ if (retval < 0)
+ return -EIO;
+
+ if (CHECK_ID(chip, 0x0159, 0x5889) ||
+ CHECK_ID(chip, 0x0138, 0x3880)) {
+ SET_BIT(value, 0);
+ SET_BIT(value, 7);
+ }
+
+ if (CHECK_ID(chip, 0x0138, 0x3882))
+ SET_BIT(value, 2);
+
+ /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */
+ retval = __do_config_autodelink(us, &value, 1);
+ if (retval < 0)
+ return -EIO;
+ }
+
+ if (CHECK_ID(chip, 0x0159, 0x5888)) {
+ value = 0x01;
+ retval = rts51x_write_mem(us, 0x48, &value, 1);
+ if (retval < 0)
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static void fw5895_init(struct us_data *us)
+{
+ struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+ int retval;
+ u8 val;
+
+ if ((PRODUCT_ID(chip) != 0x0158) || (FW_VERSION(chip) != 0x5895)) {
+ usb_stor_dbg(us, "Not the specified device, return immediately!\n");
+ } else {
+ retval = rts51x_read_mem(us, 0xFD6F, &val, 1);
+ if (retval == STATUS_SUCCESS && (val & 0x1F) == 0) {
+ val = 0x1F;
+ retval = rts51x_write_mem(us, 0xFD70, &val, 1);
+ if (retval != STATUS_SUCCESS)
+ usb_stor_dbg(us, "Write memory fail\n");
+ } else {
+ usb_stor_dbg(us, "Read memory fail, OR (val & 0x1F) != 0\n");
+ }
+ }
+}
+
+#ifdef CONFIG_REALTEK_AUTOPM
+static void fw5895_set_mmc_wp(struct us_data *us)
+{
+ struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+ int retval;
+ u8 buf[13];
+
+ if ((PRODUCT_ID(chip) != 0x0158) || (FW_VERSION(chip) != 0x5895)) {
+ usb_stor_dbg(us, "Not the specified device, return immediately!\n");
+ } else {
+ retval = rts51x_read_mem(us, 0xFD6F, buf, 1);
+ if (retval == STATUS_SUCCESS && (buf[0] & 0x24) == 0x24) {
+ /* SD Exist and SD WP */
+ retval = rts51x_read_mem(us, 0xD04E, buf, 1);
+ if (retval == STATUS_SUCCESS) {
+ buf[0] |= 0x04;
+ retval = rts51x_write_mem(us, 0xFD70, buf, 1);
+ if (retval != STATUS_SUCCESS)
+ usb_stor_dbg(us, "Write memory fail\n");
+ } else {
+ usb_stor_dbg(us, "Read memory fail\n");
+ }
+ } else {
+ usb_stor_dbg(us, "Read memory fail, OR (buf[0]&0x24)!=0x24\n");
+ }
+ }
+}
+
+static void rts51x_modi_suspend_timer(struct rts51x_chip *chip)
+{
+ struct us_data *us = chip->us;
+
+ usb_stor_dbg(us, "state:%d\n", rts51x_get_stat(chip));
+
+ chip->timer_expires = jiffies + msecs_to_jiffies(1000*ss_delay);
+ mod_timer(&chip->rts51x_suspend_timer, chip->timer_expires);
+}
+
+static void rts51x_suspend_timer_fn(unsigned long data)
+{
+ struct rts51x_chip *chip = (struct rts51x_chip *)data;
+ struct us_data *us = chip->us;
+
+ switch (rts51x_get_stat(chip)) {
+ case RTS51X_STAT_INIT:
+ case RTS51X_STAT_RUN:
+ rts51x_modi_suspend_timer(chip);
+ break;
+ case RTS51X_STAT_IDLE:
+ case RTS51X_STAT_SS:
+ usb_stor_dbg(us, "RTS51X_STAT_SS, intf->pm_usage_cnt:%d, power.usage:%d\n",
+ atomic_read(&us->pusb_intf->pm_usage_cnt),
+ atomic_read(&us->pusb_intf->dev.power.usage_count));
+
+ if (atomic_read(&us->pusb_intf->pm_usage_cnt) > 0) {
+ usb_stor_dbg(us, "Ready to enter SS state\n");
+ rts51x_set_stat(chip, RTS51X_STAT_SS);
+ /* ignore mass storage interface's children */
+ pm_suspend_ignore_children(&us->pusb_intf->dev, true);
+ usb_autopm_put_interface_async(us->pusb_intf);
+ usb_stor_dbg(us, "RTS51X_STAT_SS 01, intf->pm_usage_cnt:%d, power.usage:%d\n",
+ atomic_read(&us->pusb_intf->pm_usage_cnt),
+ atomic_read(&us->pusb_intf->dev.power.usage_count));
+ }
+ break;
+ default:
+ usb_stor_dbg(us, "Unknown state !!!\n");
+ break;
+ }
+}
+
+static inline int working_scsi(struct scsi_cmnd *srb)
+{
+ if ((srb->cmnd[0] == TEST_UNIT_READY) ||
+ (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+ struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+ static int card_first_show = 1;
+ static u8 media_not_present[] = { 0x70, 0, 0x02, 0, 0, 0, 0,
+ 10, 0, 0, 0, 0, 0x3A, 0, 0, 0, 0, 0
+ };
+ static u8 invalid_cmd_field[] = { 0x70, 0, 0x05, 0, 0, 0, 0,
+ 10, 0, 0, 0, 0, 0x24, 0, 0, 0, 0, 0
+ };
+ int ret;
+
+ if (working_scsi(srb)) {
+ usb_stor_dbg(us, "working scsi, intf->pm_usage_cnt:%d, power.usage:%d\n",
+ atomic_read(&us->pusb_intf->pm_usage_cnt),
+ atomic_read(&us->pusb_intf->dev.power.usage_count));
+
+ if (atomic_read(&us->pusb_intf->pm_usage_cnt) <= 0) {
+ ret = usb_autopm_get_interface(us->pusb_intf);
+ usb_stor_dbg(us, "working scsi, ret=%d\n", ret);
+ }
+ if (rts51x_get_stat(chip) != RTS51X_STAT_RUN)
+ rts51x_set_stat(chip, RTS51X_STAT_RUN);
+ chip->proto_handler_backup(srb, us);
+ } else {
+ if (rts51x_get_stat(chip) == RTS51X_STAT_SS) {
+ usb_stor_dbg(us, "NOT working scsi\n");
+ if ((srb->cmnd[0] == TEST_UNIT_READY) &&
+ (chip->pwr_state == US_SUSPEND)) {
+ if (TST_LUN_READY(chip, srb->device->lun)) {
+ srb->result = SAM_STAT_GOOD;
+ } else {
+ srb->result = SAM_STAT_CHECK_CONDITION;
+ memcpy(srb->sense_buffer,
+ media_not_present,
+ US_SENSE_SIZE);
+ }
+ usb_stor_dbg(us, "TEST_UNIT_READY\n");
+ goto out;
+ }
+ if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
+ int prevent = srb->cmnd[4] & 0x1;
+ if (prevent) {
+ srb->result = SAM_STAT_CHECK_CONDITION;
+ memcpy(srb->sense_buffer,
+ invalid_cmd_field,
+ US_SENSE_SIZE);
+ } else {
+ srb->result = SAM_STAT_GOOD;
+ }
+ usb_stor_dbg(us, "ALLOW_MEDIUM_REMOVAL\n");
+ goto out;
+ }
+ } else {
+ usb_stor_dbg(us, "NOT working scsi, not SS\n");
+ chip->proto_handler_backup(srb, us);
+ /* Check whether card is plugged in */
+ if (srb->cmnd[0] == TEST_UNIT_READY) {
+ if (srb->result == SAM_STAT_GOOD) {
+ SET_LUN_READY(chip, srb->device->lun);
+ if (card_first_show) {
+ card_first_show = 0;
+ fw5895_set_mmc_wp(us);
+ }
+ } else {
+ CLR_LUN_READY(chip, srb->device->lun);
+ card_first_show = 1;
+ }
+ }
+ if (rts51x_get_stat(chip) != RTS51X_STAT_IDLE)
+ rts51x_set_stat(chip, RTS51X_STAT_IDLE);
+ }
+ }
+out:
+ usb_stor_dbg(us, "state:%d\n", rts51x_get_stat(chip));
+ if (rts51x_get_stat(chip) == RTS51X_STAT_RUN)
+ rts51x_modi_suspend_timer(chip);
+}
+
+static int realtek_cr_autosuspend_setup(struct us_data *us)
+{
+ struct rts51x_chip *chip;
+ struct rts51x_status *status = NULL;
+ u8 buf[16];
+ int retval;
+
+ chip = (struct rts51x_chip *)us->extra;
+ chip->support_auto_delink = 0;
+ chip->pwr_state = US_RESUME;
+ chip->lun_ready = 0;
+ rts51x_set_stat(chip, RTS51X_STAT_INIT);
+
+ retval = rts51x_read_status(us, 0, buf, 16, &(chip->status_len));
+ if (retval != STATUS_SUCCESS) {
+ usb_stor_dbg(us, "Read status fail\n");
+ return -EIO;
+ }
+ status = chip->status;
+ status->vid = ((u16) buf[0] << 8) | buf[1];
+ status->pid = ((u16) buf[2] << 8) | buf[3];
+ status->cur_lun = buf[4];
+ status->card_type = buf[5];
+ status->total_lun = buf[6];
+ status->fw_ver = ((u16) buf[7] << 8) | buf[8];
+ status->phy_exist = buf[9];
+ status->multi_flag = buf[10];
+ status->multi_card = buf[11];
+ status->log_exist = buf[12];
+ if (chip->status_len == 16) {
+ status->detailed_type.detailed_type1 = buf[13];
+ status->function[0] = buf[14];
+ status->function[1] = buf[15];
+ }
+
+ /* back up the proto_handler in us->extra */
+ chip = (struct rts51x_chip *)(us->extra);
+ chip->proto_handler_backup = us->proto_handler;
+ /* Set the autosuspend_delay to 0 */
+ pm_runtime_set_autosuspend_delay(&us->pusb_dev->dev, 0);
+ /* override us->proto_handler setted in get_protocol() */
+ us->proto_handler = rts51x_invoke_transport;
+
+ chip->timer_expires = 0;
+ setup_timer(&chip->rts51x_suspend_timer, rts51x_suspend_timer_fn,
+ (unsigned long)chip);
+ fw5895_init(us);
+
+ /* enable autosuspend funciton of the usb device */
+ usb_enable_autosuspend(us->pusb_dev);
+
+ return 0;
+}
+#endif
+
+static void realtek_cr_destructor(void *extra)
+{
+ struct rts51x_chip *chip = extra;
+
+ if (!chip)
+ return;
+
+#ifdef CONFIG_REALTEK_AUTOPM
+ if (ss_en) {
+ del_timer(&chip->rts51x_suspend_timer);
+ chip->timer_expires = 0;
+ }
+#endif
+ kfree(chip->status);
+}
+
+#ifdef CONFIG_PM
+static int realtek_cr_suspend(struct usb_interface *iface, pm_message_t message)
+{
+ struct us_data *us = usb_get_intfdata(iface);
+
+ /* wait until no command is running */
+ mutex_lock(&us->dev_mutex);
+
+ config_autodelink_before_power_down(us);
+
+ mutex_unlock(&us->dev_mutex);
+
+ return 0;
+}
+
+static int realtek_cr_resume(struct usb_interface *iface)
+{
+ struct us_data *us = usb_get_intfdata(iface);
+
+ fw5895_init(us);
+ config_autodelink_after_power_on(us);
+
+ return 0;
+}
+#else
+#define realtek_cr_suspend NULL
+#define realtek_cr_resume NULL
+#endif
+
+static int init_realtek_cr(struct us_data *us)
+{
+ struct rts51x_chip *chip;
+ int size, i, retval;
+
+ chip = kzalloc(sizeof(struct rts51x_chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ us->extra = chip;
+ us->extra_destructor = realtek_cr_destructor;
+ us->max_lun = chip->max_lun = rts51x_get_max_lun(us);
+ chip->us = us;
+
+ usb_stor_dbg(us, "chip->max_lun = %d\n", chip->max_lun);
+
+ size = (chip->max_lun + 1) * sizeof(struct rts51x_status);
+ chip->status = kzalloc(size, GFP_KERNEL);
+ if (!chip->status)
+ goto INIT_FAIL;
+
+ for (i = 0; i <= (int)(chip->max_lun); i++) {
+ retval = rts51x_check_status(us, (u8) i);
+ if (retval < 0)
+ goto INIT_FAIL;
+ }
+
+ if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) ||
+ CHECK_FW_VER(chip, 0x5901))
+ SET_AUTO_DELINK(chip);
+ if (STATUS_LEN(chip) == 16) {
+ if (SUPPORT_AUTO_DELINK(chip))
+ SET_AUTO_DELINK(chip);
+ }
+#ifdef CONFIG_REALTEK_AUTOPM
+ if (ss_en)
+ realtek_cr_autosuspend_setup(us);
+#endif
+
+ usb_stor_dbg(us, "chip->flag = 0x%x\n", chip->flag);
+
+ (void)config_autodelink_after_power_on(us);
+
+ return 0;
+
+INIT_FAIL:
+ if (us->extra) {
+ kfree(chip->status);
+ kfree(us->extra);
+ us->extra = NULL;
+ }
+
+ return -EIO;
+}
+
+static int realtek_cr_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct us_data *us;
+ int result;
+
+ dev_dbg(&intf->dev, "Probe Realtek Card Reader!\n");
+
+ result = usb_stor_probe1(&us, intf, id,
+ (id - realtek_cr_ids) +
+ realtek_cr_unusual_dev_list);
+ if (result)
+ return result;
+
+ result = usb_stor_probe2(us);
+
+ return result;
+}
+
+static struct usb_driver realtek_cr_driver = {
+ .name = "ums-realtek",
+ .probe = realtek_cr_probe,
+ .disconnect = usb_stor_disconnect,
+ /* .suspend = usb_stor_suspend, */
+ /* .resume = usb_stor_resume, */
+ .reset_resume = usb_stor_reset_resume,
+ .suspend = realtek_cr_suspend,
+ .resume = realtek_cr_resume,
+ .pre_reset = usb_stor_pre_reset,
+ .post_reset = usb_stor_post_reset,
+ .id_table = realtek_cr_ids,
+ .soft_unbind = 1,
+ .supports_autosuspend = 1,
+ .no_dynamic_id = 1,
+};
+
+module_usb_driver(realtek_cr_driver);
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index a688b1e686e..866b5df36ed 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -104,17 +104,9 @@ static int slave_alloc (struct scsi_device *sdev)
*/
blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
- /*
- * The UFI spec treates the Peripheral Qualifier bits in an
- * INQUIRY result as reserved and requires devices to set them
- * to 0. However the SCSI spec requires these bits to be set
- * to 3 to indicate when a LUN is not present.
- *
- * Let the scanning code know if this target merely sets
- * Peripheral Device Type to 0x1f to indicate no LUN.
- */
- if (us->subclass == USB_SC_UFI)
- sdev->sdev_target->pdt_1f_for_no_lun = 1;
+ /* Tell the SCSI layer if we know there is more than one LUN */
+ if (us->protocol == USB_PR_BULK && us->max_lun > 0)
+ sdev->sdev_bflags |= BLIST_FORCELUN;
return 0;
}
@@ -123,7 +115,7 @@ static int slave_configure(struct scsi_device *sdev)
{
struct us_data *us = host_to_us(sdev->host);
- /* Many devices have trouble transfering more than 32KB at a time,
+ /* Many devices have trouble transferring more than 32KB at a time,
* while others have trouble with more than 64K. At this time we
* are limiting both to 32K (64 sectores).
*/
@@ -197,6 +189,15 @@ static int slave_configure(struct scsi_device *sdev)
* page x08, so we will skip it. */
sdev->skip_ms_page_8 = 1;
+ /* Some devices don't handle VPD pages correctly */
+ sdev->skip_vpd_pages = 1;
+
+ /* Do not attempt to use REPORT SUPPORTED OPERATION CODES */
+ sdev->no_report_opcodes = 1;
+
+ /* Do not attempt to use WRITE SAME */
+ sdev->no_write_same = 1;
+
/* Some disks return the total number of blocks in response
* to READ CAPACITY rather than the highest block number.
* If this device makes that mistake, tell the sd driver. */
@@ -213,20 +214,19 @@ static int slave_configure(struct scsi_device *sdev)
if (us->fflags & US_FL_NO_READ_CAPACITY_16)
sdev->no_read_capacity_16 = 1;
+ /*
+ * Many devices do not respond properly to READ_CAPACITY_16.
+ * Tell the SCSI layer to try READ_CAPACITY_10 first.
+ * However some USB 3.0 drive enclosures return capacity
+ * modulo 2TB. Those must use READ_CAPACITY_16
+ */
+ if (!(us->fflags & US_FL_NEEDS_CAP16))
+ sdev->try_rc_10_first = 1;
+
/* assume SPC3 or latter devices support sense size > 18 */
if (sdev->scsi_level > SCSI_SPC_2)
us->fflags |= US_FL_SANE_SENSE;
- /* Some devices report a SCSI revision level above 2 but are
- * unable to handle the REPORT LUNS command (for which
- * support is mandatory at level 3). Since we already have
- * a Get-Max-LUN request, we won't lose much by setting the
- * revision level down to 2. The only devices that would be
- * affected are those with sparse LUNs. */
- if (sdev->scsi_level > SCSI_2)
- sdev->sdev_target->scsi_level =
- sdev->scsi_level = SCSI_2;
-
/* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable
* Hardware Error) when any low-level error occurs,
* recoverable or not. Setting this flag tells the SCSI
@@ -251,6 +251,15 @@ static int slave_configure(struct scsi_device *sdev)
US_FL_SCM_MULT_TARG)) &&
us->protocol == USB_PR_BULK)
us->use_last_sector_hacks = 1;
+
+ /* Check if write cache default on flag is set or not */
+ if (us->fflags & US_FL_WRITE_CACHE)
+ sdev->wce_default_on = 1;
+
+ /* A few buggy USB-ATA bridges don't understand FUA */
+ if (us->fflags & US_FL_BROKEN_FUA)
+ sdev->broken_fua = 1;
+
} else {
/* Non-disk-type devices don't need to blacklist any pages
@@ -283,15 +292,40 @@ static int slave_configure(struct scsi_device *sdev)
return 0;
}
+static int target_alloc(struct scsi_target *starget)
+{
+ struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
+
+ /*
+ * Some USB drives don't support REPORT LUNS, even though they
+ * report a SCSI revision level above 2. Tell the SCSI layer
+ * not to issue that command; it will perform a normal sequential
+ * scan instead.
+ */
+ starget->no_report_luns = 1;
+
+ /*
+ * The UFI spec treats the Peripheral Qualifier bits in an
+ * INQUIRY result as reserved and requires devices to set them
+ * to 0. However the SCSI spec requires these bits to be set
+ * to 3 to indicate when a LUN is not present.
+ *
+ * Let the scanning code know if this target merely sets
+ * Peripheral Device Type to 0x1f to indicate no LUN.
+ */
+ if (us->subclass == USB_SC_UFI)
+ starget->pdt_1f_for_no_lun = 1;
+
+ return 0;
+}
+
/* queue a command */
/* This is always called with scsi_lock(host) held */
-static int queuecommand(struct scsi_cmnd *srb,
+static int queuecommand_lck(struct scsi_cmnd *srb,
void (*done)(struct scsi_cmnd *))
{
struct us_data *us = host_to_us(srb->device->host);
- US_DEBUGP("%s called\n", __func__);
-
/* check for state-transition errors */
if (us->srb != NULL) {
printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",
@@ -301,7 +335,7 @@ static int queuecommand(struct scsi_cmnd *srb,
/* fail the command if we are disconnecting */
if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
- US_DEBUGP("Fail command during disconnect\n");
+ usb_stor_dbg(us, "Fail command during disconnect\n");
srb->result = DID_NO_CONNECT << 16;
done(srb);
return 0;
@@ -315,6 +349,8 @@ static int queuecommand(struct scsi_cmnd *srb,
return 0;
}
+static DEF_SCSI_QCMD(queuecommand)
+
/***********************************************************************
* Error handling functions
***********************************************************************/
@@ -324,7 +360,7 @@ static int command_abort(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
- US_DEBUGP("%s called\n", __func__);
+ usb_stor_dbg(us, "%s called\n", __func__);
/* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
* bits are protected by the host lock. */
@@ -333,7 +369,7 @@ static int command_abort(struct scsi_cmnd *srb)
/* Is this command still active? */
if (us->srb != srb) {
scsi_unlock(us_to_host(us));
- US_DEBUGP ("-- nothing to abort\n");
+ usb_stor_dbg(us, "-- nothing to abort\n");
return FAILED;
}
@@ -361,7 +397,7 @@ static int device_reset(struct scsi_cmnd *srb)
struct us_data *us = host_to_us(srb->device->host);
int result;
- US_DEBUGP("%s called\n", __func__);
+ usb_stor_dbg(us, "%s called\n", __func__);
/* lock the device pointers and do the reset */
mutex_lock(&(us->dev_mutex));
@@ -377,7 +413,8 @@ static int bus_reset(struct scsi_cmnd *srb)
struct us_data *us = host_to_us(srb->device->host);
int result;
- US_DEBUGP("%s called\n", __func__);
+ usb_stor_dbg(us, "%s called\n", __func__);
+
result = usb_stor_port_reset(us);
return result < 0 ? FAILED : SUCCESS;
}
@@ -413,22 +450,21 @@ void usb_stor_report_bus_reset(struct us_data *us)
* /proc/scsi/ functions
***********************************************************************/
+static int write_info(struct Scsi_Host *host, char *buffer, int length)
+{
+ /* if someone is sending us data, just throw it away */
+ return length;
+}
+
/* we use this macro to help us write into the buffer */
#undef SPRINTF
-#define SPRINTF(args...) \
- do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
+#define SPRINTF(args...) seq_printf(m, ## args)
-static int proc_info (struct Scsi_Host *host, char *buffer,
- char **start, off_t offset, int length, int inout)
+static int show_info (struct seq_file *m, struct Scsi_Host *host)
{
struct us_data *us = host_to_us(host);
- char *pos = buffer;
const char *string;
- /* if someone is sending us data, just throw it away */
- if (inout)
- return length;
-
/* print the controller name */
SPRINTF(" Host scsi%d: usb-storage\n", host->host_no);
@@ -458,28 +494,14 @@ static int proc_info (struct Scsi_Host *host, char *buffer,
SPRINTF(" Transport: %s\n", us->transport_name);
/* show the device flags */
- if (pos < buffer + length) {
- pos += sprintf(pos, " Quirks:");
+ SPRINTF(" Quirks:");
#define US_FLAG(name, value) \
- if (us->fflags & value) pos += sprintf(pos, " " #name);
+ if (us->fflags & value) seq_printf(m, " " #name);
US_DO_ALL_FLAGS
#undef US_FLAG
-
- *(pos++) = '\n';
- }
-
- /*
- * Calculate start of next buffer, and return value.
- */
- *start = buffer + offset;
-
- if ((pos - buffer) < offset)
- return (0);
- else if ((pos - buffer - offset) < length)
- return (pos - buffer - offset);
- else
- return (length);
+ seq_putc(m, '\n');
+ return 0;
}
/***********************************************************************
@@ -487,7 +509,7 @@ US_DO_ALL_FLAGS
***********************************************************************/
/* Output routine for the sysfs max_sectors file */
-static ssize_t show_max_sectors(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t max_sectors_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
@@ -495,7 +517,7 @@ static ssize_t show_max_sectors(struct device *dev, struct device_attribute *att
}
/* Input routine for the sysfs max_sectors file */
-static ssize_t store_max_sectors(struct device *dev, struct device_attribute *attr, const char *buf,
+static ssize_t max_sectors_store(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct scsi_device *sdev = to_scsi_device(dev);
@@ -505,16 +527,14 @@ static ssize_t store_max_sectors(struct device *dev, struct device_attribute *at
blk_queue_max_hw_sectors(sdev->request_queue, ms);
return count;
}
- return -EINVAL;
+ return -EINVAL;
}
-
-static DEVICE_ATTR(max_sectors, S_IRUGO | S_IWUSR, show_max_sectors,
- store_max_sectors);
+static DEVICE_ATTR_RW(max_sectors);
static struct device_attribute *sysfs_device_attr_list[] = {
- &dev_attr_max_sectors,
- NULL,
- };
+ &dev_attr_max_sectors,
+ NULL,
+};
/*
* this defines our host template, with which we'll allocate hosts
@@ -524,7 +544,8 @@ struct scsi_host_template usb_stor_host_template = {
/* basic userland interface stuff */
.name = "usb-storage",
.proc_name = "usb-storage",
- .proc_info = proc_info,
+ .show_info = show_info,
+ .write_info = write_info,
.info = host_info,
/* command interface -- queued only */
@@ -544,6 +565,7 @@ struct scsi_host_template usb_stor_host_template = {
.slave_alloc = slave_alloc,
.slave_configure = slave_configure,
+ .target_alloc = target_alloc,
/* lots of sg segments can be handled */
.sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS,
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index bcb9a709d34..073a2c32ccc 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -69,9 +69,9 @@ static int usb_stor_sddr09_init(struct us_data *us);
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
- .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ .driver_info = (flags) }
-struct usb_device_id sddr09_usb_ids[] = {
+static struct usb_device_id sddr09_usb_ids[] = {
# include "unusual_sddr09.h"
{ } /* Terminating entry */
};
@@ -105,8 +105,6 @@ static struct us_unusual_dev sddr09_unusual_dev_list[] = {
#define LSB_of(s) ((s)&0xFF)
#define MSB_of(s) ((s)>>8)
-/* #define US_DEBUGP printk */
-
/*
* First some stuff that does not belong here:
* data on SmartMedia and other cards, completely
@@ -221,11 +219,7 @@ static void nand_init_ecc(void) {
/* compute 3-byte ecc on 256 bytes */
static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) {
int i, j, a;
- unsigned char par, bit, bits[8];
-
- par = 0;
- for (j = 0; j < 8; j++)
- bits[j] = 0;
+ unsigned char par = 0, bit, bits[8] = {0};
/* collect 16 checksum bits */
for (i = 0; i < 256; i++) {
@@ -347,7 +341,7 @@ sddr09_test_unit_ready(struct us_data *us) {
result = sddr09_send_scsi_command(us, command, 6);
- US_DEBUGP("sddr09_test_unit_ready returns %d\n", result);
+ usb_stor_dbg(us, "sddr09_test_unit_ready returns %d\n", result);
return result;
}
@@ -423,8 +417,8 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,
result = sddr09_send_scsi_command(us, command, 12);
if (result) {
- US_DEBUGP("Result for send_control in sddr09_read2%d %d\n",
- x, result);
+ usb_stor_dbg(us, "Result for send_control in sddr09_read2%d %d\n",
+ x, result);
return result;
}
@@ -432,8 +426,8 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,
buf, bulklen, use_sg, NULL);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for bulk_transfer in sddr09_read2%d %d\n",
- x, result);
+ usb_stor_dbg(us, "Result for bulk_transfer in sddr09_read2%d %d\n",
+ x, result);
return -EIO;
}
return 0;
@@ -494,8 +488,7 @@ sddr09_read22(struct us_data *us, unsigned long fromaddress,
int nr_of_pages, int pageshift, unsigned char *buf, int use_sg) {
int bulklen = (nr_of_pages << pageshift) + (nr_of_pages << CONTROL_SHIFT);
- US_DEBUGP("sddr09_read22: reading %d pages, %d bytes\n",
- nr_of_pages, bulklen);
+ usb_stor_dbg(us, "reading %d pages, %d bytes\n", nr_of_pages, bulklen);
return sddr09_readX(us, 2, fromaddress, nr_of_pages, bulklen,
buf, use_sg);
}
@@ -538,7 +531,7 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) {
unsigned char *command = us->iobuf;
int result;
- US_DEBUGP("sddr09_erase: erase address %lu\n", Eaddress);
+ usb_stor_dbg(us, "erase address %lu\n", Eaddress);
memset(command, 0, 12);
command[0] = 0xEA;
@@ -551,8 +544,8 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) {
result = sddr09_send_scsi_command(us, command, 12);
if (result)
- US_DEBUGP("Result for send_control in sddr09_erase %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_control in sddr09_erase %d\n",
+ result);
return result;
}
@@ -609,8 +602,8 @@ sddr09_writeX(struct us_data *us,
result = sddr09_send_scsi_command(us, command, 12);
if (result) {
- US_DEBUGP("Result for send_control in sddr09_writeX %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_control in sddr09_writeX %d\n",
+ result);
return result;
}
@@ -618,8 +611,8 @@ sddr09_writeX(struct us_data *us,
buf, bulklen, use_sg, NULL);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for bulk_transfer in sddr09_writeX %d\n",
- result);
+ usb_stor_dbg(us, "Result for bulk_transfer in sddr09_writeX %d\n",
+ result);
return -EIO;
}
return 0;
@@ -687,8 +680,8 @@ sddr09_read_sg_test_only(struct us_data *us) {
result = sddr09_send_scsi_command(us, command, 4*nsg+3);
if (result) {
- US_DEBUGP("Result for send_control in sddr09_read_sg %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_control in sddr09_read_sg %d\n",
+ result);
return result;
}
@@ -700,8 +693,8 @@ sddr09_read_sg_test_only(struct us_data *us) {
buf, bulklen, NULL);
kfree(buf);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for bulk_transfer in sddr09_read_sg %d\n",
- result);
+ usb_stor_dbg(us, "Result for bulk_transfer in sddr09_read_sg %d\n",
+ result);
return -EIO;
}
@@ -727,7 +720,7 @@ sddr09_read_status(struct us_data *us, unsigned char *status) {
unsigned char *data = us->iobuf;
int result;
- US_DEBUGP("Reading status...\n");
+ usb_stor_dbg(us, "Reading status...\n");
memset(command, 0, 12);
command[0] = 0xEC;
@@ -789,8 +782,8 @@ sddr09_read_data(struct us_data *us,
/* Not overflowing capacity? */
if (lba >= maxlba) {
- US_DEBUGP("Error: Requested lba %u exceeds "
- "maximum %u\n", lba, maxlba);
+ usb_stor_dbg(us, "Error: Requested lba %u exceeds maximum %u\n",
+ lba, maxlba);
result = -EIO;
break;
}
@@ -800,8 +793,8 @@ sddr09_read_data(struct us_data *us,
if (pba == UNDEF) { /* this lba was never written */
- US_DEBUGP("Read %d zero pages (LBA %d) page %d\n",
- pages, lba, page);
+ usb_stor_dbg(us, "Read %d zero pages (LBA %d) page %d\n",
+ pages, lba, page);
/* This is not really an error. It just means
that the block has never been written.
@@ -811,9 +804,8 @@ sddr09_read_data(struct us_data *us,
memset(buffer, 0, len);
} else {
- US_DEBUGP("Read %d pages, from PBA %d"
- " (LBA %d) page %d\n",
- pages, pba, lba, page);
+ usb_stor_dbg(us, "Read %d pages, from PBA %d (LBA %d) page %d\n",
+ pages, pba, lba, page);
address = ((pba << info->blockshift) + page) <<
info->pageshift;
@@ -916,14 +908,14 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
cptr = bptr + info->pagesize;
nand_compute_ecc(bptr, ecc);
if (!nand_compare_ecc(cptr+13, ecc)) {
- US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n",
- i, pba);
+ usb_stor_dbg(us, "Warning: bad ecc in page %d- of pba %d\n",
+ i, pba);
nand_store_ecc(cptr+13, ecc);
}
nand_compute_ecc(bptr+(info->pagesize / 2), ecc);
if (!nand_compare_ecc(cptr+8, ecc)) {
- US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n",
- i, pba);
+ usb_stor_dbg(us, "Warning: bad ecc in page %d+ of pba %d\n",
+ i, pba);
nand_store_ecc(cptr+8, ecc);
}
cptr[6] = cptr[11] = MSB_of(lbap);
@@ -943,22 +935,21 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
nand_store_ecc(cptr+8, ecc);
}
- US_DEBUGP("Rewrite PBA %d (LBA %d)\n", pba, lba);
+ usb_stor_dbg(us, "Rewrite PBA %d (LBA %d)\n", pba, lba);
result = sddr09_write_inplace(us, address>>1, info->blocksize,
info->pageshift, blockbuffer, 0);
- US_DEBUGP("sddr09_write_inplace returns %d\n", result);
+ usb_stor_dbg(us, "sddr09_write_inplace returns %d\n", result);
#if 0
{
unsigned char status = 0;
int result2 = sddr09_read_status(us, &status);
if (result2)
- US_DEBUGP("sddr09_write_inplace: cannot read status\n");
+ usb_stor_dbg(us, "cannot read status\n");
else if (status != 0xc0)
- US_DEBUGP("sddr09_write_inplace: status after write: 0x%x\n",
- status);
+ usb_stor_dbg(us, "status after write: 0x%x\n", status);
}
#endif
@@ -1031,8 +1022,8 @@ sddr09_write_data(struct us_data *us,
/* Not overflowing capacity? */
if (lba >= maxlba) {
- US_DEBUGP("Error: Requested lba %u exceeds "
- "maximum %u\n", lba, maxlba);
+ usb_stor_dbg(us, "Error: Requested lba %u exceeds maximum %u\n",
+ lba, maxlba);
result = -EIO;
break;
}
@@ -1064,8 +1055,8 @@ sddr09_read_control(struct us_data *us,
unsigned char *content,
int use_sg) {
- US_DEBUGP("Read control address %lu, blocks %d\n",
- address, blocks);
+ usb_stor_dbg(us, "Read control address %lu, blocks %d\n",
+ address, blocks);
return sddr09_read21(us, address, blocks,
CONTROL_SHIFT, content, use_sg);
@@ -1111,21 +1102,21 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) {
result = sddr09_read_status(us, &status);
if (result) {
- US_DEBUGP("sddr09_get_wp: read_status fails\n");
+ usb_stor_dbg(us, "read_status fails\n");
return result;
}
- US_DEBUGP("sddr09_get_wp: status 0x%02X", status);
+ usb_stor_dbg(us, "status 0x%02X", status);
if ((status & 0x80) == 0) {
info->flags |= SDDR09_WP; /* write protected */
- US_DEBUGP(" WP");
+ US_DEBUGPX(" WP");
}
if (status & 0x40)
- US_DEBUGP(" Ready");
+ US_DEBUGPX(" Ready");
if (status & LUNBITS)
- US_DEBUGP(" Suspended");
+ US_DEBUGPX(" Suspended");
if (status & 0x1)
- US_DEBUGP(" Error");
- US_DEBUGP("\n");
+ US_DEBUGPX(" Error");
+ US_DEBUGPX("\n");
return 0;
}
@@ -1154,12 +1145,12 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) {
char blurbtxt[256];
int result;
- US_DEBUGP("Reading capacity...\n");
+ usb_stor_dbg(us, "Reading capacity...\n");
result = sddr09_read_deviceID(us, deviceID);
if (result) {
- US_DEBUGP("Result of read_deviceID is %d\n", result);
+ usb_stor_dbg(us, "Result of read_deviceID is %d\n", result);
printk(KERN_WARNING "sddr09: could not read card info\n");
return NULL;
}
@@ -1392,7 +1383,7 @@ sddr09_read_map(struct us_data *us) {
lbact += ct;
}
info->lbact = lbact;
- US_DEBUGP("Found %d LBA's\n", lbact);
+ usb_stor_dbg(us, "Found %d LBA's\n", lbact);
result = 0;
done:
@@ -1423,18 +1414,18 @@ sddr09_common_init(struct us_data *us) {
/* set the configuration -- STALL is an acceptable response here */
if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) {
- US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev
- ->actconfig->desc.bConfigurationValue);
+ usb_stor_dbg(us, "active config #%d != 1 ??\n",
+ us->pusb_dev->actconfig->desc.bConfigurationValue);
return -EINVAL;
}
result = usb_reset_configuration(us->pusb_dev);
- US_DEBUGP("Result of usb_reset_configuration is %d\n", result);
+ usb_stor_dbg(us, "Result of usb_reset_configuration is %d\n", result);
if (result == -EPIPE) {
- US_DEBUGP("-- stall on control interface\n");
+ usb_stor_dbg(us, "-- stall on control interface\n");
} else if (result != 0) {
/* it's not a stall, but another error -- time to bail */
- US_DEBUGP("-- Unknown error. Rejecting device\n");
+ usb_stor_dbg(us, "-- Unknown error. Rejecting device\n");
return -EINVAL;
}
@@ -1464,20 +1455,20 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) {
result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2);
if (result) {
- US_DEBUGP("sddr09_init: send_command fails\n");
+ usb_stor_dbg(us, "send_command fails\n");
return result;
}
- US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]);
+ usb_stor_dbg(us, "%02X %02X\n", data[0], data[1]);
// get 07 02
result = sddr09_send_command(us, 0x08, USB_DIR_IN, data, 2);
if (result) {
- US_DEBUGP("sddr09_init: 2nd send_command fails\n");
+ usb_stor_dbg(us, "2nd send_command fails\n");
return result;
}
- US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]);
+ usb_stor_dbg(us, "%02X %02X\n", data[0], data[1]);
// get 07 00
result = sddr09_request_sense(us, data, 18);
@@ -1507,7 +1498,7 @@ static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
{
int ret;
- US_DEBUGP("dpcm_transport: LUN=%d\n", srb->device->lun);
+ usb_stor_dbg(us, "LUN=%d\n", srb->device->lun);
switch (srb->device->lun) {
case 0:
@@ -1533,8 +1524,7 @@ static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
break;
default:
- US_DEBUGP("dpcm_transport: Invalid LUN %d\n",
- srb->device->lun);
+ usb_stor_dbg(us, "Invalid LUN %d\n", srb->device->lun);
ret = USB_STOR_TRANSPORT_ERROR;
break;
}
@@ -1640,8 +1630,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
or for all pages. */
/* %% We should check DBD %% */
if (modepage == 0x01 || modepage == 0x3F) {
- US_DEBUGP("SDDR09: Dummy up request for "
- "mode page 0x%x\n", modepage);
+ usb_stor_dbg(us, "Dummy up request for mode page 0x%x\n",
+ modepage);
memcpy(ptr, mode_page_01, sizeof(mode_page_01));
((__be16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2);
@@ -1667,8 +1657,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
- US_DEBUGP("READ_10: read page %d pagect %d\n",
- page, pages);
+ usb_stor_dbg(us, "READ_10: read page %d pagect %d\n",
+ page, pages);
result = sddr09_read_data(us, page, pages);
return (result == 0 ? USB_STOR_TRANSPORT_GOOD :
@@ -1682,8 +1672,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
- US_DEBUGP("WRITE_10: write page %d pagect %d\n",
- page, pages);
+ usb_stor_dbg(us, "WRITE_10: write page %d pagect %d\n",
+ page, pages);
result = sddr09_write_data(us, page, pages);
return (result == 0 ? USB_STOR_TRANSPORT_GOOD :
@@ -1710,12 +1700,12 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
for (i=0; i<12; i++)
sprintf(ptr+strlen(ptr), "%02X ", srb->cmnd[i]);
- US_DEBUGP("SDDR09: Send control for command %s\n", ptr);
+ usb_stor_dbg(us, "Send control for command %s\n", ptr);
result = sddr09_send_scsi_command(us, srb->cmnd, 12);
if (result) {
- US_DEBUGP("sddr09_transport: sddr09_send_scsi_command "
- "returns %d\n", result);
+ usb_stor_dbg(us, "sddr09_send_scsi_command returns %d\n",
+ result);
return USB_STOR_TRANSPORT_ERROR;
}
@@ -1727,10 +1717,10 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
unsigned int pipe = (srb->sc_data_direction == DMA_TO_DEVICE)
? us->send_bulk_pipe : us->recv_bulk_pipe;
- US_DEBUGP("SDDR09: %s %d bytes\n",
- (srb->sc_data_direction == DMA_TO_DEVICE) ?
- "sending" : "receiving",
- scsi_bufflen(srb));
+ usb_stor_dbg(us, "%s %d bytes\n",
+ (srb->sc_data_direction == DMA_TO_DEVICE) ?
+ "sending" : "receiving",
+ scsi_bufflen(srb));
result = usb_stor_bulk_srb(us, pipe, srb);
@@ -1787,17 +1777,7 @@ static struct usb_driver sddr09_driver = {
.post_reset = usb_stor_post_reset,
.id_table = sddr09_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
-static int __init sddr09_init(void)
-{
- return usb_register(&sddr09_driver);
-}
-
-static void __exit sddr09_exit(void)
-{
- usb_deregister(&sddr09_driver);
-}
-
-module_init(sddr09_init);
-module_exit(sddr09_exit);
+module_usb_driver(sddr09_driver);
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index 44dfed7754e..aacedef9667 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -46,9 +46,9 @@ MODULE_LICENSE("GPL");
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
- .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ .driver_info = (flags) }
-struct usb_device_id sddr55_usb_ids[] = {
+static struct usb_device_id sddr55_usb_ids[] = {
# include "unusual_sddr55.h"
{ } /* Terminating entry */
};
@@ -145,8 +145,7 @@ static int sddr55_status(struct us_data *us)
result = sddr55_bulk_transport(us,
DMA_TO_DEVICE, command, 8);
- US_DEBUGP("Result for send_command in status %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_command in status %d\n", result);
if (result != USB_STOR_XFER_GOOD) {
set_sense_info (4, 0, 0); /* hardware error */
@@ -236,9 +235,8 @@ static int sddr55_read_data(struct us_data *us,
info->blocksize - page);
len = pages << info->pageshift;
- US_DEBUGP("Read %02X pages, from PBA %04X"
- " (LBA %04X) page %02X\n",
- pages, pba, lba, page);
+ usb_stor_dbg(us, "Read %02X pages, from PBA %04X (LBA %04X) page %02X\n",
+ pages, pba, lba, page);
if (pba == NOT_ALLOCATED) {
/* no pba for this lba, fill with zeroes */
@@ -261,8 +259,8 @@ static int sddr55_read_data(struct us_data *us,
result = sddr55_bulk_transport(us,
DMA_TO_DEVICE, command, 8);
- US_DEBUGP("Result for send_command in read_data %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_command in read_data %d\n",
+ result);
if (result != USB_STOR_XFER_GOOD) {
result = USB_STOR_TRANSPORT_ERROR;
@@ -368,9 +366,8 @@ static int sddr55_write_data(struct us_data *us,
usb_stor_access_xfer_buf(buffer, len, us->srb,
&sg, &offset, FROM_XFER_BUF);
- US_DEBUGP("Write %02X pages, to PBA %04X"
- " (LBA %04X) page %02X\n",
- pages, pba, lba, page);
+ usb_stor_dbg(us, "Write %02X pages, to PBA %04X (LBA %04X) page %02X\n",
+ pages, pba, lba, page);
command[4] = 0;
@@ -384,7 +381,7 @@ static int sddr55_write_data(struct us_data *us,
/* set pba to first block in zone lba is in */
pba = (lba / 1000) * 1024;
- US_DEBUGP("No PBA for LBA %04X\n",lba);
+ usb_stor_dbg(us, "No PBA for LBA %04X\n", lba);
if (max_pba > 1024)
max_pba = 1024;
@@ -407,14 +404,15 @@ static int sddr55_write_data(struct us_data *us,
if (pba == -1) {
/* oh dear */
- US_DEBUGP("Couldn't find unallocated block\n");
+ usb_stor_dbg(us, "Couldn't find unallocated block\n");
set_sense_info (3, 0x31, 0); /* medium error */
result = USB_STOR_TRANSPORT_FAILED;
goto leave;
}
- US_DEBUGP("Allocating PBA %04X for LBA %04X\n", pba, lba);
+ usb_stor_dbg(us, "Allocating PBA %04X for LBA %04X\n",
+ pba, lba);
/* set writing to unallocated block flag */
command[4] = 0x40;
@@ -439,8 +437,8 @@ static int sddr55_write_data(struct us_data *us,
DMA_TO_DEVICE, command, 8);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for send_command in write_data %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_command in write_data %d\n",
+ result);
/* set_sense_info is superfluous here? */
set_sense_info (3, 0x3, 0);/* peripheral write error */
@@ -453,8 +451,8 @@ static int sddr55_write_data(struct us_data *us,
DMA_TO_DEVICE, buffer, len);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for send_data in write_data %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_data in write_data %d\n",
+ result);
/* set_sense_info is superfluous here? */
set_sense_info (3, 0x3, 0);/* peripheral write error */
@@ -466,8 +464,8 @@ static int sddr55_write_data(struct us_data *us,
result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for get_status in write_data %d\n",
- result);
+ usb_stor_dbg(us, "Result for get_status in write_data %d\n",
+ result);
/* set_sense_info is superfluous here? */
set_sense_info (3, 0x3, 0);/* peripheral write error */
@@ -487,8 +485,8 @@ static int sddr55_write_data(struct us_data *us,
goto leave;
}
- US_DEBUGP("Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n",
- lba, pba, new_pba);
+ usb_stor_dbg(us, "Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n",
+ lba, pba, new_pba);
/* update the lba<->pba maps, note new_pba might be the same as pba */
info->lba_to_pba[lba] = new_pba;
@@ -531,8 +529,8 @@ static int sddr55_read_deviceID(struct us_data *us,
command[7] = 0x84;
result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8);
- US_DEBUGP("Result of send_control for device ID is %d\n",
- result);
+ usb_stor_dbg(us, "Result of send_control for device ID is %d\n",
+ result);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -568,20 +566,19 @@ static unsigned long sddr55_get_capacity(struct us_data *us) {
int result;
struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
- US_DEBUGP("Reading capacity...\n");
+ usb_stor_dbg(us, "Reading capacity...\n");
result = sddr55_read_deviceID(us,
&manufacturerID,
&deviceID);
- US_DEBUGP("Result of read_deviceID is %d\n",
- result);
+ usb_stor_dbg(us, "Result of read_deviceID is %d\n", result);
if (result != USB_STOR_XFER_GOOD)
return 0;
- US_DEBUGP("Device ID = %02X\n", deviceID);
- US_DEBUGP("Manuf ID = %02X\n", manufacturerID);
+ usb_stor_dbg(us, "Device ID = %02X\n", deviceID);
+ usb_stor_dbg(us, "Manuf ID = %02X\n", manufacturerID);
info->pageshift = 9;
info->smallpageshift = 0;
@@ -753,7 +750,7 @@ static int sddr55_read_map(struct us_data *us) {
}
if (lba<0x10 || (lba>=0x3E0 && lba<0x3EF))
- US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i);
+ usb_stor_dbg(us, "LBA %04X <-> PBA %04X\n", lba, i);
info->lba_to_pba[lba + zone * 1000] = i;
}
@@ -808,7 +805,10 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
info = (struct sddr55_card_info *)(us->extra);
if (srb->cmnd[0] == REQUEST_SENSE) {
- US_DEBUGP("SDDR55: request sense %02x/%02x/%02x\n", info->sense_data[2], info->sense_data[12], info->sense_data[13]);
+ usb_stor_dbg(us, "request sense %02x/%02x/%02x\n",
+ info->sense_data[2],
+ info->sense_data[12],
+ info->sense_data[13]);
memcpy (ptr, info->sense_data, sizeof info->sense_data);
ptr[0] = 0x70;
@@ -892,13 +892,11 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb);
if ( (srb->cmnd[2] & 0x3F) == 0x01 ) {
- US_DEBUGP(
- "SDDR55: Dummy up request for mode page 1\n");
+ usb_stor_dbg(us, "Dummy up request for mode page 1\n");
return USB_STOR_TRANSPORT_GOOD;
} else if ( (srb->cmnd[2] & 0x3F) == 0x3F ) {
- US_DEBUGP(
- "SDDR55: Dummy up request for all mode pages\n");
+ usb_stor_dbg(us, "Dummy up request for all mode pages\n");
return USB_STOR_TRANSPORT_GOOD;
}
@@ -908,10 +906,8 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
- US_DEBUGP(
- "SDDR55: %s medium removal. Not that I can do"
- " anything about it...\n",
- (srb->cmnd[4]&0x03) ? "Prevent" : "Allow");
+ usb_stor_dbg(us, "%s medium removal. Not that I can do anything about it...\n",
+ (srb->cmnd[4]&0x03) ? "Prevent" : "Allow");
return USB_STOR_TRANSPORT_GOOD;
@@ -935,8 +931,8 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
if (lba >= info->max_log_blks) {
- US_DEBUGP("Error: Requested LBA %04X exceeds maximum "
- "block %04X\n", lba, info->max_log_blks-1);
+ usb_stor_dbg(us, "Error: Requested LBA %04X exceeds maximum block %04X\n",
+ lba, info->max_log_blks - 1);
set_sense_info (5, 0x24, 0); /* invalid field in command */
@@ -946,15 +942,13 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
pba = info->lba_to_pba[lba];
if (srb->cmnd[0] == WRITE_10) {
- US_DEBUGP("WRITE_10: write block %04X (LBA %04X) page %01X"
- " pages %d\n",
- pba, lba, page, pages);
+ usb_stor_dbg(us, "WRITE_10: write block %04X (LBA %04X) page %01X pages %d\n",
+ pba, lba, page, pages);
return sddr55_write_data(us, lba, page, pages);
} else {
- US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X"
- " pages %d\n",
- pba, lba, page, pages);
+ usb_stor_dbg(us, "READ_10: read block %04X (LBA %04X) page %01X pages %d\n",
+ pba, lba, page, pages);
return sddr55_read_data(us, lba, page, pages);
}
@@ -1006,17 +1000,7 @@ static struct usb_driver sddr55_driver = {
.post_reset = usb_stor_post_reset,
.id_table = sddr55_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
-static int __init sddr55_init(void)
-{
- return usb_register(&sddr55_driver);
-}
-
-static void __exit sddr55_exit(void)
-{
- usb_deregister(&sddr55_driver);
-}
-
-module_init(sddr55_init);
-module_exit(sddr55_exit);
+module_usb_driver(sddr55_driver);
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index bd3f415893d..008d805c3d2 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -168,9 +168,9 @@ static int init_usbat_flash(struct us_data *us);
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
- .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ .driver_info = (flags) }
-struct usb_device_id usbat_usb_ids[] = {
+static struct usb_device_id usbat_usb_ids[] = {
# include "unusual_usbat.h"
{ } /* Terminating entry */
};
@@ -271,7 +271,7 @@ static int usbat_bulk_read(struct us_data *us,
if (len == 0)
return USB_STOR_XFER_GOOD;
- US_DEBUGP("usbat_bulk_read: len = %d\n", len);
+ usb_stor_dbg(us, "len = %d\n", len);
return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, buf, len, use_sg, NULL);
}
@@ -286,7 +286,7 @@ static int usbat_bulk_write(struct us_data *us,
if (len == 0)
return USB_STOR_XFER_GOOD;
- US_DEBUGP("usbat_bulk_write: len = %d\n", len);
+ usb_stor_dbg(us, "len = %d\n", len);
return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, buf, len, use_sg, NULL);
}
@@ -312,7 +312,7 @@ static int usbat_get_status(struct us_data *us, unsigned char *status)
int rc;
rc = usbat_read(us, USBAT_ATA, USBAT_ATA_STATUS, status);
- US_DEBUGP("usbat_get_status: 0x%02X\n", (unsigned short) (*status));
+ usb_stor_dbg(us, "0x%02X\n", *status);
return rc;
}
@@ -340,7 +340,7 @@ static int usbat_check_status(struct us_data *us)
}
/*
- * Stores critical information in internal registers in prepartion for the execution
+ * Stores critical information in internal registers in preparation for the execution
* of a conditional usbat_read_blocks or usbat_write_blocks call.
*/
static int usbat_set_shuttle_features(struct us_data *us,
@@ -425,7 +425,7 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)
return USB_STOR_TRANSPORT_FAILED;
if ((*status & 0x80)==0x00) { /* not busy */
- US_DEBUGP("Waited not busy for %d steps\n", i);
+ usb_stor_dbg(us, "Waited not busy for %d steps\n", i);
return USB_STOR_TRANSPORT_GOOD;
}
@@ -439,8 +439,8 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)
msleep(1000); /* X minutes */
}
- US_DEBUGP("Waited not busy for %d minutes, timing out.\n",
- minutes);
+ usb_stor_dbg(us, "Waited not busy for %d minutes, timing out\n",
+ minutes);
return USB_STOR_TRANSPORT_FAILED;
}
@@ -657,8 +657,9 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
if (*status & 0x20) /* device fault */
return USB_STOR_TRANSPORT_FAILED;
- US_DEBUGP("Redoing %s\n",
- direction==DMA_TO_DEVICE ? "write" : "read");
+ usb_stor_dbg(us, "Redoing %s\n",
+ direction == DMA_TO_DEVICE
+ ? "write" : "read");
} else if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -667,8 +668,8 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
}
- US_DEBUGP("Bummer! %s bulk data 20 times failed.\n",
- direction==DMA_TO_DEVICE ? "Writing" : "Reading");
+ usb_stor_dbg(us, "Bummer! %s bulk data 20 times failed\n",
+ direction == DMA_TO_DEVICE ? "Writing" : "Reading");
return USB_STOR_TRANSPORT_FAILED;
}
@@ -827,7 +828,7 @@ static int usbat_read_user_io(struct us_data *us, unsigned char *data_flags)
data_flags,
USBAT_UIO_READ);
- US_DEBUGP("usbat_read_user_io: UIO register reads %02X\n", (unsigned short) (*data_flags));
+ usb_stor_dbg(us, "UIO register reads %02X\n", *data_flags);
return result;
}
@@ -900,10 +901,11 @@ static int usbat_device_enable_cdt(struct us_data *us)
/*
* Determine if media is present.
*/
-static int usbat_flash_check_media_present(unsigned char *uio)
+static int usbat_flash_check_media_present(struct us_data *us,
+ unsigned char *uio)
{
if (*uio & USBAT_UIO_UI0) {
- US_DEBUGP("usbat_flash_check_media_present: no media detected\n");
+ usb_stor_dbg(us, "no media detected\n");
return USBAT_FLASH_MEDIA_NONE;
}
@@ -913,10 +915,11 @@ static int usbat_flash_check_media_present(unsigned char *uio)
/*
* Determine if media has changed since last operation
*/
-static int usbat_flash_check_media_changed(unsigned char *uio)
+static int usbat_flash_check_media_changed(struct us_data *us,
+ unsigned char *uio)
{
if (*uio & USBAT_UIO_0) {
- US_DEBUGP("usbat_flash_check_media_changed: media change detected\n");
+ usb_stor_dbg(us, "media change detected\n");
return USBAT_FLASH_MEDIA_CHANGED;
}
@@ -937,7 +940,7 @@ static int usbat_flash_check_media(struct us_data *us,
return USB_STOR_TRANSPORT_ERROR;
/* Check for media existence */
- rc = usbat_flash_check_media_present(uio);
+ rc = usbat_flash_check_media_present(us, uio);
if (rc == USBAT_FLASH_MEDIA_NONE) {
info->sense_key = 0x02;
info->sense_asc = 0x3A;
@@ -946,7 +949,7 @@ static int usbat_flash_check_media(struct us_data *us,
}
/* Check for media change */
- rc = usbat_flash_check_media_changed(uio);
+ rc = usbat_flash_check_media_changed(us, uio);
if (rc == USBAT_FLASH_MEDIA_CHANGED) {
/* Reset and re-enable card detect */
@@ -1008,11 +1011,11 @@ static int usbat_identify_device(struct us_data *us,
/* Check for error bit, or if the command 'fell through' */
if (status == 0xA1 || !(status & 0x01)) {
/* Device is HP 8200 */
- US_DEBUGP("usbat_identify_device: Detected HP8200 CDRW\n");
+ usb_stor_dbg(us, "Detected HP8200 CDRW\n");
info->devicetype = USBAT_DEV_HP8200;
} else {
/* Device is a CompactFlash reader/writer */
- US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");
+ usb_stor_dbg(us, "Detected Flash reader/writer\n");
info->devicetype = USBAT_DEV_FLASH;
}
@@ -1075,7 +1078,7 @@ static int usbat_flash_get_sector_count(struct us_data *us,
/* ATA command : IDENTIFY DEVICE */
rc = usbat_multiple_write(us, registers, command, 3);
if (rc != USB_STOR_XFER_GOOD) {
- US_DEBUGP("usbat_flash_get_sector_count: Gah! identify_device failed\n");
+ usb_stor_dbg(us, "Gah! identify_device failed\n");
rc = USB_STOR_TRANSPORT_ERROR;
goto leave;
}
@@ -1178,7 +1181,7 @@ static int usbat_flash_read_data(struct us_data *us,
if (result != USB_STOR_TRANSPORT_GOOD)
goto leave;
- US_DEBUGP("usbat_flash_read_data: %d bytes\n", len);
+ usb_stor_dbg(us, "%d bytes\n", len);
/* Store the data in the transfer buffer */
usb_stor_access_xfer_buf(buffer, len, us->srb,
@@ -1301,8 +1304,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
unsigned int sg_offset = 0;
struct scatterlist *sg = NULL;
- US_DEBUGP("handle_read10: transfersize %d\n",
- srb->transfersize);
+ usb_stor_dbg(us, "transfersize %d\n", srb->transfersize);
if (scsi_bufflen(srb) < 0x10000) {
@@ -1329,14 +1331,14 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
len = short_pack(data[7+9], data[7+8]);
len <<= 16;
len |= data[7+7];
- US_DEBUGP("handle_read10: GPCMD_READ_CD: len %d\n", len);
+ usb_stor_dbg(us, "GPCMD_READ_CD: len %d\n", len);
srb->transfersize = scsi_bufflen(srb)/len;
}
if (!srb->transfersize) {
srb->transfersize = 2048; /* A guess */
- US_DEBUGP("handle_read10: transfersize 0, forcing %d\n",
- srb->transfersize);
+ usb_stor_dbg(us, "transfersize 0, forcing %d\n",
+ srb->transfersize);
}
/*
@@ -1346,7 +1348,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
*/
len = (65535/srb->transfersize) * srb->transfersize;
- US_DEBUGP("Max read is %d bytes\n", len);
+ usb_stor_dbg(us, "Max read is %d bytes\n", len);
len = min(len, scsi_bufflen(srb));
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL) /* bloody hell! */
@@ -1460,10 +1462,9 @@ static int init_usbat(struct us_data *us, int devicetype)
unsigned char *status = us->iobuf;
us->extra = kzalloc(sizeof(struct usbat_info), GFP_NOIO);
- if (!us->extra) {
- US_DEBUGP("init_usbat: Gah! Can't allocate storage for usbat info struct!\n");
+ if (!us->extra)
return 1;
- }
+
info = (struct usbat_info *) (us->extra);
/* Enable peripheral control signals */
@@ -1473,7 +1474,7 @@ static int init_usbat(struct us_data *us, int devicetype)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 1\n");
+ usb_stor_dbg(us, "INIT 1\n");
msleep(2000);
@@ -1481,7 +1482,7 @@ static int init_usbat(struct us_data *us, int devicetype)
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 2\n");
+ usb_stor_dbg(us, "INIT 2\n");
rc = usbat_read_user_io(us, status);
if (rc != USB_STOR_XFER_GOOD)
@@ -1491,32 +1492,32 @@ static int init_usbat(struct us_data *us, int devicetype)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 3\n");
+ usb_stor_dbg(us, "INIT 3\n");
rc = usbat_select_and_test_registers(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 4\n");
+ usb_stor_dbg(us, "INIT 4\n");
rc = usbat_read_user_io(us, status);
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 5\n");
+ usb_stor_dbg(us, "INIT 5\n");
/* Enable peripheral control signals and card detect */
rc = usbat_device_enable_cdt(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 6\n");
+ usb_stor_dbg(us, "INIT 6\n");
rc = usbat_read_user_io(us, status);
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 7\n");
+ usb_stor_dbg(us, "INIT 7\n");
msleep(1400);
@@ -1524,19 +1525,19 @@ static int init_usbat(struct us_data *us, int devicetype)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 8\n");
+ usb_stor_dbg(us, "INIT 8\n");
rc = usbat_select_and_test_registers(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 9\n");
+ usb_stor_dbg(us, "INIT 9\n");
/* At this point, we need to detect which device we are using */
if (usbat_set_transport(us, info, devicetype))
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 10\n");
+ usb_stor_dbg(us, "INIT 10\n");
if (usbat_get_device_type(us) == USBAT_DEV_FLASH) {
subcountH = 0x02;
@@ -1547,7 +1548,7 @@ static int init_usbat(struct us_data *us, int devicetype)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 11\n");
+ usb_stor_dbg(us, "INIT 11\n");
return USB_STOR_TRANSPORT_GOOD;
}
@@ -1592,7 +1593,7 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
}
result = usbat_get_status(us, status);
- US_DEBUGP("Status = %02X\n", *status);
+ usb_stor_dbg(us, "Status = %02X\n", *status);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (srb->cmnd[0] == TEST_UNIT_READY)
@@ -1610,7 +1611,7 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
if (result == USB_STOR_TRANSPORT_GOOD) {
transferred += len;
- US_DEBUGP("Wrote %08X bytes\n", transferred);
+ usb_stor_dbg(us, "Wrote %08X bytes\n", transferred);
}
return result;
@@ -1623,8 +1624,8 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
}
if (len > 0xFFFF) {
- US_DEBUGP("Error: len = %08X... what do I do now?\n",
- len);
+ usb_stor_dbg(us, "Error: len = %08X... what do I do now?\n",
+ len);
return USB_STOR_TRANSPORT_ERROR;
}
@@ -1693,7 +1694,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
};
if (srb->cmnd[0] == INQUIRY) {
- US_DEBUGP("usbat_flash_transport: INQUIRY. Returning bogus response.\n");
+ usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
memcpy(ptr, inquiry_response, sizeof(inquiry_response));
fill_inquiry_response(us, ptr, 36);
return USB_STOR_TRANSPORT_GOOD;
@@ -1710,8 +1711,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
/* hard coded 512 byte sectors as per ATA spec */
info->ssize = 0x200;
- US_DEBUGP("usbat_flash_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
- info->sectors, info->ssize);
+ usb_stor_dbg(us, "READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
+ info->sectors, info->ssize);
/*
* build the reply
@@ -1726,7 +1727,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
}
if (srb->cmnd[0] == MODE_SELECT_10) {
- US_DEBUGP("usbat_flash_transport: Gah! MODE_SELECT_10.\n");
+ usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -1736,7 +1737,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
- US_DEBUGP("usbat_flash_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "READ_10: read block 0x%04lx count %ld\n",
+ block, blocks);
return usbat_flash_read_data(us, info, block, blocks);
}
@@ -1750,7 +1752,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
- US_DEBUGP("usbat_flash_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "READ_12: read block 0x%04lx count %ld\n",
+ block, blocks);
return usbat_flash_read_data(us, info, block, blocks);
}
@@ -1760,7 +1763,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
- US_DEBUGP("usbat_flash_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "WRITE_10: write block 0x%04lx count %ld\n",
+ block, blocks);
return usbat_flash_write_data(us, info, block, blocks);
}
@@ -1774,13 +1778,14 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
- US_DEBUGP("usbat_flash_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "WRITE_12: write block 0x%04lx count %ld\n",
+ block, blocks);
return usbat_flash_write_data(us, info, block, blocks);
}
if (srb->cmnd[0] == TEST_UNIT_READY) {
- US_DEBUGP("usbat_flash_transport: TEST_UNIT_READY.\n");
+ usb_stor_dbg(us, "TEST_UNIT_READY\n");
rc = usbat_flash_check_media(us, info);
if (rc != USB_STOR_TRANSPORT_GOOD)
@@ -1790,7 +1795,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
}
if (srb->cmnd[0] == REQUEST_SENSE) {
- US_DEBUGP("usbat_flash_transport: REQUEST_SENSE.\n");
+ usb_stor_dbg(us, "REQUEST_SENSE\n");
memset(ptr, 0, 18);
ptr[0] = 0xF0;
@@ -1811,8 +1816,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
return USB_STOR_TRANSPORT_GOOD;
}
- US_DEBUGP("usbat_flash_transport: Gah! Unknown command: %d (0x%x)\n",
- srb->cmnd[0], srb->cmnd[0]);
+ usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
+ srb->cmnd[0], srb->cmnd[0]);
info->sense_key = 0x05;
info->sense_asc = 0x20;
info->sense_ascq = 0x00;
@@ -1846,7 +1851,7 @@ static int usbat_probe(struct usb_interface *intf,
us->transport_name = "Shuttle USBAT";
us->transport = usbat_flash_transport;
us->transport_reset = usb_stor_CB_reset;
- us->max_lun = 1;
+ us->max_lun = 0;
result = usb_stor_probe2(us);
return result;
@@ -1863,17 +1868,7 @@ static struct usb_driver usbat_driver = {
.post_reset = usb_stor_post_reset,
.id_table = usbat_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
-static int __init usbat_init(void)
-{
- return usb_register(&usbat_driver);
-}
-
-static void __exit usbat_exit(void)
-{
- usb_deregister(&usbat_driver);
-}
-
-module_init(usbat_init);
-module_exit(usbat_exit);
+module_usb_driver(usbat_driver);
diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c
index 57fc2f532ca..2ea657be14c 100644
--- a/drivers/usb/storage/sierra_ms.c
+++ b/drivers/usb/storage/sierra_ms.c
@@ -3,6 +3,7 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <linux/usb.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include "usb.h"
@@ -46,7 +47,7 @@ static bool containsFullLinuxPackage(struct swoc_info *swocInfo)
static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
{
int result;
- US_DEBUGP("SWIMS: %s", "DEVICE MODE SWITCH\n");
+ dev_dbg(&udev->dev, "SWIMS: %s", "DEVICE MODE SWITCH\n");
result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
SWIMS_USB_REQUEST_SetSwocMode, /* __u8 request */
USB_TYPE_VENDOR | USB_DIR_OUT, /* __u8 request type */
@@ -64,7 +65,7 @@ static int sierra_get_swoc_info(struct usb_device *udev,
{
int result;
- US_DEBUGP("SWIMS: Attempting to get TRU-Install info.\n");
+ dev_dbg(&udev->dev, "SWIMS: Attempting to get TRU-Install info\n");
result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
SWIMS_USB_REQUEST_GetSwocInfo, /* __u8 request */
@@ -80,11 +81,11 @@ static int sierra_get_swoc_info(struct usb_device *udev,
return result;
}
-static void debug_swoc(struct swoc_info *swocInfo)
+static void debug_swoc(const struct device *dev, struct swoc_info *swocInfo)
{
- US_DEBUGP("SWIMS: SWoC Rev: %02d \n", swocInfo->rev);
- US_DEBUGP("SWIMS: Linux SKU: %04X \n", swocInfo->LinuxSKU);
- US_DEBUGP("SWIMS: Linux Version: %04X \n", swocInfo->LinuxVer);
+ dev_dbg(dev, "SWIMS: SWoC Rev: %02d\n", swocInfo->rev);
+ dev_dbg(dev, "SWIMS: Linux SKU: %04X\n", swocInfo->LinuxSKU);
+ dev_dbg(dev, "SWIMS: Linux Version: %04X\n", swocInfo->LinuxVer);
}
@@ -100,18 +101,17 @@ static ssize_t show_truinst(struct device *dev, struct device_attribute *attr,
} else {
swocInfo = kmalloc(sizeof(struct swoc_info), GFP_KERNEL);
if (!swocInfo) {
- US_DEBUGP("SWIMS: Allocation failure\n");
snprintf(buf, PAGE_SIZE, "Error\n");
return -ENOMEM;
}
result = sierra_get_swoc_info(udev, swocInfo);
if (result < 0) {
- US_DEBUGP("SWIMS: failed SWoC query\n");
+ dev_dbg(dev, "SWIMS: failed SWoC query\n");
kfree(swocInfo);
snprintf(buf, PAGE_SIZE, "Error\n");
return -EIO;
}
- debug_swoc(swocInfo);
+ debug_swoc(dev, swocInfo);
result = snprintf(buf, PAGE_SIZE,
"REV=%02d SKU=%04X VER=%04X\n",
swocInfo->rev,
@@ -121,80 +121,71 @@ static ssize_t show_truinst(struct device *dev, struct device_attribute *attr,
}
return result;
}
-static DEVICE_ATTR(truinst, S_IWUGO | S_IRUGO, show_truinst, NULL);
+static DEVICE_ATTR(truinst, S_IRUGO, show_truinst, NULL);
int sierra_ms_init(struct us_data *us)
{
int result, retries;
- signed long delay_t;
struct swoc_info *swocInfo;
struct usb_device *udev;
struct Scsi_Host *sh;
- struct scsi_device *sd;
- delay_t = 2;
retries = 3;
result = 0;
udev = us->pusb_dev;
sh = us_to_host(us);
- sd = scsi_get_host_dev(sh);
-
- US_DEBUGP("SWIMS: sierra_ms_init called\n");
+ scsi_get_host_dev(sh);
/* Force Modem mode */
if (swi_tru_install == TRU_FORCE_MODEM) {
- US_DEBUGP("SWIMS: %s", "Forcing Modem Mode\n");
+ usb_stor_dbg(us, "SWIMS: Forcing Modem Mode\n");
result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem);
if (result < 0)
- US_DEBUGP("SWIMS: Failed to switch to modem mode.\n");
+ usb_stor_dbg(us, "SWIMS: Failed to switch to modem mode\n");
return -EIO;
}
/* Force Mass Storage mode (keep CD-Rom) */
else if (swi_tru_install == TRU_FORCE_MS) {
- US_DEBUGP("SWIMS: %s", "Forcing Mass Storage Mode\n");
+ usb_stor_dbg(us, "SWIMS: Forcing Mass Storage Mode\n");
goto complete;
}
/* Normal TRU-Install Logic */
else {
- US_DEBUGP("SWIMS: %s", "Normal SWoC Logic\n");
+ usb_stor_dbg(us, "SWIMS: Normal SWoC Logic\n");
swocInfo = kmalloc(sizeof(struct swoc_info),
GFP_KERNEL);
- if (!swocInfo) {
- US_DEBUGP("SWIMS: %s", "Allocation failure\n");
+ if (!swocInfo)
return -ENOMEM;
- }
retries = 3;
do {
retries--;
result = sierra_get_swoc_info(udev, swocInfo);
if (result < 0) {
- US_DEBUGP("SWIMS: %s", "Failed SWoC query\n");
+ usb_stor_dbg(us, "SWIMS: Failed SWoC query\n");
schedule_timeout_uninterruptible(2*HZ);
}
} while (retries && result < 0);
if (result < 0) {
- US_DEBUGP("SWIMS: %s",
- "Completely failed SWoC query\n");
+ usb_stor_dbg(us, "SWIMS: Completely failed SWoC query\n");
kfree(swocInfo);
return -EIO;
}
- debug_swoc(swocInfo);
+ debug_swoc(&us->pusb_dev->dev, swocInfo);
/* If there is not Linux software on the TRU-Install device
* then switch to modem mode
*/
if (!containsFullLinuxPackage(swocInfo)) {
- US_DEBUGP("SWIMS: %s",
- "Switching to Modem Mode\n");
+ usb_stor_dbg(us, "SWIMS: Switching to Modem Mode\n");
result = sierra_set_ms_mode(udev,
SWIMS_SET_MODE_Modem);
if (result < 0)
- US_DEBUGP("SWIMS: Failed to switch modem\n");
+ usb_stor_dbg(us, "SWIMS: Failed to switch modem\n");
kfree(swocInfo);
return -EIO;
}
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 00418995d8e..22c7d4360fa 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -46,6 +46,7 @@
#include <linux/sched.h>
#include <linux/gfp.h>
#include <linux/errno.h>
+#include <linux/export.h>
#include <linux/usb/quirks.h>
@@ -165,7 +166,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
/* cancel the URB, if it hasn't been cancelled already */
if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
- US_DEBUGP("-- cancelling URB\n");
+ usb_stor_dbg(us, "-- cancelling URB\n");
usb_unlink_urb(us->current_urb);
}
}
@@ -177,8 +178,8 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
if (timeleft <= 0) {
- US_DEBUGP("%s -- cancelling URB\n",
- timeleft == 0 ? "Timeout" : "Signal");
+ usb_stor_dbg(us, "%s -- cancelling URB\n",
+ timeleft == 0 ? "Timeout" : "Signal");
usb_kill_urb(us->current_urb);
}
@@ -196,9 +197,8 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
{
int status;
- US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
- __func__, request, requesttype,
- value, index, size);
+ usb_stor_dbg(us, "rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
+ request, requesttype, value, index, size);
/* fill in the devrequest structure */
us->cr->bRequestType = requesttype;
@@ -248,7 +248,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
if (result >= 0)
usb_reset_endpoint(us->pusb_dev, endp);
- US_DEBUGP("%s: result = %d\n", __func__, result);
+ usb_stor_dbg(us, "result = %d\n", result);
return result;
}
EXPORT_SYMBOL_GPL(usb_stor_clear_halt);
@@ -264,18 +264,18 @@ EXPORT_SYMBOL_GPL(usb_stor_clear_halt);
static int interpret_urb_result(struct us_data *us, unsigned int pipe,
unsigned int length, int result, unsigned int partial)
{
- US_DEBUGP("Status code %d; transferred %u/%u\n",
- result, partial, length);
+ usb_stor_dbg(us, "Status code %d; transferred %u/%u\n",
+ result, partial, length);
switch (result) {
/* no error code; did we send all the data? */
case 0:
if (partial != length) {
- US_DEBUGP("-- short transfer\n");
+ usb_stor_dbg(us, "-- short transfer\n");
return USB_STOR_XFER_SHORT;
}
- US_DEBUGP("-- transfer complete\n");
+ usb_stor_dbg(us, "-- transfer complete\n");
return USB_STOR_XFER_GOOD;
/* stalled */
@@ -283,39 +283,40 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,
/* for control endpoints, (used by CB[I]) a stall indicates
* a failed command */
if (usb_pipecontrol(pipe)) {
- US_DEBUGP("-- stall on control pipe\n");
+ usb_stor_dbg(us, "-- stall on control pipe\n");
return USB_STOR_XFER_STALLED;
}
/* for other sorts of endpoint, clear the stall */
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
+ usb_stor_dbg(us, "clearing endpoint halt for pipe 0x%x\n",
+ pipe);
if (usb_stor_clear_halt(us, pipe) < 0)
return USB_STOR_XFER_ERROR;
return USB_STOR_XFER_STALLED;
/* babble - the device tried to send more than we wanted to read */
case -EOVERFLOW:
- US_DEBUGP("-- babble\n");
+ usb_stor_dbg(us, "-- babble\n");
return USB_STOR_XFER_LONG;
/* the transfer was cancelled by abort, disconnect, or timeout */
case -ECONNRESET:
- US_DEBUGP("-- transfer cancelled\n");
+ usb_stor_dbg(us, "-- transfer cancelled\n");
return USB_STOR_XFER_ERROR;
/* short scatter-gather read transfer */
case -EREMOTEIO:
- US_DEBUGP("-- short read transfer\n");
+ usb_stor_dbg(us, "-- short read transfer\n");
return USB_STOR_XFER_SHORT;
/* abort or disconnect in progress */
case -EIO:
- US_DEBUGP("-- abort or disconnect in progress\n");
+ usb_stor_dbg(us, "-- abort or disconnect in progress\n");
return USB_STOR_XFER_ERROR;
/* the catch-all error case */
default:
- US_DEBUGP("-- unknown error\n");
+ usb_stor_dbg(us, "-- unknown error\n");
return USB_STOR_XFER_ERROR;
}
}
@@ -330,9 +331,8 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
{
int result;
- US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
- __func__, request, requesttype,
- value, index, size);
+ usb_stor_dbg(us, "rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
+ request, requesttype, value, index, size);
/* fill in the devrequest structure */
us->cr->bRequestType = requesttype;
@@ -366,7 +366,7 @@ static int usb_stor_intr_transfer(struct us_data *us, void *buf,
unsigned int pipe = us->recv_intr_pipe;
unsigned int maxp;
- US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
+ usb_stor_dbg(us, "xfer %u bytes\n", length);
/* calculate the max packet size */
maxp = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe));
@@ -393,7 +393,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
{
int result;
- US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
+ usb_stor_dbg(us, "xfer %u bytes\n", length);
/* fill and submit the URB */
usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length,
@@ -425,12 +425,11 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
return USB_STOR_XFER_ERROR;
/* initialize the scatter-gather request block */
- US_DEBUGP("%s: xfer %u bytes, %d entries\n", __func__,
- length, num_sg);
+ usb_stor_dbg(us, "xfer %u bytes, %d entries\n", length, num_sg);
result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
sg, num_sg, length, GFP_NOIO);
if (result) {
- US_DEBUGP("usb_sg_init returned %d\n", result);
+ usb_stor_dbg(us, "usb_sg_init returned %d\n", result);
return USB_STOR_XFER_ERROR;
}
@@ -443,7 +442,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
/* cancel the request, if it hasn't been cancelled already */
if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
- US_DEBUGP("-- cancelling sg request\n");
+ usb_stor_dbg(us, "-- cancelling sg request\n");
usb_sg_cancel(&us->current_sg);
}
}
@@ -608,14 +607,14 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
* short-circuit all other processing
*/
if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
- US_DEBUGP("-- command was aborted\n");
+ usb_stor_dbg(us, "-- command was aborted\n");
srb->result = DID_ABORT << 16;
goto Handle_Errors;
}
/* if there is a transport error, reset and don't auto-sense */
if (result == USB_STOR_TRANSPORT_ERROR) {
- US_DEBUGP("-- transport indicates error, resetting\n");
+ usb_stor_dbg(us, "-- transport indicates error, resetting\n");
srb->result = DID_ERROR << 16;
goto Handle_Errors;
}
@@ -644,7 +643,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
*/
if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_DPCM_USB) &&
srb->sc_data_direction != DMA_FROM_DEVICE) {
- US_DEBUGP("-- CB transport device requiring auto-sense\n");
+ usb_stor_dbg(us, "-- CB transport device requiring auto-sense\n");
need_auto_sense = 1;
}
@@ -654,7 +653,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
* "failure" and an "error" in the transport mechanism.
*/
if (result == USB_STOR_TRANSPORT_FAILED) {
- US_DEBUGP("-- transport indicates command failure\n");
+ usb_stor_dbg(us, "-- transport indicates command failure\n");
need_auto_sense = 1;
}
@@ -669,7 +668,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
!(us->fflags & US_FL_SANE_SENSE) &&
!(us->fflags & US_FL_BAD_SENSE) &&
!(srb->cmnd[2] & 0x20))) {
- US_DEBUGP("-- SAT supported, increasing auto-sense\n");
+ usb_stor_dbg(us, "-- SAT supported, increasing auto-sense\n");
us->fflags |= US_FL_SANE_SENSE;
}
@@ -683,7 +682,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
(srb->cmnd[0] == MODE_SENSE) ||
(srb->cmnd[0] == LOG_SENSE) ||
(srb->cmnd[0] == MODE_SENSE_10))) {
- US_DEBUGP("-- unexpectedly short transfer\n");
+ usb_stor_dbg(us, "-- unexpectedly short transfer\n");
}
/* Now, if we need to do the auto-sense, let's do it */
@@ -691,12 +690,15 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
int temp_result;
struct scsi_eh_save ses;
int sense_size = US_SENSE_SIZE;
+ struct scsi_sense_hdr sshdr;
+ const u8 *scdd;
+ u8 fm_ili;
/* device supports and needs bigger sense buffer */
if (us->fflags & US_FL_SANE_SENSE)
sense_size = ~0;
Retry_Sense:
- US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
+ usb_stor_dbg(us, "Issuing auto-REQUEST_SENSE\n");
scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size);
@@ -715,7 +717,7 @@ Retry_Sense:
scsi_eh_restore_cmnd(srb, &ses);
if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
- US_DEBUGP("-- auto-sense aborted\n");
+ usb_stor_dbg(us, "-- auto-sense aborted\n");
srb->result = DID_ABORT << 16;
/* If SANE_SENSE caused this problem, disable it */
@@ -733,7 +735,7 @@ Retry_Sense:
*/
if (temp_result == USB_STOR_TRANSPORT_FAILED &&
sense_size != US_SENSE_SIZE) {
- US_DEBUGP("-- auto-sense failure, retry small sense\n");
+ usb_stor_dbg(us, "-- auto-sense failure, retry small sense\n");
sense_size = US_SENSE_SIZE;
us->fflags &= ~US_FL_SANE_SENSE;
us->fflags |= US_FL_BAD_SENSE;
@@ -742,7 +744,7 @@ Retry_Sense:
/* Other failures */
if (temp_result != USB_STOR_TRANSPORT_GOOD) {
- US_DEBUGP("-- auto-sense failure\n");
+ usb_stor_dbg(us, "-- auto-sense failure\n");
/* we skip the reset if this happens to be a
* multi-target device, since failure of an
@@ -762,44 +764,43 @@ Retry_Sense:
!(us->fflags & US_FL_SANE_SENSE) &&
!(us->fflags & US_FL_BAD_SENSE) &&
(srb->sense_buffer[0] & 0x7C) == 0x70) {
- US_DEBUGP("-- SANE_SENSE support enabled\n");
+ usb_stor_dbg(us, "-- SANE_SENSE support enabled\n");
us->fflags |= US_FL_SANE_SENSE;
/* Indicate to the user that we truncated their sense
* because we didn't know it supported larger sense.
*/
- US_DEBUGP("-- Sense data truncated to %i from %i\n",
- US_SENSE_SIZE,
- srb->sense_buffer[7] + 8);
+ usb_stor_dbg(us, "-- Sense data truncated to %i from %i\n",
+ US_SENSE_SIZE,
+ srb->sense_buffer[7] + 8);
srb->sense_buffer[7] = (US_SENSE_SIZE - 8);
}
- US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);
- US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
- srb->sense_buffer[0],
- srb->sense_buffer[2] & 0xf,
- srb->sense_buffer[12],
- srb->sense_buffer[13]);
+ scsi_normalize_sense(srb->sense_buffer, SCSI_SENSE_BUFFERSIZE,
+ &sshdr);
+
+ usb_stor_dbg(us, "-- Result from auto-sense is %d\n",
+ temp_result);
+ usb_stor_dbg(us, "-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
+ sshdr.response_code, sshdr.sense_key,
+ sshdr.asc, sshdr.ascq);
#ifdef CONFIG_USB_STORAGE_DEBUG
- usb_stor_show_sense(
- srb->sense_buffer[2] & 0xf,
- srb->sense_buffer[12],
- srb->sense_buffer[13]);
+ usb_stor_show_sense(us, sshdr.sense_key, sshdr.asc, sshdr.ascq);
#endif
/* set the result so the higher layers expect this data */
srb->result = SAM_STAT_CHECK_CONDITION;
+ scdd = scsi_sense_desc_find(srb->sense_buffer,
+ SCSI_SENSE_BUFFERSIZE, 4);
+ fm_ili = (scdd ? scdd[3] : srb->sense_buffer[2]) & 0xA0;
+
/* We often get empty sense data. This could indicate that
* everything worked or that there was an unspecified
* problem. We have to decide which.
*/
- if ( /* Filemark 0, ignore EOM, ILI 0, no sense */
- (srb->sense_buffer[2] & 0xaf) == 0 &&
- /* No ASC or ASCQ */
- srb->sense_buffer[12] == 0 &&
- srb->sense_buffer[13] == 0) {
-
+ if (sshdr.sense_key == 0 && sshdr.asc == 0 && sshdr.ascq == 0 &&
+ fm_ili == 0) {
/* If things are really okay, then let's show that.
* Zero out the sense buffer so the higher layers
* won't realize we did an unsolicited auto-sense.
@@ -814,11 +815,43 @@ Retry_Sense:
*/
} else {
srb->result = DID_ERROR << 16;
- srb->sense_buffer[2] = HARDWARE_ERROR;
+ if ((sshdr.response_code & 0x72) == 0x72)
+ srb->sense_buffer[1] = HARDWARE_ERROR;
+ else
+ srb->sense_buffer[2] = HARDWARE_ERROR;
}
}
}
+ /*
+ * Some devices don't work or return incorrect data the first
+ * time they get a READ(10) command, or for the first READ(10)
+ * after a media change. If the INITIAL_READ10 flag is set,
+ * keep track of whether READ(10) commands succeed. If the
+ * previous one succeeded and this one failed, set the REDO_READ10
+ * flag to force a retry.
+ */
+ if (unlikely((us->fflags & US_FL_INITIAL_READ10) &&
+ srb->cmnd[0] == READ_10)) {
+ if (srb->result == SAM_STAT_GOOD) {
+ set_bit(US_FLIDX_READ10_WORKED, &us->dflags);
+ } else if (test_bit(US_FLIDX_READ10_WORKED, &us->dflags)) {
+ clear_bit(US_FLIDX_READ10_WORKED, &us->dflags);
+ set_bit(US_FLIDX_REDO_READ10, &us->dflags);
+ }
+
+ /*
+ * Next, if the REDO_READ10 flag is set, return a result
+ * code that will cause the SCSI core to retry the READ(10)
+ * command immediately.
+ */
+ if (test_bit(US_FLIDX_REDO_READ10, &us->dflags)) {
+ clear_bit(US_FLIDX_REDO_READ10, &us->dflags);
+ srb->result = DID_IMM_RETRY << 16;
+ srb->sense_buffer[0] = 0;
+ }
+ }
+
/* Did we transfer less than the minimum amount required? */
if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) &&
scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
@@ -858,20 +891,18 @@ Retry_Sense:
/* Stop the current URB transfer */
void usb_stor_stop_transport(struct us_data *us)
{
- US_DEBUGP("%s called\n", __func__);
-
/* If the state machine is blocked waiting for an URB,
* let's wake it up. The test_and_clear_bit() call
* guarantees that if a URB has just been submitted,
* it won't be cancelled more than once. */
if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
- US_DEBUGP("-- cancelling URB\n");
+ usb_stor_dbg(us, "-- cancelling URB\n");
usb_unlink_urb(us->current_urb);
}
/* If we are waiting for a scatter-gather operation, cancel it. */
if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
- US_DEBUGP("-- cancelling sg request\n");
+ usb_stor_dbg(us, "-- cancelling sg request\n");
usb_sg_cancel(&us->current_sg);
}
}
@@ -894,7 +925,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
us->ifnum, srb->cmnd, srb->cmd_len);
/* check the return code for the command */
- US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);
+ usb_stor_dbg(us, "Call to usb_stor_ctrl_transfer() returned %d\n",
+ result);
/* if we stalled the command, it means command failed */
if (result == USB_STOR_XFER_STALLED) {
@@ -912,7 +944,7 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
pipe = srb->sc_data_direction == DMA_FROM_DEVICE ?
us->recv_bulk_pipe : us->send_bulk_pipe;
result = usb_stor_bulk_srb(us, pipe, srb);
- US_DEBUGP("CBI data stage result is 0x%x\n", result);
+ usb_stor_dbg(us, "CBI data stage result is 0x%x\n", result);
/* if we stalled the data transfer it means command failed */
if (result == USB_STOR_XFER_STALLED)
@@ -930,8 +962,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
return USB_STOR_TRANSPORT_GOOD;
result = usb_stor_intr_transfer(us, us->iobuf, 2);
- US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n",
- us->iobuf[0], us->iobuf[1]);
+ usb_stor_dbg(us, "Got interrupt data (0x%x, 0x%x)\n",
+ us->iobuf[0], us->iobuf[1]);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -958,8 +990,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
* into the first byte -- so if it's non-zero, call it a failure.
*/
if (us->iobuf[0]) {
- US_DEBUGP("CBI IRQ data showed reserved bType 0x%x\n",
- us->iobuf[0]);
+ usb_stor_dbg(us, "CBI IRQ data showed reserved bType 0x%x\n",
+ us->iobuf[0]);
goto Failed;
}
@@ -1000,8 +1032,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
USB_RECIP_INTERFACE,
0, us->ifnum, us->iobuf, 1, 10*HZ);
- US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
- result, us->iobuf[0]);
+ usb_stor_dbg(us, "GetMaxLUN command result is %d, data is %d\n",
+ result, us->iobuf[0]);
/* if we have a successful request, return the result */
if (result > 0)
@@ -1037,7 +1069,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
/* set up the command wrapper */
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(transfer_length);
- bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
+ bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ?
+ US_BULK_FLAG_IN : 0;
bcb->Tag = ++us->tag;
bcb->Lun = srb->device->lun;
if (us->fflags & US_FL_SCM_MULT_TARG)
@@ -1049,14 +1082,14 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
memcpy(bcb->CDB, srb->cmnd, bcb->Length);
/* send it to out endpoint */
- US_DEBUGP("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
- le32_to_cpu(bcb->Signature), bcb->Tag,
- le32_to_cpu(bcb->DataTransferLength), bcb->Flags,
- (bcb->Lun >> 4), (bcb->Lun & 0x0F),
- bcb->Length);
+ usb_stor_dbg(us, "Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
+ le32_to_cpu(bcb->Signature), bcb->Tag,
+ le32_to_cpu(bcb->DataTransferLength), bcb->Flags,
+ (bcb->Lun >> 4), (bcb->Lun & 0x0F),
+ bcb->Length);
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
bcb, cbwlen, NULL);
- US_DEBUGP("Bulk command transfer result=%d\n", result);
+ usb_stor_dbg(us, "Bulk command transfer result=%d\n", result);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -1073,7 +1106,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ?
us->recv_bulk_pipe : us->send_bulk_pipe;
result = usb_stor_bulk_srb(us, pipe, srb);
- US_DEBUGP("Bulk data transfer result 0x%x\n", result);
+ usb_stor_dbg(us, "Bulk data transfer result 0x%x\n", result);
if (result == USB_STOR_XFER_ERROR)
return USB_STOR_TRANSPORT_ERROR;
@@ -1092,7 +1125,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
*/
/* get CSW for device status */
- US_DEBUGP("Attempting to get CSW...\n");
+ usb_stor_dbg(us, "Attempting to get CSW...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
bcs, US_BULK_CS_WRAP_LEN, &cswlen);
@@ -1101,7 +1134,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
* CSWs. If we encounter such a thing, try to read the CSW again.
*/
if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
- US_DEBUGP("Received 0-length CSW; retrying...\n");
+ usb_stor_dbg(us, "Received 0-length CSW; retrying...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
bcs, US_BULK_CS_WRAP_LEN, &cswlen);
}
@@ -1110,24 +1143,24 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
if (result == USB_STOR_XFER_STALLED) {
/* get the status again */
- US_DEBUGP("Attempting to get CSW (2nd try)...\n");
+ usb_stor_dbg(us, "Attempting to get CSW (2nd try)...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
bcs, US_BULK_CS_WRAP_LEN, NULL);
}
/* if we still have a failure at this point, we're in trouble */
- US_DEBUGP("Bulk status result = %d\n", result);
+ usb_stor_dbg(us, "Bulk status result = %d\n", result);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
/* check bulk status */
residue = le32_to_cpu(bcs->Residue);
- US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
- le32_to_cpu(bcs->Signature), bcs->Tag,
- residue, bcs->Status);
+ usb_stor_dbg(us, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
+ le32_to_cpu(bcs->Signature), bcs->Tag,
+ residue, bcs->Status);
if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) ||
bcs->Status > US_BULK_STAT_PHASE) {
- US_DEBUGP("Bulk logical error\n");
+ usb_stor_dbg(us, "Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -1138,12 +1171,12 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
if (!us->bcs_signature) {
us->bcs_signature = bcs->Signature;
if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN))
- US_DEBUGP("Learnt BCS signature 0x%08X\n",
- le32_to_cpu(us->bcs_signature));
+ usb_stor_dbg(us, "Learnt BCS signature 0x%08X\n",
+ le32_to_cpu(us->bcs_signature));
} else if (bcs->Signature != us->bcs_signature) {
- US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n",
- le32_to_cpu(bcs->Signature),
- le32_to_cpu(us->bcs_signature));
+ usb_stor_dbg(us, "Signature mismatch: got %08X, expecting %08X\n",
+ le32_to_cpu(bcs->Signature),
+ le32_to_cpu(us->bcs_signature));
return USB_STOR_TRANSPORT_ERROR;
}
@@ -1220,7 +1253,7 @@ static int usb_stor_reset_common(struct us_data *us,
int result2;
if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
- US_DEBUGP("No reset during disconnect\n");
+ usb_stor_dbg(us, "No reset during disconnect\n");
return -EIO;
}
@@ -1228,7 +1261,7 @@ static int usb_stor_reset_common(struct us_data *us,
request, requesttype, value, index, data, size,
5*HZ);
if (result < 0) {
- US_DEBUGP("Soft reset failed: %d\n", result);
+ usb_stor_dbg(us, "Soft reset failed: %d\n", result);
return result;
}
@@ -1238,23 +1271,23 @@ static int usb_stor_reset_common(struct us_data *us,
test_bit(US_FLIDX_DISCONNECTING, &us->dflags),
HZ*6);
if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
- US_DEBUGP("Reset interrupted by disconnect\n");
+ usb_stor_dbg(us, "Reset interrupted by disconnect\n");
return -EIO;
}
- US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
+ usb_stor_dbg(us, "Soft reset: clearing bulk-in endpoint halt\n");
result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
- US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n");
+ usb_stor_dbg(us, "Soft reset: clearing bulk-out endpoint halt\n");
result2 = usb_stor_clear_halt(us, us->send_bulk_pipe);
/* return a result code based on the result of the clear-halts */
if (result >= 0)
result = result2;
if (result < 0)
- US_DEBUGP("Soft reset failed\n");
+ usb_stor_dbg(us, "Soft reset failed\n");
else
- US_DEBUGP("Soft reset done\n");
+ usb_stor_dbg(us, "Soft reset done\n");
return result;
}
@@ -1264,8 +1297,6 @@ static int usb_stor_reset_common(struct us_data *us,
int usb_stor_CB_reset(struct us_data *us)
{
- US_DEBUGP("%s called\n", __func__);
-
memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);
us->iobuf[0] = SEND_DIAGNOSTIC;
us->iobuf[1] = 4;
@@ -1280,8 +1311,6 @@ EXPORT_SYMBOL_GPL(usb_stor_CB_reset);
*/
int usb_stor_Bulk_reset(struct us_data *us)
{
- US_DEBUGP("%s called\n", __func__);
-
return usb_stor_reset_common(us, US_BULK_RESET_REQUEST,
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum, NULL, 0);
@@ -1296,21 +1325,22 @@ int usb_stor_port_reset(struct us_data *us)
int result;
/*for these devices we must use the class specific method */
- if (us->pusb_dev->quirks & USB_QUIRK_RESET_MORPHS)
+ if (us->pusb_dev->quirks & USB_QUIRK_RESET)
return -EPERM;
result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
if (result < 0)
- US_DEBUGP("unable to lock device for reset: %d\n", result);
+ usb_stor_dbg(us, "unable to lock device for reset: %d\n",
+ result);
else {
/* Were we disconnected while waiting for the lock? */
if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
result = -EIO;
- US_DEBUGP("No reset during disconnect\n");
+ usb_stor_dbg(us, "No reset during disconnect\n");
} else {
result = usb_reset_device(us->pusb_dev);
- US_DEBUGP("usb_reset_device returns %d\n",
- result);
+ usb_stor_dbg(us, "usb_reset_device returns %d\n",
+ result);
}
usb_unlock_device(us->pusb_dev);
}
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 242ff5e791a..9369d752d41 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -42,45 +42,6 @@
#include <linux/blkdev.h>
/*
- * Bulk only data structures
- */
-
-/* command block wrapper */
-struct bulk_cb_wrap {
- __le32 Signature; /* contains 'USBC' */
- __u32 Tag; /* unique per command id */
- __le32 DataTransferLength; /* size of data */
- __u8 Flags; /* direction in bit 0 */
- __u8 Lun; /* LUN normally 0 */
- __u8 Length; /* of of the CDB */
- __u8 CDB[16]; /* max command */
-};
-
-#define US_BULK_CB_WRAP_LEN 31
-#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */
-#define US_BULK_FLAG_IN 1
-#define US_BULK_FLAG_OUT 0
-
-/* command status wrapper */
-struct bulk_cs_wrap {
- __le32 Signature; /* should = 'USBS' */
- __u32 Tag; /* same as original command */
- __le32 Residue; /* amount not transferred */
- __u8 Status; /* see below */
- __u8 Filler[18];
-};
-
-#define US_BULK_CS_WRAP_LEN 13
-#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */
-#define US_BULK_STAT_OK 0
-#define US_BULK_STAT_FAIL 1
-#define US_BULK_STAT_PHASE 2
-
-/* bulk-only class specific requests */
-#define US_BULK_RESET_REQUEST 0xff
-#define US_BULK_GET_MAX_LUN 0xfe
-
-/*
* usb_stor_bulk_transfer_xxx() return codes, in order of severity
*/
diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h
new file mode 100644
index 00000000000..bb05b984d5f
--- /dev/null
+++ b/drivers/usb/storage/uas-detect.h
@@ -0,0 +1,96 @@
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include "usb.h"
+
+static int uas_is_interface(struct usb_host_interface *intf)
+{
+ return (intf->desc.bInterfaceClass == USB_CLASS_MASS_STORAGE &&
+ intf->desc.bInterfaceSubClass == USB_SC_SCSI &&
+ intf->desc.bInterfaceProtocol == USB_PR_UAS);
+}
+
+static int uas_isnt_supported(struct usb_device *udev)
+{
+ struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+ dev_warn(&udev->dev, "The driver for the USB controller %s does not "
+ "support scatter-gather which is\n",
+ hcd->driver->description);
+ dev_warn(&udev->dev, "required by the UAS driver. Please try an"
+ "alternative USB controller if you wish to use UAS.\n");
+ return -ENODEV;
+}
+
+static int uas_find_uas_alt_setting(struct usb_interface *intf)
+{
+ int i;
+ struct usb_device *udev = interface_to_usbdev(intf);
+ int sg_supported = udev->bus->sg_tablesize != 0;
+
+ for (i = 0; i < intf->num_altsetting; i++) {
+ struct usb_host_interface *alt = &intf->altsetting[i];
+
+ if (uas_is_interface(alt)) {
+ if (!sg_supported)
+ return uas_isnt_supported(udev);
+ return alt->desc.bAlternateSetting;
+ }
+ }
+
+ return -ENODEV;
+}
+
+static int uas_find_endpoints(struct usb_host_interface *alt,
+ struct usb_host_endpoint *eps[])
+{
+ struct usb_host_endpoint *endpoint = alt->endpoint;
+ unsigned i, n_endpoints = alt->desc.bNumEndpoints;
+
+ for (i = 0; i < n_endpoints; i++) {
+ unsigned char *extra = endpoint[i].extra;
+ int len = endpoint[i].extralen;
+ while (len >= 3) {
+ if (extra[1] == USB_DT_PIPE_USAGE) {
+ unsigned pipe_id = extra[2];
+ if (pipe_id > 0 && pipe_id < 5)
+ eps[pipe_id - 1] = &endpoint[i];
+ break;
+ }
+ len -= extra[0];
+ extra += extra[0];
+ }
+ }
+
+ if (!eps[0] || !eps[1] || !eps[2] || !eps[3])
+ return -ENODEV;
+
+ return 0;
+}
+
+static int uas_use_uas_driver(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_host_endpoint *eps[4] = { };
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+ unsigned long flags = id->driver_info;
+ int r, alt;
+
+ usb_stor_adjust_quirks(udev, &flags);
+
+ if (flags & US_FL_IGNORE_UAS)
+ return 0;
+
+ if (udev->speed >= USB_SPEED_SUPER && !hcd->can_do_streams)
+ return 0;
+
+ alt = uas_find_uas_alt_setting(intf);
+ if (alt < 0)
+ return 0;
+
+ r = uas_find_endpoints(&intf->altsetting[alt], eps);
+ if (r < 0)
+ return 0;
+
+ return 1;
+}
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index d1268191acb..511b2295316 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -2,6 +2,7 @@
* USB Attached SCSI
* Note that this is not the same as the USB Mass Storage driver
*
+ * Copyright Hans de Goede <hdegoede@redhat.com> for Red Hat, Inc. 2013
* Copyright Matthew Wilcox for Intel Corp, 2010
* Copyright Sarah Sharp for Intel Corp, 2010
*
@@ -11,55 +12,22 @@
#include <linux/blkdev.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/module.h>
#include <linux/usb.h>
+#include <linux/usb_usual.h>
+#include <linux/usb/hcd.h>
#include <linux/usb/storage.h>
+#include <linux/usb/uas.h>
#include <scsi/scsi.h>
+#include <scsi/scsi_eh.h>
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
-/* Common header for all IUs */
-struct iu {
- __u8 iu_id;
- __u8 rsvd1;
- __be16 tag;
-};
-
-enum {
- IU_ID_COMMAND = 0x01,
- IU_ID_STATUS = 0x03,
- IU_ID_RESPONSE = 0x04,
- IU_ID_TASK_MGMT = 0x05,
- IU_ID_READ_READY = 0x06,
- IU_ID_WRITE_READY = 0x07,
-};
-
-struct command_iu {
- __u8 iu_id;
- __u8 rsvd1;
- __be16 tag;
- __u8 prio_attr;
- __u8 rsvd5;
- __u8 len;
- __u8 rsvd7;
- struct scsi_lun lun;
- __u8 cdb[16]; /* XXX: Overflow-checking tools may misunderstand */
-};
-
-struct sense_iu {
- __u8 iu_id;
- __u8 rsvd1;
- __be16 tag;
- __be16 status_qual;
- __u8 status;
- __u8 service_response;
- __u8 rsvd8[6];
- __be16 len;
- __u8 sense[SCSI_SENSE_BUFFERSIZE];
-};
+#include "uas-detect.h"
/*
* The r00-r01c specs define this version of the SENSE IU data structure.
@@ -75,36 +43,41 @@ struct sense_iu_old {
__u8 sense[SCSI_SENSE_BUFFERSIZE];
};
-enum {
- CMD_PIPE_ID = 1,
- STATUS_PIPE_ID = 2,
- DATA_IN_PIPE_ID = 3,
- DATA_OUT_PIPE_ID = 4,
-
- UAS_SIMPLE_TAG = 0,
- UAS_HEAD_TAG = 1,
- UAS_ORDERED_TAG = 2,
- UAS_ACA = 4,
-};
-
struct uas_dev_info {
struct usb_interface *intf;
struct usb_device *udev;
- int qdepth;
+ struct usb_anchor cmd_urbs;
+ struct usb_anchor sense_urbs;
+ struct usb_anchor data_urbs;
+ int qdepth, resetting;
+ struct response_iu response;
unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
unsigned use_streams:1;
unsigned uas_sense_old:1;
+ unsigned running_task:1;
+ unsigned shutdown:1;
+ struct scsi_cmnd *cmnd;
+ spinlock_t lock;
+ struct work_struct work;
+ struct list_head inflight_list;
+ struct list_head dead_list;
};
enum {
- ALLOC_SENSE_URB = (1 << 0),
- SUBMIT_SENSE_URB = (1 << 1),
+ SUBMIT_STATUS_URB = (1 << 1),
ALLOC_DATA_IN_URB = (1 << 2),
SUBMIT_DATA_IN_URB = (1 << 3),
ALLOC_DATA_OUT_URB = (1 << 4),
SUBMIT_DATA_OUT_URB = (1 << 5),
ALLOC_CMD_URB = (1 << 6),
SUBMIT_CMD_URB = (1 << 7),
+ COMMAND_INFLIGHT = (1 << 8),
+ DATA_IN_URB_INFLIGHT = (1 << 9),
+ DATA_OUT_URB_INFLIGHT = (1 << 10),
+ COMMAND_COMPLETED = (1 << 11),
+ COMMAND_ABORTED = (1 << 12),
+ UNLINK_DATA_URBS = (1 << 13),
+ IS_IN_WORK_LIST = (1 << 14),
};
/* Overrides scsi_pointer */
@@ -112,7 +85,6 @@ struct uas_cmd_info {
unsigned int state;
unsigned int stream;
struct urb *cmd_urb;
- struct urb *sense_urb;
struct urb *data_in_urb;
struct urb *data_out_urb;
struct list_head list;
@@ -121,28 +93,121 @@ struct uas_cmd_info {
/* I hate forward declarations, but I actually have a loop */
static int uas_submit_urbs(struct scsi_cmnd *cmnd,
struct uas_dev_info *devinfo, gfp_t gfp);
+static void uas_do_work(struct work_struct *work);
+static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller);
+static void uas_free_streams(struct uas_dev_info *devinfo);
+static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller);
+
+/* Must be called with devinfo->lock held, will temporary unlock the lock */
+static void uas_unlink_data_urbs(struct uas_dev_info *devinfo,
+ struct uas_cmd_info *cmdinfo,
+ unsigned long *lock_flags)
+{
+ /*
+ * The UNLINK_DATA_URBS flag makes sure uas_try_complete
+ * (called by urb completion) doesn't release cmdinfo
+ * underneath us.
+ */
+ cmdinfo->state |= UNLINK_DATA_URBS;
+ spin_unlock_irqrestore(&devinfo->lock, *lock_flags);
-static DEFINE_SPINLOCK(uas_work_lock);
-static LIST_HEAD(uas_work_list);
+ if (cmdinfo->data_in_urb)
+ usb_unlink_urb(cmdinfo->data_in_urb);
+ if (cmdinfo->data_out_urb)
+ usb_unlink_urb(cmdinfo->data_out_urb);
+
+ spin_lock_irqsave(&devinfo->lock, *lock_flags);
+ cmdinfo->state &= ~UNLINK_DATA_URBS;
+}
static void uas_do_work(struct work_struct *work)
{
+ struct uas_dev_info *devinfo =
+ container_of(work, struct uas_dev_info, work);
struct uas_cmd_info *cmdinfo;
- struct list_head list;
-
- spin_lock_irq(&uas_work_lock);
- list_replace_init(&uas_work_list, &list);
- spin_unlock_irq(&uas_work_lock);
+ unsigned long flags;
+ int err;
- list_for_each_entry(cmdinfo, &list, list) {
+ spin_lock_irqsave(&devinfo->lock, flags);
+ list_for_each_entry(cmdinfo, &devinfo->inflight_list, list) {
struct scsi_pointer *scp = (void *)cmdinfo;
- struct scsi_cmnd *cmnd = container_of(scp,
- struct scsi_cmnd, SCp);
- uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_KERNEL);
+ struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
+ SCp);
+
+ if (!(cmdinfo->state & IS_IN_WORK_LIST))
+ continue;
+
+ err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
+ if (!err)
+ cmdinfo->state &= ~IS_IN_WORK_LIST;
+ else
+ schedule_work(&devinfo->work);
}
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+}
+
+static void uas_mark_cmd_dead(struct uas_dev_info *devinfo,
+ struct uas_cmd_info *cmdinfo,
+ int result, const char *caller)
+{
+ struct scsi_pointer *scp = (void *)cmdinfo;
+ struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
+
+ uas_log_cmd_state(cmnd, caller);
+ WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
+ WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
+ cmdinfo->state |= COMMAND_ABORTED;
+ cmdinfo->state &= ~IS_IN_WORK_LIST;
+ cmnd->result = result << 16;
+ list_move_tail(&cmdinfo->list, &devinfo->dead_list);
}
-static DECLARE_WORK(uas_work, uas_do_work);
+static void uas_abort_inflight(struct uas_dev_info *devinfo, int result,
+ const char *caller)
+{
+ struct uas_cmd_info *cmdinfo;
+ struct uas_cmd_info *temp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&devinfo->lock, flags);
+ list_for_each_entry_safe(cmdinfo, temp, &devinfo->inflight_list, list)
+ uas_mark_cmd_dead(devinfo, cmdinfo, result, caller);
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+}
+
+static void uas_add_work(struct uas_cmd_info *cmdinfo)
+{
+ struct scsi_pointer *scp = (void *)cmdinfo;
+ struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
+ struct uas_dev_info *devinfo = cmnd->device->hostdata;
+
+ WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
+ cmdinfo->state |= IS_IN_WORK_LIST;
+ schedule_work(&devinfo->work);
+}
+
+static void uas_zap_dead(struct uas_dev_info *devinfo)
+{
+ struct uas_cmd_info *cmdinfo;
+ struct uas_cmd_info *temp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&devinfo->lock, flags);
+ list_for_each_entry_safe(cmdinfo, temp, &devinfo->dead_list, list) {
+ struct scsi_pointer *scp = (void *)cmdinfo;
+ struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
+ SCp);
+ uas_log_cmd_state(cmnd, __func__);
+ WARN_ON_ONCE(!(cmdinfo->state & COMMAND_ABORTED));
+ /* all urbs are killed, clear inflight bits */
+ cmdinfo->state &= ~(COMMAND_INFLIGHT |
+ DATA_IN_URB_INFLIGHT |
+ DATA_OUT_URB_INFLIGHT);
+ uas_try_complete(cmnd, __func__);
+ }
+ devinfo->running_task = 0;
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+}
static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
{
@@ -165,10 +230,6 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
}
cmnd->result = sense_iu->status;
- if (sdev->current_cmnd)
- sdev->current_cmnd = NULL;
- cmnd->scsi_done(cmnd);
- usb_free_urb(urb);
}
static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
@@ -192,92 +253,216 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
}
cmnd->result = sense_iu->status;
- if (sdev->current_cmnd)
- sdev->current_cmnd = NULL;
+}
+
+static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller)
+{
+ struct uas_cmd_info *ci = (void *)&cmnd->SCp;
+
+ scmd_printk(KERN_INFO, cmnd, "%s %p tag %d, inflight:"
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ caller, cmnd, cmnd->request->tag,
+ (ci->state & SUBMIT_STATUS_URB) ? " s-st" : "",
+ (ci->state & ALLOC_DATA_IN_URB) ? " a-in" : "",
+ (ci->state & SUBMIT_DATA_IN_URB) ? " s-in" : "",
+ (ci->state & ALLOC_DATA_OUT_URB) ? " a-out" : "",
+ (ci->state & SUBMIT_DATA_OUT_URB) ? " s-out" : "",
+ (ci->state & ALLOC_CMD_URB) ? " a-cmd" : "",
+ (ci->state & SUBMIT_CMD_URB) ? " s-cmd" : "",
+ (ci->state & COMMAND_INFLIGHT) ? " CMD" : "",
+ (ci->state & DATA_IN_URB_INFLIGHT) ? " IN" : "",
+ (ci->state & DATA_OUT_URB_INFLIGHT) ? " OUT" : "",
+ (ci->state & COMMAND_COMPLETED) ? " done" : "",
+ (ci->state & COMMAND_ABORTED) ? " abort" : "",
+ (ci->state & UNLINK_DATA_URBS) ? " unlink": "",
+ (ci->state & IS_IN_WORK_LIST) ? " work" : "");
+}
+
+static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
+{
+ struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
+
+ WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
+ if (cmdinfo->state & (COMMAND_INFLIGHT |
+ DATA_IN_URB_INFLIGHT |
+ DATA_OUT_URB_INFLIGHT |
+ UNLINK_DATA_URBS))
+ return -EBUSY;
+ WARN_ON_ONCE(cmdinfo->state & COMMAND_COMPLETED);
+ cmdinfo->state |= COMMAND_COMPLETED;
+ usb_free_urb(cmdinfo->data_in_urb);
+ usb_free_urb(cmdinfo->data_out_urb);
+ if (cmdinfo->state & COMMAND_ABORTED)
+ scmd_printk(KERN_INFO, cmnd, "abort completed\n");
+ list_del(&cmdinfo->list);
cmnd->scsi_done(cmnd);
- usb_free_urb(urb);
+ return 0;
}
static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
- unsigned direction)
+ unsigned direction)
{
struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
int err;
- cmdinfo->state = direction | SUBMIT_SENSE_URB;
+ cmdinfo->state |= direction | SUBMIT_STATUS_URB;
err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
if (err) {
- spin_lock(&uas_work_lock);
- list_add_tail(&cmdinfo->list, &uas_work_list);
- spin_unlock(&uas_work_lock);
- schedule_work(&uas_work);
+ uas_add_work(cmdinfo);
}
}
static void uas_stat_cmplt(struct urb *urb)
{
struct iu *iu = urb->transfer_buffer;
- struct scsi_device *sdev = urb->context;
- struct uas_dev_info *devinfo = sdev->hostdata;
+ struct Scsi_Host *shost = urb->context;
+ struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
struct scsi_cmnd *cmnd;
+ struct uas_cmd_info *cmdinfo;
+ unsigned long flags;
u16 tag;
if (urb->status) {
- dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status);
+ if (urb->status == -ENOENT) {
+ dev_err(&urb->dev->dev, "stat urb: killed, stream %d\n",
+ urb->stream_id);
+ } else {
+ dev_err(&urb->dev->dev, "stat urb: status %d\n",
+ urb->status);
+ }
usb_free_urb(urb);
return;
}
+ if (devinfo->resetting) {
+ usb_free_urb(urb);
+ return;
+ }
+
+ spin_lock_irqsave(&devinfo->lock, flags);
tag = be16_to_cpup(&iu->tag) - 1;
- if (sdev->current_cmnd)
- cmnd = sdev->current_cmnd;
+ if (tag == 0)
+ cmnd = devinfo->cmnd;
else
- cmnd = scsi_find_tag(sdev, tag);
- if (!cmnd)
+ cmnd = scsi_host_find_tag(shost, tag - 1);
+
+ if (!cmnd) {
+ if (iu->iu_id == IU_ID_RESPONSE) {
+ if (!devinfo->running_task)
+ dev_warn(&urb->dev->dev,
+ "stat urb: recv unexpected response iu\n");
+ /* store results for uas_eh_task_mgmt() */
+ memcpy(&devinfo->response, iu, sizeof(devinfo->response));
+ }
+ usb_free_urb(urb);
+ spin_unlock_irqrestore(&devinfo->lock, flags);
return;
+ }
+ cmdinfo = (void *)&cmnd->SCp;
switch (iu->iu_id) {
case IU_ID_STATUS:
+ if (devinfo->cmnd == cmnd)
+ devinfo->cmnd = NULL;
+
if (urb->actual_length < 16)
devinfo->uas_sense_old = 1;
if (devinfo->uas_sense_old)
uas_sense_old(urb, cmnd);
else
uas_sense(urb, cmnd);
+ if (cmnd->result != 0) {
+ /* cancel data transfers on error */
+ uas_unlink_data_urbs(devinfo, cmdinfo, &flags);
+ }
+ cmdinfo->state &= ~COMMAND_INFLIGHT;
+ uas_try_complete(cmnd, __func__);
break;
case IU_ID_READ_READY:
+ if (!cmdinfo->data_in_urb ||
+ (cmdinfo->state & DATA_IN_URB_INFLIGHT)) {
+ scmd_printk(KERN_ERR, cmnd, "unexpected read rdy\n");
+ break;
+ }
uas_xfer_data(urb, cmnd, SUBMIT_DATA_IN_URB);
break;
case IU_ID_WRITE_READY:
+ if (!cmdinfo->data_out_urb ||
+ (cmdinfo->state & DATA_OUT_URB_INFLIGHT)) {
+ scmd_printk(KERN_ERR, cmnd, "unexpected write rdy\n");
+ break;
+ }
uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB);
break;
default:
scmd_printk(KERN_ERR, cmnd,
"Bogus IU (%d) received on status pipe\n", iu->iu_id);
}
+ usb_free_urb(urb);
+ spin_unlock_irqrestore(&devinfo->lock, flags);
}
static void uas_data_cmplt(struct urb *urb)
{
- struct scsi_data_buffer *sdb = urb->context;
- sdb->resid = sdb->length - urb->actual_length;
+ struct scsi_cmnd *cmnd = urb->context;
+ struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
+ struct scsi_data_buffer *sdb = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&devinfo->lock, flags);
+ if (cmdinfo->data_in_urb == urb) {
+ sdb = scsi_in(cmnd);
+ cmdinfo->state &= ~DATA_IN_URB_INFLIGHT;
+ } else if (cmdinfo->data_out_urb == urb) {
+ sdb = scsi_out(cmnd);
+ cmdinfo->state &= ~DATA_OUT_URB_INFLIGHT;
+ }
+ if (sdb == NULL) {
+ WARN_ON_ONCE(1);
+ } else if (urb->status) {
+ if (urb->status != -ECONNRESET) {
+ uas_log_cmd_state(cmnd, __func__);
+ scmd_printk(KERN_ERR, cmnd,
+ "data cmplt err %d stream %d\n",
+ urb->status, urb->stream_id);
+ }
+ /* error: no data transfered */
+ sdb->resid = sdb->length;
+ } else {
+ sdb->resid = sdb->length - urb->actual_length;
+ }
+ uas_try_complete(cmnd, __func__);
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+}
+
+static void uas_cmd_cmplt(struct urb *urb)
+{
+ struct scsi_cmnd *cmnd = urb->context;
+
+ if (urb->status) {
+ uas_log_cmd_state(cmnd, __func__);
+ scmd_printk(KERN_ERR, cmnd, "cmd cmplt err %d\n", urb->status);
+ }
usb_free_urb(urb);
}
static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
- unsigned int pipe, u16 stream_id,
- struct scsi_data_buffer *sdb,
- enum dma_data_direction dir)
+ unsigned int pipe, u16 stream_id,
+ struct scsi_cmnd *cmnd,
+ enum dma_data_direction dir)
{
struct usb_device *udev = devinfo->udev;
struct urb *urb = usb_alloc_urb(0, gfp);
+ struct scsi_data_buffer *sdb = (dir == DMA_FROM_DEVICE)
+ ? scsi_in(cmnd) : scsi_out(cmnd);
if (!urb)
goto out;
- usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt,
- sdb);
- if (devinfo->use_streams)
- urb->stream_id = stream_id;
+ usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length,
+ uas_data_cmplt, cmnd);
+ urb->stream_id = stream_id;
urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0;
urb->sg = sdb->table.sgl;
out:
@@ -285,7 +470,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
}
static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
- struct scsi_cmnd *cmnd, u16 stream_id)
+ struct Scsi_Host *shost, u16 stream_id)
{
struct usb_device *udev = devinfo->udev;
struct urb *urb = usb_alloc_urb(0, gfp);
@@ -294,12 +479,12 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
if (!urb)
goto out;
- iu = kmalloc(sizeof(*iu), gfp);
+ iu = kzalloc(sizeof(*iu), gfp);
if (!iu)
goto free;
usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
- uas_stat_cmplt, cmnd->device);
+ uas_stat_cmplt, shost);
urb->stream_id = stream_id;
urb->transfer_flags |= URB_FREE_BUFFER;
out:
@@ -310,7 +495,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
}
static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
- struct scsi_cmnd *cmnd, u16 stream_id)
+ struct scsi_cmnd *cmnd)
{
struct usb_device *udev = devinfo->udev;
struct scsi_device *sdev = cmnd->device;
@@ -325,19 +510,22 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
if (len < 0)
len = 0;
len = ALIGN(len, 4);
- iu = kmalloc(sizeof(*iu) + len, gfp);
+ iu = kzalloc(sizeof(*iu) + len, gfp);
if (!iu)
goto free;
iu->iu_id = IU_ID_COMMAND;
- iu->tag = cpu_to_be16(stream_id);
+ if (blk_rq_tagged(cmnd->request))
+ iu->tag = cpu_to_be16(cmnd->request->tag + 2);
+ else
+ iu->tag = cpu_to_be16(1);
iu->prio_attr = UAS_SIMPLE_TAG;
iu->len = len;
int_to_scsilun(sdev->lun, &iu->lun);
memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len);
usb_fill_bulk_urb(urb, udev, devinfo->cmd_pipe, iu, sizeof(*iu) + len,
- usb_free_urb, NULL);
+ uas_cmd_cmplt, cmnd);
urb->transfer_flags |= URB_FREE_BUFFER;
out:
return urb;
@@ -346,113 +534,212 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
return NULL;
}
+static int uas_submit_task_urb(struct scsi_cmnd *cmnd, gfp_t gfp,
+ u8 function, u16 stream_id)
+{
+ struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
+ struct usb_device *udev = devinfo->udev;
+ struct urb *urb = usb_alloc_urb(0, gfp);
+ struct task_mgmt_iu *iu;
+ int err = -ENOMEM;
+
+ if (!urb)
+ goto err;
+
+ iu = kzalloc(sizeof(*iu), gfp);
+ if (!iu)
+ goto err;
+
+ iu->iu_id = IU_ID_TASK_MGMT;
+ iu->tag = cpu_to_be16(stream_id);
+ int_to_scsilun(cmnd->device->lun, &iu->lun);
+
+ iu->function = function;
+ switch (function) {
+ case TMF_ABORT_TASK:
+ if (blk_rq_tagged(cmnd->request))
+ iu->task_tag = cpu_to_be16(cmnd->request->tag + 2);
+ else
+ iu->task_tag = cpu_to_be16(1);
+ break;
+ }
+
+ usb_fill_bulk_urb(urb, udev, devinfo->cmd_pipe, iu, sizeof(*iu),
+ uas_cmd_cmplt, cmnd);
+ urb->transfer_flags |= URB_FREE_BUFFER;
+
+ usb_anchor_urb(urb, &devinfo->cmd_urbs);
+ err = usb_submit_urb(urb, gfp);
+ if (err) {
+ usb_unanchor_urb(urb);
+ uas_log_cmd_state(cmnd, __func__);
+ scmd_printk(KERN_ERR, cmnd, "task submission err %d\n", err);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ usb_free_urb(urb);
+ return err;
+}
+
/*
* Why should I request the Status IU before sending the Command IU? Spec
* says to, but also says the device may receive them in any order. Seems
* daft to me.
*/
-static int uas_submit_urbs(struct scsi_cmnd *cmnd,
- struct uas_dev_info *devinfo, gfp_t gfp)
+static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd,
+ gfp_t gfp, unsigned int stream)
{
- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct Scsi_Host *shost = cmnd->device->host;
+ struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
+ struct urb *urb;
+ int err;
- if (cmdinfo->state & ALLOC_SENSE_URB) {
- cmdinfo->sense_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd,
- cmdinfo->stream);
- if (!cmdinfo->sense_urb)
- return SCSI_MLQUEUE_DEVICE_BUSY;
- cmdinfo->state &= ~ALLOC_SENSE_URB;
+ urb = uas_alloc_sense_urb(devinfo, gfp, shost, stream);
+ if (!urb)
+ return NULL;
+ usb_anchor_urb(urb, &devinfo->sense_urbs);
+ err = usb_submit_urb(urb, gfp);
+ if (err) {
+ usb_unanchor_urb(urb);
+ uas_log_cmd_state(cmnd, __func__);
+ shost_printk(KERN_INFO, shost,
+ "sense urb submission error %d stream %d\n",
+ err, stream);
+ usb_free_urb(urb);
+ return NULL;
}
+ return urb;
+}
- if (cmdinfo->state & SUBMIT_SENSE_URB) {
- if (usb_submit_urb(cmdinfo->sense_urb, gfp)) {
- scmd_printk(KERN_INFO, cmnd,
- "sense urb submission failure\n");
+static int uas_submit_urbs(struct scsi_cmnd *cmnd,
+ struct uas_dev_info *devinfo, gfp_t gfp)
+{
+ struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct urb *urb;
+ int err;
+
+ WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
+ if (cmdinfo->state & SUBMIT_STATUS_URB) {
+ urb = uas_submit_sense_urb(cmnd, gfp, cmdinfo->stream);
+ if (!urb)
return SCSI_MLQUEUE_DEVICE_BUSY;
- }
- cmdinfo->state &= ~SUBMIT_SENSE_URB;
+ cmdinfo->state &= ~SUBMIT_STATUS_URB;
}
if (cmdinfo->state & ALLOC_DATA_IN_URB) {
cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp,
devinfo->data_in_pipe, cmdinfo->stream,
- scsi_in(cmnd), DMA_FROM_DEVICE);
+ cmnd, DMA_FROM_DEVICE);
if (!cmdinfo->data_in_urb)
return SCSI_MLQUEUE_DEVICE_BUSY;
cmdinfo->state &= ~ALLOC_DATA_IN_URB;
}
if (cmdinfo->state & SUBMIT_DATA_IN_URB) {
- if (usb_submit_urb(cmdinfo->data_in_urb, gfp)) {
+ usb_anchor_urb(cmdinfo->data_in_urb, &devinfo->data_urbs);
+ err = usb_submit_urb(cmdinfo->data_in_urb, gfp);
+ if (err) {
+ usb_unanchor_urb(cmdinfo->data_in_urb);
+ uas_log_cmd_state(cmnd, __func__);
scmd_printk(KERN_INFO, cmnd,
- "data in urb submission failure\n");
+ "data in urb submission error %d stream %d\n",
+ err, cmdinfo->data_in_urb->stream_id);
return SCSI_MLQUEUE_DEVICE_BUSY;
}
cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
+ cmdinfo->state |= DATA_IN_URB_INFLIGHT;
}
if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp,
devinfo->data_out_pipe, cmdinfo->stream,
- scsi_out(cmnd), DMA_TO_DEVICE);
+ cmnd, DMA_TO_DEVICE);
if (!cmdinfo->data_out_urb)
return SCSI_MLQUEUE_DEVICE_BUSY;
cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
}
if (cmdinfo->state & SUBMIT_DATA_OUT_URB) {
- if (usb_submit_urb(cmdinfo->data_out_urb, gfp)) {
+ usb_anchor_urb(cmdinfo->data_out_urb, &devinfo->data_urbs);
+ err = usb_submit_urb(cmdinfo->data_out_urb, gfp);
+ if (err) {
+ usb_unanchor_urb(cmdinfo->data_out_urb);
+ uas_log_cmd_state(cmnd, __func__);
scmd_printk(KERN_INFO, cmnd,
- "data out urb submission failure\n");
+ "data out urb submission error %d stream %d\n",
+ err, cmdinfo->data_out_urb->stream_id);
return SCSI_MLQUEUE_DEVICE_BUSY;
}
cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
+ cmdinfo->state |= DATA_OUT_URB_INFLIGHT;
}
if (cmdinfo->state & ALLOC_CMD_URB) {
- cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd,
- cmdinfo->stream);
+ cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd);
if (!cmdinfo->cmd_urb)
return SCSI_MLQUEUE_DEVICE_BUSY;
cmdinfo->state &= ~ALLOC_CMD_URB;
}
if (cmdinfo->state & SUBMIT_CMD_URB) {
- if (usb_submit_urb(cmdinfo->cmd_urb, gfp)) {
+ usb_anchor_urb(cmdinfo->cmd_urb, &devinfo->cmd_urbs);
+ err = usb_submit_urb(cmdinfo->cmd_urb, gfp);
+ if (err) {
+ usb_unanchor_urb(cmdinfo->cmd_urb);
+ uas_log_cmd_state(cmnd, __func__);
scmd_printk(KERN_INFO, cmnd,
- "cmd urb submission failure\n");
+ "cmd urb submission error %d\n", err);
return SCSI_MLQUEUE_DEVICE_BUSY;
}
+ cmdinfo->cmd_urb = NULL;
cmdinfo->state &= ~SUBMIT_CMD_URB;
+ cmdinfo->state |= COMMAND_INFLIGHT;
}
return 0;
}
-static int uas_queuecommand(struct scsi_cmnd *cmnd,
+static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
void (*done)(struct scsi_cmnd *))
{
struct scsi_device *sdev = cmnd->device;
struct uas_dev_info *devinfo = sdev->hostdata;
struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ unsigned long flags;
int err;
BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
- if (!cmdinfo->sense_urb && sdev->current_cmnd)
+ spin_lock_irqsave(&devinfo->lock, flags);
+
+ if (devinfo->resetting) {
+ cmnd->result = DID_ERROR << 16;
+ cmnd->scsi_done(cmnd);
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+ return 0;
+ }
+
+ if (devinfo->cmnd) {
+ spin_unlock_irqrestore(&devinfo->lock, flags);
return SCSI_MLQUEUE_DEVICE_BUSY;
+ }
+
+ memset(cmdinfo, 0, sizeof(*cmdinfo));
if (blk_rq_tagged(cmnd->request)) {
- cmdinfo->stream = cmnd->request->tag + 1;
+ cmdinfo->stream = cmnd->request->tag + 2;
} else {
- sdev->current_cmnd = cmnd;
+ devinfo->cmnd = cmnd;
cmdinfo->stream = 1;
}
cmnd->scsi_done = done;
- cmdinfo->state = ALLOC_SENSE_URB | SUBMIT_SENSE_URB |
+ cmdinfo->state = SUBMIT_STATUS_URB |
ALLOC_CMD_URB | SUBMIT_CMD_URB;
switch (cmnd->sc_data_direction) {
@@ -475,49 +762,130 @@ static int uas_queuecommand(struct scsi_cmnd *cmnd,
err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC);
if (err) {
/* If we did nothing, give up now */
- if (cmdinfo->state & SUBMIT_SENSE_URB) {
- usb_free_urb(cmdinfo->sense_urb);
+ if (cmdinfo->state & SUBMIT_STATUS_URB) {
+ spin_unlock_irqrestore(&devinfo->lock, flags);
return SCSI_MLQUEUE_DEVICE_BUSY;
}
- spin_lock(&uas_work_lock);
- list_add_tail(&cmdinfo->list, &uas_work_list);
- spin_unlock(&uas_work_lock);
- schedule_work(&uas_work);
+ uas_add_work(cmdinfo);
}
+ list_add_tail(&cmdinfo->list, &devinfo->inflight_list);
+ spin_unlock_irqrestore(&devinfo->lock, flags);
return 0;
}
-static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
+static DEF_SCSI_QCMD(uas_queuecommand)
+
+static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
+ const char *fname, u8 function)
{
- struct scsi_device *sdev = cmnd->device;
- sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
- cmnd->request->tag);
+ struct Scsi_Host *shost = cmnd->device->host;
+ struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
+ u16 tag = devinfo->qdepth;
+ unsigned long flags;
+ struct urb *sense_urb;
+ int result = SUCCESS;
+
+ spin_lock_irqsave(&devinfo->lock, flags);
+
+ if (devinfo->resetting) {
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+ return FAILED;
+ }
+
+ if (devinfo->running_task) {
+ shost_printk(KERN_INFO, shost,
+ "%s: %s: error already running a task\n",
+ __func__, fname);
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+ return FAILED;
+ }
+
+ devinfo->running_task = 1;
+ memset(&devinfo->response, 0, sizeof(devinfo->response));
+ sense_urb = uas_submit_sense_urb(cmnd, GFP_ATOMIC,
+ devinfo->use_streams ? tag : 0);
+ if (!sense_urb) {
+ shost_printk(KERN_INFO, shost,
+ "%s: %s: submit sense urb failed\n",
+ __func__, fname);
+ devinfo->running_task = 0;
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+ return FAILED;
+ }
+ if (uas_submit_task_urb(cmnd, GFP_ATOMIC, function, tag)) {
+ shost_printk(KERN_INFO, shost,
+ "%s: %s: submit task mgmt urb failed\n",
+ __func__, fname);
+ devinfo->running_task = 0;
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+ usb_kill_urb(sense_urb);
+ return FAILED;
+ }
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+
+ if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 3000) == 0) {
+ /*
+ * Note we deliberately do not clear running_task here. If we
+ * allow new tasks to be submitted, there is no way to figure
+ * out if a received response_iu is for the failed task or for
+ * the new one. A bus-reset will eventually clear running_task.
+ */
+ shost_printk(KERN_INFO, shost,
+ "%s: %s timed out\n", __func__, fname);
+ return FAILED;
+ }
+
+ spin_lock_irqsave(&devinfo->lock, flags);
+ devinfo->running_task = 0;
+ if (be16_to_cpu(devinfo->response.tag) != tag) {
+ shost_printk(KERN_INFO, shost,
+ "%s: %s failed (wrong tag %d/%d)\n", __func__,
+ fname, be16_to_cpu(devinfo->response.tag), tag);
+ result = FAILED;
+ } else if (devinfo->response.response_code != RC_TMF_COMPLETE) {
+ shost_printk(KERN_INFO, shost,
+ "%s: %s failed (rc 0x%x)\n", __func__,
+ fname, devinfo->response.response_code);
+ result = FAILED;
+ }
+ spin_unlock_irqrestore(&devinfo->lock, flags);
-/* XXX: Send ABORT TASK Task Management command */
- return FAILED;
+ return result;
}
-static int uas_eh_device_reset_handler(struct scsi_cmnd *cmnd)
+static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
{
- struct scsi_device *sdev = cmnd->device;
- sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
- cmnd->request->tag);
+ struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&devinfo->lock, flags);
+
+ if (devinfo->resetting) {
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+ return FAILED;
+ }
-/* XXX: Send LOGICAL UNIT RESET Task Management command */
- return FAILED;
+ uas_mark_cmd_dead(devinfo, cmdinfo, DID_ABORT, __func__);
+ if (cmdinfo->state & COMMAND_INFLIGHT) {
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+ ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK);
+ } else {
+ uas_unlink_data_urbs(devinfo, cmdinfo, &flags);
+ uas_try_complete(cmnd, __func__);
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+ ret = SUCCESS;
+ }
+ return ret;
}
-static int uas_eh_target_reset_handler(struct scsi_cmnd *cmnd)
+static int uas_eh_device_reset_handler(struct scsi_cmnd *cmnd)
{
- struct scsi_device *sdev = cmnd->device;
- sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
- cmnd->request->tag);
-
-/* XXX: Can we reset just the one USB interface?
- * Would calling usb_set_interface() have the right effect?
- */
- return FAILED;
+ sdev_printk(KERN_INFO, cmnd->device, "%s\n", __func__);
+ return uas_eh_task_mgmt(cmnd, "LOGICAL UNIT RESET",
+ TMF_LOGICAL_UNIT_RESET);
}
static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
@@ -525,19 +893,57 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
struct scsi_device *sdev = cmnd->device;
struct uas_dev_info *devinfo = sdev->hostdata;
struct usb_device *udev = devinfo->udev;
+ int err;
+
+ err = usb_lock_device_for_reset(udev, devinfo->intf);
+ if (err) {
+ shost_printk(KERN_ERR, sdev->host,
+ "%s FAILED to get lock err %d\n", __func__, err);
+ return FAILED;
+ }
+
+ shost_printk(KERN_INFO, sdev->host, "%s start\n", __func__);
+ devinfo->resetting = 1;
+ uas_abort_inflight(devinfo, DID_RESET, __func__);
+ usb_kill_anchored_urbs(&devinfo->cmd_urbs);
+ usb_kill_anchored_urbs(&devinfo->sense_urbs);
+ usb_kill_anchored_urbs(&devinfo->data_urbs);
+ uas_zap_dead(devinfo);
+ err = usb_reset_device(udev);
+ devinfo->resetting = 0;
- sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
- cmnd->request->tag);
+ usb_unlock_device(udev);
- if (usb_reset_device(udev))
- return SUCCESS;
+ if (err) {
+ shost_printk(KERN_INFO, sdev->host, "%s FAILED\n", __func__);
+ return FAILED;
+ }
- return FAILED;
+ shost_printk(KERN_INFO, sdev->host, "%s success\n", __func__);
+ return SUCCESS;
}
static int uas_slave_alloc(struct scsi_device *sdev)
{
- sdev->hostdata = (void *)sdev->host->hostdata[0];
+ sdev->hostdata = (void *)sdev->host->hostdata;
+
+ /* USB has unusual DMA-alignment requirements: Although the
+ * starting address of each scatter-gather element doesn't matter,
+ * the length of each element except the last must be divisible
+ * by the Bulk maxpacket value. There's currently no way to
+ * express this by block-layer constraints, so we'll cop out
+ * and simply require addresses to be aligned at 512-byte
+ * boundaries. This is okay since most block I/O involves
+ * hardware sectors that are multiples of 512 bytes in length,
+ * and since host controllers up through USB 2.0 have maxpacket
+ * values no larger than 512.
+ *
+ * But it doesn't suffice for Wireless USB, where Bulk maxpacket
+ * values can be as large as 2048. To make that work properly
+ * will require changes to the block layer.
+ */
+ blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
+
return 0;
}
@@ -545,7 +951,7 @@ static int uas_slave_configure(struct scsi_device *sdev)
{
struct uas_dev_info *devinfo = sdev->hostdata;
scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
- scsi_activate_tcq(sdev, devinfo->qdepth - 1);
+ scsi_activate_tcq(sdev, devinfo->qdepth - 2);
return 0;
}
@@ -557,7 +963,6 @@ static struct scsi_host_template uas_host_template = {
.slave_configure = uas_slave_configure,
.eh_abort_handler = uas_eh_abort_handler,
.eh_device_reset_handler = uas_eh_device_reset_handler,
- .eh_target_reset_handler = uas_eh_target_reset_handler,
.eh_bus_reset_handler = uas_eh_bus_reset_handler,
.can_queue = 65536, /* Is there a limit on the _host_ ? */
.this_id = -1,
@@ -567,7 +972,14 @@ static struct scsi_host_template uas_host_template = {
.ordered_tag = 1,
};
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+ vendorName, productName, useProtocol, useTransport, \
+ initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+ .driver_info = (flags) }
+
static struct usb_device_id uas_usb_ids[] = {
+# include "unusual_uas.h"
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) },
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_UAS) },
/* 0xaa is a prototype device I happen to have access to */
@@ -576,114 +988,127 @@ static struct usb_device_id uas_usb_ids[] = {
};
MODULE_DEVICE_TABLE(usb, uas_usb_ids);
-static void uas_configure_endpoints(struct uas_dev_info *devinfo)
+#undef UNUSUAL_DEV
+
+static int uas_switch_interface(struct usb_device *udev,
+ struct usb_interface *intf)
+{
+ int alt;
+
+ alt = uas_find_uas_alt_setting(intf);
+ if (alt < 0)
+ return alt;
+
+ return usb_set_interface(udev,
+ intf->altsetting[0].desc.bInterfaceNumber, alt);
+}
+
+static int uas_configure_endpoints(struct uas_dev_info *devinfo)
{
struct usb_host_endpoint *eps[4] = { };
- struct usb_interface *intf = devinfo->intf;
struct usb_device *udev = devinfo->udev;
- struct usb_host_endpoint *endpoint = intf->cur_altsetting->endpoint;
- unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints;
+ int r;
devinfo->uas_sense_old = 0;
-
- for (i = 0; i < n_endpoints; i++) {
- unsigned char *extra = endpoint[i].extra;
- int len = endpoint[i].extralen;
- while (len > 1) {
- if (extra[1] == USB_DT_PIPE_USAGE) {
- unsigned pipe_id = extra[2];
- if (pipe_id > 0 && pipe_id < 5)
- eps[pipe_id - 1] = &endpoint[i];
- break;
- }
- len -= extra[0];
- extra += extra[0];
- }
- }
-
- /*
- * Assume that if we didn't find a control pipe descriptor, we're
- * using a device with old firmware that happens to be set up like
- * this.
- */
- if (!eps[0]) {
- devinfo->cmd_pipe = usb_sndbulkpipe(udev, 1);
- devinfo->status_pipe = usb_rcvbulkpipe(udev, 1);
- devinfo->data_in_pipe = usb_rcvbulkpipe(udev, 2);
- devinfo->data_out_pipe = usb_sndbulkpipe(udev, 2);
-
- eps[1] = usb_pipe_endpoint(udev, devinfo->status_pipe);
- eps[2] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
- eps[3] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
- } else {
- devinfo->cmd_pipe = usb_sndbulkpipe(udev,
- eps[0]->desc.bEndpointAddress);
- devinfo->status_pipe = usb_rcvbulkpipe(udev,
- eps[1]->desc.bEndpointAddress);
- devinfo->data_in_pipe = usb_rcvbulkpipe(udev,
- eps[2]->desc.bEndpointAddress);
- devinfo->data_out_pipe = usb_sndbulkpipe(udev,
- eps[3]->desc.bEndpointAddress);
- }
-
- devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1, 3, 256,
- GFP_KERNEL);
- if (devinfo->qdepth < 0) {
+ devinfo->cmnd = NULL;
+
+ r = uas_find_endpoints(devinfo->intf->cur_altsetting, eps);
+ if (r)
+ return r;
+
+ devinfo->cmd_pipe = usb_sndbulkpipe(udev,
+ usb_endpoint_num(&eps[0]->desc));
+ devinfo->status_pipe = usb_rcvbulkpipe(udev,
+ usb_endpoint_num(&eps[1]->desc));
+ devinfo->data_in_pipe = usb_rcvbulkpipe(udev,
+ usb_endpoint_num(&eps[2]->desc));
+ devinfo->data_out_pipe = usb_sndbulkpipe(udev,
+ usb_endpoint_num(&eps[3]->desc));
+
+ if (udev->speed != USB_SPEED_SUPER) {
devinfo->qdepth = 256;
devinfo->use_streams = 0;
} else {
+ devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1,
+ 3, 256, GFP_NOIO);
+ if (devinfo->qdepth < 0)
+ return devinfo->qdepth;
devinfo->use_streams = 1;
}
+
+ return 0;
+}
+
+static void uas_free_streams(struct uas_dev_info *devinfo)
+{
+ struct usb_device *udev = devinfo->udev;
+ struct usb_host_endpoint *eps[3];
+
+ eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
+ eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
+ eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
+ usb_free_streams(devinfo->intf, eps, 3, GFP_NOIO);
}
-/*
- * XXX: What I'd like to do here is register a SCSI host for each USB host in
- * the system. Follow usb-storage's design of registering a SCSI host for
- * each USB device for the moment. Can implement this by walking up the
- * USB hierarchy until we find a USB host.
- */
static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
- int result;
- struct Scsi_Host *shost;
+ int result = -ENOMEM;
+ struct Scsi_Host *shost = NULL;
struct uas_dev_info *devinfo;
struct usb_device *udev = interface_to_usbdev(intf);
- if (id->bInterfaceProtocol == 0x50) {
- int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-/* XXX: Shouldn't assume that 1 is the alternative we want */
- int ret = usb_set_interface(udev, ifnum, 1);
- if (ret)
- return -ENODEV;
- }
+ if (!uas_use_uas_driver(intf, id))
+ return -ENODEV;
- devinfo = kmalloc(sizeof(struct uas_dev_info), GFP_KERNEL);
- if (!devinfo)
- return -ENOMEM;
+ if (uas_switch_interface(udev, intf))
+ return -ENODEV;
- result = -ENOMEM;
- shost = scsi_host_alloc(&uas_host_template, sizeof(void *));
+ shost = scsi_host_alloc(&uas_host_template,
+ sizeof(struct uas_dev_info));
if (!shost)
- goto free;
+ goto set_alt0;
shost->max_cmd_len = 16 + 252;
shost->max_id = 1;
+ shost->max_lun = 256;
+ shost->max_channel = 0;
shost->sg_tablesize = udev->bus->sg_tablesize;
- result = scsi_add_host(shost, &intf->dev);
- if (result)
- goto free;
- shost->hostdata[0] = (unsigned long)devinfo;
-
+ devinfo = (struct uas_dev_info *)shost->hostdata;
devinfo->intf = intf;
devinfo->udev = udev;
- uas_configure_endpoints(devinfo);
+ devinfo->resetting = 0;
+ devinfo->running_task = 0;
+ devinfo->shutdown = 0;
+ init_usb_anchor(&devinfo->cmd_urbs);
+ init_usb_anchor(&devinfo->sense_urbs);
+ init_usb_anchor(&devinfo->data_urbs);
+ spin_lock_init(&devinfo->lock);
+ INIT_WORK(&devinfo->work, uas_do_work);
+ INIT_LIST_HEAD(&devinfo->inflight_list);
+ INIT_LIST_HEAD(&devinfo->dead_list);
+
+ result = uas_configure_endpoints(devinfo);
+ if (result)
+ goto set_alt0;
+
+ result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2);
+ if (result)
+ goto free_streams;
- scsi_scan_host(shost);
usb_set_intfdata(intf, shost);
+ result = scsi_add_host(shost, &intf->dev);
+ if (result)
+ goto free_streams;
+
+ scsi_scan_host(shost);
return result;
- free:
- kfree(devinfo);
+
+free_streams:
+ uas_free_streams(devinfo);
+ usb_set_intfdata(intf, NULL);
+set_alt0:
+ usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
if (shost)
scsi_host_put(shost);
return result;
@@ -691,58 +1116,146 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
static int uas_pre_reset(struct usb_interface *intf)
{
-/* XXX: Need to return 1 if it's not our device in error handling */
+ struct Scsi_Host *shost = usb_get_intfdata(intf);
+ struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
+ unsigned long flags;
+
+ if (devinfo->shutdown)
+ return 0;
+
+ /* Block new requests */
+ spin_lock_irqsave(shost->host_lock, flags);
+ scsi_block_requests(shost);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ /* Wait for any pending requests to complete */
+ flush_work(&devinfo->work);
+ if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 5000) == 0) {
+ shost_printk(KERN_ERR, shost, "%s: timed out\n", __func__);
+ return 1;
+ }
+
+ uas_free_streams(devinfo);
+
return 0;
}
static int uas_post_reset(struct usb_interface *intf)
{
-/* XXX: Need to return 1 if it's not our device in error handling */
+ struct Scsi_Host *shost = usb_get_intfdata(intf);
+ struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
+ unsigned long flags;
+
+ if (devinfo->shutdown)
+ return 0;
+
+ if (uas_configure_endpoints(devinfo) != 0) {
+ shost_printk(KERN_ERR, shost,
+ "%s: alloc streams error after reset", __func__);
+ return 1;
+ }
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ scsi_report_bus_reset(shost, 0);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ scsi_unblock_requests(shost);
+
return 0;
}
-static void uas_disconnect(struct usb_interface *intf)
+static int uas_suspend(struct usb_interface *intf, pm_message_t message)
{
- struct usb_device *udev = interface_to_usbdev(intf);
- struct usb_host_endpoint *eps[3];
struct Scsi_Host *shost = usb_get_intfdata(intf);
- struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+ struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
- scsi_remove_host(shost);
+ /* Wait for any pending requests to complete */
+ flush_work(&devinfo->work);
+ if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 5000) == 0) {
+ shost_printk(KERN_ERR, shost, "%s: timed out\n", __func__);
+ return -ETIME;
+ }
- eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
- eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
- eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
- usb_free_streams(intf, eps, 3, GFP_KERNEL);
+ return 0;
+}
- kfree(devinfo);
+static int uas_resume(struct usb_interface *intf)
+{
+ return 0;
+}
+
+static int uas_reset_resume(struct usb_interface *intf)
+{
+ struct Scsi_Host *shost = usb_get_intfdata(intf);
+ struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
+ unsigned long flags;
+
+ if (uas_configure_endpoints(devinfo) != 0) {
+ shost_printk(KERN_ERR, shost,
+ "%s: alloc streams error after reset", __func__);
+ return -EIO;
+ }
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ scsi_report_bus_reset(shost, 0);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ return 0;
+}
+
+static void uas_disconnect(struct usb_interface *intf)
+{
+ struct Scsi_Host *shost = usb_get_intfdata(intf);
+ struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
+
+ devinfo->resetting = 1;
+ cancel_work_sync(&devinfo->work);
+ uas_abort_inflight(devinfo, DID_NO_CONNECT, __func__);
+ usb_kill_anchored_urbs(&devinfo->cmd_urbs);
+ usb_kill_anchored_urbs(&devinfo->sense_urbs);
+ usb_kill_anchored_urbs(&devinfo->data_urbs);
+ uas_zap_dead(devinfo);
+ scsi_remove_host(shost);
+ uas_free_streams(devinfo);
+ scsi_host_put(shost);
}
/*
- * XXX: Should this plug into libusual so we can auto-upgrade devices from
- * Bulk-Only to UAS?
+ * Put the device back in usb-storage mode on shutdown, as some BIOS-es
+ * hang on reboot when the device is still in uas mode. Note the reset is
+ * necessary as some devices won't revert to usb-storage mode without it.
*/
+static void uas_shutdown(struct device *dev)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct Scsi_Host *shost = usb_get_intfdata(intf);
+ struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
+
+ if (system_state != SYSTEM_RESTART)
+ return;
+
+ devinfo->shutdown = 1;
+ uas_free_streams(devinfo);
+ usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
+ usb_reset_device(udev);
+}
+
static struct usb_driver uas_driver = {
.name = "uas",
.probe = uas_probe,
.disconnect = uas_disconnect,
.pre_reset = uas_pre_reset,
.post_reset = uas_post_reset,
+ .suspend = uas_suspend,
+ .resume = uas_resume,
+ .reset_resume = uas_reset_resume,
+ .drvwrap.driver.shutdown = uas_shutdown,
.id_table = uas_usb_ids,
};
-static int uas_init(void)
-{
- return usb_register(&uas_driver);
-}
-
-static void uas_exit(void)
-{
- usb_deregister(&uas_driver);
-}
-
-module_init(uas_init);
-module_exit(uas_exit);
+module_usb_driver(uas_driver);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Matthew Wilcox and Sarah Sharp");
+MODULE_AUTHOR(
+ "Hans de Goede <hdegoede@redhat.com>, Matthew Wilcox and Sarah Sharp");
diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h
index c854fdebe0a..82e8ed0324e 100644
--- a/drivers/usb/storage/unusual_cypress.h
+++ b/drivers/usb/storage/unusual_cypress.h
@@ -31,4 +31,9 @@ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999,
"Cypress ISD-300LP",
USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
+UNUSUAL_DEV( 0x14cd, 0x6116, 0x0160, 0x0160,
+ "Super Top",
+ "USB 2.0 SATA BRIDGE",
+ USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
+
#endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 6ccdd3dd525..80a5b366255 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -53,6 +53,14 @@
* as opposed to devices that do something strangely or wrongly.
*/
+/* In-kernel mode switching is deprecated. Do not add new devices to
+ * this list for the sole purpose of switching them to a different
+ * mode. Existing userspace solutions are superior.
+ *
+ * New mode switching devices should instead be added to the database
+ * maintained at http://www.draisberghof.de/usb_modeswitch/
+ */
+
#if !defined(CONFIG_USB_STORAGE_SDDR09) && \
!defined(CONFIG_USB_STORAGE_SDDR09_MODULE)
#define NO_SDDR09
@@ -110,7 +118,7 @@ UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
-/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
+/* Deduced by Jonathan Woithe <jwoithe@just42.net>
* Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
* always fails and confuses drive.
*/
@@ -226,6 +234,27 @@ UNUSUAL_DEV( 0x0421, 0x0495, 0x0370, 0x0370,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_MAX_SECTORS_64 ),
+/* Reported by Daniele Forsi <dforsi@gmail.com> */
+UNUSUAL_DEV( 0x0421, 0x04b9, 0x0350, 0x0350,
+ "Nokia",
+ "5300",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_MAX_SECTORS_64 ),
+
+/* Patch submitted by Victor A. Santos <victoraur.santos@gmail.com> */
+UNUSUAL_DEV( 0x0421, 0x05af, 0x0742, 0x0742,
+ "Nokia",
+ "305",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_MAX_SECTORS_64),
+
+/* Patch submitted by Mikhail Zolotaryov <lebon@lebon.org.ua> */
+UNUSUAL_DEV( 0x0421, 0x06aa, 0x1110, 0x1110,
+ "Nokia",
+ "502",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_MAX_SECTORS_64 ),
+
#ifdef NO_SDDR09
UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
"Microtech",
@@ -481,6 +510,20 @@ UNUSUAL_DEV( 0x04e8, 0x507c, 0x0220, 0x0220,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_MAX_SECTORS_64),
+/* Reported by Vitaly Kuznetsov <vitty@altlinux.ru> */
+UNUSUAL_DEV( 0x04e8, 0x5122, 0x0000, 0x9999,
+ "Samsung",
+ "YP-CP3",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG),
+
+/* Added by Dmitry Artamonow <mad_soft@inbox.ru> */
+UNUSUAL_DEV( 0x04e8, 0x5136, 0x0000, 0x9999,
+ "Samsung",
+ "YP-Z3",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_MAX_SECTORS_64),
+
/* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
* Device uses standards-violating 32-byte Bulk Command Block Wrappers and
* reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011.
@@ -643,6 +686,13 @@ UNUSUAL_DEV( 0x054c, 0x016a, 0x0000, 0x9999,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
+/* Submitted by Ren Bigcren <bigcren.ren@sonymobile.com> */
+UNUSUAL_DEV( 0x054c, 0x02a5, 0x0100, 0x0100,
+ "Sony Corp.",
+ "MicroVault Flash Drive",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_NO_READ_CAPACITY_16 ),
+
/* floppy reports multiple luns */
UNUSUAL_DEV( 0x055d, 0x2020, 0x0000, 0x0210,
"SAMSUNG",
@@ -997,6 +1047,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,
USB_SC_8070, USB_PR_CB, NULL,
US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ),
+/* Submitted by Oleksandr Chumachenko <ledest@gmail.com> */
+UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100,
+ "Casio",
+ "EX-N1 DigitalCamera",
+ USB_SC_8070, USB_PR_DEVICE, NULL, 0),
+
/* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
"Samsung",
@@ -1037,6 +1093,15 @@ UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_BULK32),
+/* Reported by <ttkspam@free.fr>
+ * The device reports a vendor-specific device class, requiring an
+ * explicit vendor/product match.
+ */
+UNUSUAL_DEV( 0x0851, 0x1542, 0x0002, 0x0002,
+ "MagicPixel",
+ "FW_Omega2",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0),
+
/* Andrew Lunn <andrew@lunn.ch>
* PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL
* on LUN 4.
@@ -1098,6 +1163,16 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/* Reported by Paul Hartman <paul.hartman+linux@gmail.com>
+ * This card reader returns "Illegal Request, Logical Block Address
+ * Out of Range" for the first READ(10) after a new card is inserted.
+ */
+UNUSUAL_DEV( 0x090c, 0x6000, 0x0100, 0x0100,
+ "Feiya",
+ "SD/SDHC Card Reader",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_INITIAL_READ10 ),
+
/* This Pentax still camera is not conformant
* to the USB storage specification: -
* - It does not like the INQUIRY command. So we must handle this command
@@ -1241,6 +1316,12 @@ UNUSUAL_DEV( 0x0af0, 0xd357, 0x0000, 0x0000,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
0 ),
+/* Reported by Namjae Jeon <namjae.jeon@samsung.com> */
+UNUSUAL_DEV(0x0bc2, 0x2300, 0x0000, 0x9999,
+ "Seagate",
+ "Portable HDD",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_WRITE_CACHE),
+
/* Reported by Ben Efros <ben@pc-doctor.com> */
UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000,
"Seagate",
@@ -1381,6 +1462,20 @@ UNUSUAL_DEV( 0x0f19, 0x0105, 0x0100, 0x0100,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Submitted by Nick Holloway */
+UNUSUAL_DEV( 0x0f88, 0x042e, 0x0100, 0x0100,
+ "VTech",
+ "Kidizoom",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
+/* Reported by Moritz Moeller-Herrmann <moritz-kernel@moeller-herrmann.de> */
+UNUSUAL_DEV( 0x0fca, 0x8004, 0x0201, 0x0201,
+ "Research In Motion",
+ "BlackBerry Bold 9000",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_MAX_SECTORS_64 ),
+
/* Reported by Michael Stattmann <michael@stattmann.com> */
UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000,
"Sony Ericsson",
@@ -1435,6 +1530,12 @@ UNUSUAL_DEV( 0x1058, 0x0704, 0x0000, 0x9999,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_SANE_SENSE),
+/* Reported by Namjae Jeon <namjae.jeon@samsung.com> */
+UNUSUAL_DEV(0x1058, 0x070a, 0x0000, 0x9999,
+ "Western Digital",
+ "My Passport HDD",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_WRITE_CACHE),
+
/* Reported by Fabio Venturi <f.venturi@tdnet.it>
* The device reports a vendor-specific bDeviceClass.
*/
@@ -1821,6 +1922,13 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Qinglin Ye <yestyle@gmail.com> */
+UNUSUAL_DEV( 0x13fe, 0x3600, 0x0100, 0x0100,
+ "Kingston",
+ "DT 101 G2",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_BULK_IGNORE_TAG ),
+
/* Reported by Francesco Foresti <frafore@tiscali.it> */
UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201,
"Super Top",
@@ -1828,6 +1936,13 @@ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Michael Büsch <m@bues.ch> */
+UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0114,
+ "JMicron",
+ "USB to ATA/ATAPI Bridge",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_BROKEN_FUA ),
+
/* Reported by Alexandre Oliva <oliva@lsd.ic.unicamp.br>
* JMicron responds to USN and several other SCSI ioctls with a
* residue that causes subsequent I/O requests to fail. */
@@ -1845,6 +1960,20 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Oliver Neukum <oneukum@suse.com> */
+UNUSUAL_DEV( 0x174c, 0x55aa, 0x0100, 0x0100,
+ "ASMedia",
+ "AS2105",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_NEEDS_CAP16),
+
+/* Reported by Jesse Feddema <jdfeddema@gmail.com> */
+UNUSUAL_DEV( 0x177f, 0x0400, 0x0000, 0x0000,
+ "Yarvik",
+ "PMP400",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ),
+
/* Reported by Hans de Goede <hdegoede@redhat.com>
* These Appotech controllers are found in Picture Frames, they provide a
* (buggy) emulation of a cdrom drive which contains the windows software
@@ -1865,6 +1994,31 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_NO_READ_DISC_INFO ),
+/* Reported by Sven Geggus <sven-usbst@geggus.net>
+ * This encrypted pen drive returns bogus data for the initial READ(10).
+ */
+UNUSUAL_DEV( 0x1b1c, 0x1ab5, 0x0200, 0x0200,
+ "Corsair",
+ "Padlock v2",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_INITIAL_READ10 ),
+
+/* Patch by Richard Schütz <r.schtz@t-online.de>
+ * This external hard drive enclosure uses a JMicron chip which
+ * needs the US_FL_IGNORE_RESIDUE flag to work properly. */
+UNUSUAL_DEV( 0x1e68, 0x001b, 0x0000, 0x0000,
+ "TrekStor GmbH & Co. KG",
+ "DataStation maxi g.u",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ),
+
+/* Reported by Jasper Mackenzie <scarletpimpernal@hotmail.com> */
+UNUSUAL_DEV( 0x1e74, 0x4621, 0x0000, 0x0000,
+ "Coby Electronics",
+ "MP3 Player",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ),
+
UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001,
"ST",
"2A",
@@ -1930,6 +2084,16 @@ UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100,
"Micro Mini 1GB",
USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+/*
+ * Nick Bowler <nbowler@elliptictech.com>
+ * SCSI stack spams (otherwise harmless) error messages.
+ */
+UNUSUAL_DEV( 0xc251, 0x4003, 0x0100, 0x0100,
+ "Keil Software, Inc.",
+ "V2M MotherBoard",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_NOT_LOCKABLE),
+
/* Reported by Andrew Simmons <andrew.simmons@gmail.com> */
UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001,
"DataStor",
@@ -1943,26 +2107,31 @@ UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001,
"Digital MP3 Audio Player",
USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+/* Unusual uas devices */
+#if IS_ENABLED(CONFIG_USB_UAS)
+#include "unusual_uas.h"
+#endif
+
/* Control/Bulk transport for all SubClass values */
-USUAL_DEV(USB_SC_RBC, USB_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_8020, USB_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_QIC, USB_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_UFI, USB_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_8070, USB_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_SCSI, USB_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_RBC, USB_PR_CB),
+USUAL_DEV(USB_SC_8020, USB_PR_CB),
+USUAL_DEV(USB_SC_QIC, USB_PR_CB),
+USUAL_DEV(USB_SC_UFI, USB_PR_CB),
+USUAL_DEV(USB_SC_8070, USB_PR_CB),
+USUAL_DEV(USB_SC_SCSI, USB_PR_CB),
/* Control/Bulk/Interrupt transport for all SubClass values */
-USUAL_DEV(USB_SC_RBC, USB_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_8020, USB_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_QIC, USB_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_UFI, USB_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_8070, USB_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_SCSI, USB_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_RBC, USB_PR_CBI),
+USUAL_DEV(USB_SC_8020, USB_PR_CBI),
+USUAL_DEV(USB_SC_QIC, USB_PR_CBI),
+USUAL_DEV(USB_SC_UFI, USB_PR_CBI),
+USUAL_DEV(USB_SC_8070, USB_PR_CBI),
+USUAL_DEV(USB_SC_SCSI, USB_PR_CBI),
/* Bulk-only transport for all SubClass values */
-USUAL_DEV(USB_SC_RBC, USB_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_8020, USB_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_QIC, USB_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_UFI, USB_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_8070, USB_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0),
+USUAL_DEV(USB_SC_RBC, USB_PR_BULK),
+USUAL_DEV(USB_SC_8020, USB_PR_BULK),
+USUAL_DEV(USB_SC_QIC, USB_PR_BULK),
+USUAL_DEV(USB_SC_UFI, USB_PR_BULK),
+USUAL_DEV(USB_SC_8070, USB_PR_BULK),
+USUAL_DEV(USB_SC_SCSI, USB_PR_BULK),
diff --git a/drivers/usb/storage/unusual_ene_ub6250.h b/drivers/usb/storage/unusual_ene_ub6250.h
new file mode 100644
index 00000000000..5667f5d365c
--- /dev/null
+++ b/drivers/usb/storage/unusual_ene_ub6250.h
@@ -0,0 +1,26 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(CONFIG_USB_STORAGE_ENE_UB6250) || \
+ defined(CONFIG_USB_STORAGE_ENE_UB6250_MODULE)
+
+UNUSUAL_DEV(0x0cf2, 0x6250, 0x0000, 0x9999,
+ "ENE",
+ "ENE UB6250 reader",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0),
+
+#endif /* defined(CONFIG_USB_STORAGE_ENE_UB6250) || ... */
diff --git a/drivers/usb/storage/unusual_realtek.h b/drivers/usb/storage/unusual_realtek.h
new file mode 100644
index 00000000000..e41f50c95ed
--- /dev/null
+++ b/drivers/usb/storage/unusual_realtek.h
@@ -0,0 +1,41 @@
+/* Driver for Realtek RTS51xx USB card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ * wwang (wei_wang@realsil.com.cn)
+ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#if defined(CONFIG_USB_STORAGE_REALTEK) || \
+ defined(CONFIG_USB_STORAGE_REALTEK_MODULE)
+
+UNUSUAL_DEV(0x0bda, 0x0138, 0x0000, 0x9999,
+ "Realtek",
+ "USB Card Reader",
+ USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+
+UNUSUAL_DEV(0x0bda, 0x0158, 0x0000, 0x9999,
+ "Realtek",
+ "USB Card Reader",
+ USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+
+UNUSUAL_DEV(0x0bda, 0x0159, 0x0000, 0x9999,
+ "Realtek",
+ "USB Card Reader",
+ USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+
+#endif /* defined(CONFIG_USB_STORAGE_REALTEK) || ... */
diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h
new file mode 100644
index 00000000000..7244444df8e
--- /dev/null
+++ b/drivers/usb/storage/unusual_uas.h
@@ -0,0 +1,52 @@
+/* Driver for USB Attached SCSI devices - Unusual Devices File
+ *
+ * (c) 2013 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on the same file for the usb-storage driver, which is:
+ * (c) 2000-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ * (c) 2000 Adam J. Richter (adam@yggdrasil.com), Yggdrasil Computing, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * IMPORTANT NOTE: This file must be included in another file which defines
+ * a UNUSUAL_DEV macro before this file is included.
+ */
+
+/*
+ * If you edit this file, please try to keep it sorted first by VendorID,
+ * then by ProductID.
+ *
+ * If you want to add an entry for this file, be sure to include the
+ * following information:
+ * - a patch that adds the entry for your device, including your
+ * email address right above the entry (plus maybe a brief
+ * explanation of the reason for the entry),
+ * - lsusb -v output for the device
+ * Send your submission to Hans de Goede <hdegoede@redhat.com>
+ * and don't forget to CC: the USB development list <linux-usb@vger.kernel.org>
+ */
+
+/*
+ * This is an example entry for the US_FL_IGNORE_UAS flag. Once we have an
+ * actual entry using US_FL_IGNORE_UAS this entry should be removed.
+ *
+ * UNUSUAL_DEV( 0xabcd, 0x1234, 0x0100, 0x0100,
+ * "Example",
+ * "Storage with broken UAS",
+ * USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ * US_FL_IGNORE_UAS),
+ */
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 4219c197cb0..f1c96261a50 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -53,7 +53,6 @@
#include <linux/errno.h>
#include <linux/freezer.h>
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
@@ -73,6 +72,10 @@
#include "sierra_ms.h"
#include "option_ms.h"
+#if IS_ENABLED(CONFIG_USB_UAS)
+#include "uas-detect.h"
+#endif
+
/* Some informational data */
MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
MODULE_DESCRIPTION("USB Mass Storage driver for Linux");
@@ -114,21 +117,65 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
#define COMPLIANT_DEV UNUSUAL_DEV
-#define USUAL_DEV(use_protocol, use_transport, use_type) \
+#define USUAL_DEV(use_protocol, use_transport) \
{ \
.useProtocol = use_protocol, \
.useTransport = use_transport, \
}
+#define UNUSUAL_VENDOR_INTF(idVendor, cl, sc, pr, \
+ vendor_name, product_name, use_protocol, use_transport, \
+ init_function, Flags) \
+{ \
+ .vendorName = vendor_name, \
+ .productName = product_name, \
+ .useProtocol = use_protocol, \
+ .useTransport = use_transport, \
+ .initFunction = init_function, \
+}
+
static struct us_unusual_dev us_unusual_dev_list[] = {
-# include "unusual_devs.h"
+# include "unusual_devs.h"
{ } /* Terminating entry */
};
+static struct us_unusual_dev for_dynamic_ids =
+ USUAL_DEV(USB_SC_SCSI, USB_PR_BULK);
+
#undef UNUSUAL_DEV
#undef COMPLIANT_DEV
#undef USUAL_DEV
+#undef UNUSUAL_VENDOR_INTF
+
+#ifdef CONFIG_LOCKDEP
+
+static struct lock_class_key us_interface_key[USB_MAXINTERFACES];
+
+static void us_set_lock_class(struct mutex *mutex,
+ struct usb_interface *intf)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_host_config *config = udev->actconfig;
+ int i;
+
+ for (i = 0; i < config->desc.bNumInterfaces; i++) {
+ if (config->interface[i] == intf)
+ break;
+ }
+
+ BUG_ON(i == config->desc.bNumInterfaces);
+
+ lockdep_set_class(mutex, &us_interface_key[i]);
+}
+
+#else
+
+static void us_set_lock_class(struct mutex *mutex,
+ struct usb_interface *intf)
+{
+}
+#endif
#ifdef CONFIG_PM /* Minimal support for suspend and resume */
@@ -139,7 +186,6 @@ int usb_stor_suspend(struct usb_interface *iface, pm_message_t message)
/* Wait until no command is running */
mutex_lock(&us->dev_mutex);
- US_DEBUGP("%s\n", __func__);
if (us->suspend_resume_hook)
(us->suspend_resume_hook)(us, US_SUSPEND);
@@ -157,7 +203,6 @@ int usb_stor_resume(struct usb_interface *iface)
mutex_lock(&us->dev_mutex);
- US_DEBUGP("%s\n", __func__);
if (us->suspend_resume_hook)
(us->suspend_resume_hook)(us, US_RESUME);
@@ -170,8 +215,6 @@ int usb_stor_reset_resume(struct usb_interface *iface)
{
struct us_data *us = usb_get_intfdata(iface);
- US_DEBUGP("%s\n", __func__);
-
/* Report the reset to the SCSI core */
usb_stor_report_bus_reset(us);
@@ -192,8 +235,6 @@ int usb_stor_pre_reset(struct usb_interface *iface)
{
struct us_data *us = usb_get_intfdata(iface);
- US_DEBUGP("%s\n", __func__);
-
/* Make sure no command runs during the reset */
mutex_lock(&us->dev_mutex);
return 0;
@@ -204,8 +245,6 @@ int usb_stor_post_reset(struct usb_interface *iface)
{
struct us_data *us = usb_get_intfdata(iface);
- US_DEBUGP("%s\n", __func__);
-
/* Report the reset to the SCSI core */
usb_stor_report_bus_reset(us);
@@ -229,17 +268,17 @@ EXPORT_SYMBOL_GPL(usb_stor_post_reset);
void fill_inquiry_response(struct us_data *us, unsigned char *data,
unsigned int data_len)
{
- if (data_len<36) // You lose.
+ if (data_len < 36) /* You lose. */
return;
memset(data+8, ' ', 28);
- if(data[0]&0x20) { /* USB device currently not connected. Return
+ if (data[0]&0x20) { /* USB device currently not connected. Return
peripheral qualifier 001b ("...however, the
physical device is not currently connected
to this logical unit") and leave vendor and
product identification empty. ("If the target
does store some of the INQUIRY data on the
- device, it may return zeros or ASCII spaces
+ device, it may return zeros or ASCII spaces
(20h) in those fields until the data is
available from the device."). */
} else {
@@ -266,12 +305,12 @@ static int usb_stor_control_thread(void * __us)
struct us_data *us = (struct us_data *)__us;
struct Scsi_Host *host = us_to_host(us);
- for(;;) {
- US_DEBUGP("*** thread sleeping.\n");
+ for (;;) {
+ usb_stor_dbg(us, "*** thread sleeping\n");
if (wait_for_completion_interruptible(&us->cmnd_ready))
break;
- US_DEBUGP("*** thread awakened.\n");
+ usb_stor_dbg(us, "*** thread awakened\n");
/* lock the device pointers */
mutex_lock(&(us->dev_mutex));
@@ -283,7 +322,7 @@ static int usb_stor_control_thread(void * __us)
if (us->srb == NULL) {
scsi_unlock(host);
mutex_unlock(&us->dev_mutex);
- US_DEBUGP("-- exiting\n");
+ usb_stor_dbg(us, "-- exiting\n");
break;
}
@@ -295,31 +334,31 @@ static int usb_stor_control_thread(void * __us)
scsi_unlock(host);
- /* reject the command if the direction indicator
+ /* reject the command if the direction indicator
* is UNKNOWN
*/
if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
- US_DEBUGP("UNKNOWN data direction\n");
+ usb_stor_dbg(us, "UNKNOWN data direction\n");
us->srb->result = DID_ERROR << 16;
}
/* reject if target != 0 or if LUN is higher than
* the maximum known LUN
*/
- else if (us->srb->device->id &&
+ else if (us->srb->device->id &&
!(us->fflags & US_FL_SCM_MULT_TARG)) {
- US_DEBUGP("Bad target number (%d:%d)\n",
- us->srb->device->id, us->srb->device->lun);
+ usb_stor_dbg(us, "Bad target number (%d:%d)\n",
+ us->srb->device->id, us->srb->device->lun);
us->srb->result = DID_BAD_TARGET << 16;
}
else if (us->srb->device->lun > us->max_lun) {
- US_DEBUGP("Bad LUN (%d:%d)\n",
- us->srb->device->id, us->srb->device->lun);
+ usb_stor_dbg(us, "Bad LUN (%d:%d)\n",
+ us->srb->device->id, us->srb->device->lun);
us->srb->result = DID_BAD_TARGET << 16;
}
- /* Handle those devices which need us to fake
+ /* Handle those devices which need us to fake
* their inquiry data */
else if ((us->srb->cmnd[0] == INQUIRY) &&
(us->fflags & US_FL_FIX_INQUIRY)) {
@@ -327,14 +366,14 @@ static int usb_stor_control_thread(void * __us)
0x00, 0x80, 0x02, 0x02,
0x1F, 0x00, 0x00, 0x00};
- US_DEBUGP("Faking INQUIRY command\n");
+ usb_stor_dbg(us, "Faking INQUIRY command\n");
fill_inquiry_response(us, data_ptr, 36);
us->srb->result = SAM_STAT_GOOD;
}
/* we've got a command, let's do it! */
else {
- US_DEBUG(usb_stor_show_command(us->srb));
+ US_DEBUG(usb_stor_show_command(us, us->srb));
us->proto_handler(us->srb, us);
usb_mark_last_busy(us->pusb_dev);
}
@@ -344,12 +383,12 @@ static int usb_stor_control_thread(void * __us)
/* indicate that the command is done */
if (us->srb->result != DID_ABORT << 16) {
- US_DEBUGP("scsi cmd done, result=0x%x\n",
- us->srb->result);
+ usb_stor_dbg(us, "scsi cmd done, result=0x%x\n",
+ us->srb->result);
us->srb->scsi_done(us->srb);
} else {
SkipForAbort:
- US_DEBUGP("scsi command aborted\n");
+ usb_stor_dbg(us, "scsi command aborted\n");
}
/* If an abort request was received we need to signal that
@@ -382,7 +421,7 @@ SkipForAbort:
}
__set_current_state(TASK_RUNNING);
return 0;
-}
+}
/***********************************************************************
* Device probing and disconnecting
@@ -391,34 +430,30 @@ SkipForAbort:
/* Associate our private data with the USB device */
static int associate_dev(struct us_data *us, struct usb_interface *intf)
{
- US_DEBUGP("-- %s\n", __func__);
-
/* Fill in the device-related fields */
us->pusb_dev = interface_to_usbdev(intf);
us->pusb_intf = intf;
us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
- US_DEBUGP("Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n",
- le16_to_cpu(us->pusb_dev->descriptor.idVendor),
- le16_to_cpu(us->pusb_dev->descriptor.idProduct),
- le16_to_cpu(us->pusb_dev->descriptor.bcdDevice));
- US_DEBUGP("Interface Subclass: 0x%02x, Protocol: 0x%02x\n",
- intf->cur_altsetting->desc.bInterfaceSubClass,
- intf->cur_altsetting->desc.bInterfaceProtocol);
+ usb_stor_dbg(us, "Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n",
+ le16_to_cpu(us->pusb_dev->descriptor.idVendor),
+ le16_to_cpu(us->pusb_dev->descriptor.idProduct),
+ le16_to_cpu(us->pusb_dev->descriptor.bcdDevice));
+ usb_stor_dbg(us, "Interface Subclass: 0x%02x, Protocol: 0x%02x\n",
+ intf->cur_altsetting->desc.bInterfaceSubClass,
+ intf->cur_altsetting->desc.bInterfaceProtocol);
/* Store our private data in the interface */
usb_set_intfdata(intf, us);
/* Allocate the control/setup and DMA-mapped buffers */
us->cr = kmalloc(sizeof(*us->cr), GFP_KERNEL);
- if (!us->cr) {
- US_DEBUGP("usb_ctrlrequest allocation failed\n");
+ if (!us->cr)
return -ENOMEM;
- }
us->iobuf = usb_alloc_coherent(us->pusb_dev, US_IOBUF_SIZE,
GFP_KERNEL, &us->iobuf_dma);
if (!us->iobuf) {
- US_DEBUGP("I/O buffer allocation failed\n");
+ usb_stor_dbg(us, "I/O buffer allocation failed\n");
return -ENOMEM;
}
return 0;
@@ -428,18 +463,20 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
#define TOLOWER(x) ((x) | 0x20)
/* Adjust device flags based on the "quirks=" module parameter */
-static void adjust_quirks(struct us_data *us)
+void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags)
{
char *p;
- u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor);
- u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
+ u16 vid = le16_to_cpu(udev->descriptor.idVendor);
+ u16 pid = le16_to_cpu(udev->descriptor.idProduct);
unsigned f = 0;
unsigned int mask = (US_FL_SANE_SENSE | US_FL_BAD_SENSE |
- US_FL_FIX_CAPACITY |
+ US_FL_FIX_CAPACITY | US_FL_IGNORE_UAS |
US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE |
US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |
- US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT);
+ US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT |
+ US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 |
+ US_FL_INITIAL_READ10 | US_FL_WRITE_CACHE);
p = quirks;
while (*p) {
@@ -471,6 +508,12 @@ static void adjust_quirks(struct us_data *us)
case 'c':
f |= US_FL_FIX_CAPACITY;
break;
+ case 'd':
+ f |= US_FL_NO_READ_DISC_INFO;
+ break;
+ case 'e':
+ f |= US_FL_NO_READ_CAPACITY_16;
+ break;
case 'h':
f |= US_FL_CAPACITY_HEURISTICS;
break;
@@ -483,23 +526,33 @@ static void adjust_quirks(struct us_data *us)
case 'm':
f |= US_FL_MAX_SECTORS_64;
break;
+ case 'n':
+ f |= US_FL_INITIAL_READ10;
+ break;
case 'o':
f |= US_FL_CAPACITY_OK;
break;
+ case 'p':
+ f |= US_FL_WRITE_CACHE;
+ break;
case 'r':
f |= US_FL_IGNORE_RESIDUE;
break;
case 's':
f |= US_FL_SINGLE_LUN;
break;
+ case 'u':
+ f |= US_FL_IGNORE_UAS;
+ break;
case 'w':
f |= US_FL_NO_WP_DETECT;
break;
/* Ignore unrecognized flag characters */
}
}
- us->fflags = (us->fflags & ~mask) | f;
+ *fflags = (*fflags & ~mask) | f;
}
+EXPORT_SYMBOL_GPL(usb_stor_adjust_quirks);
/* Get the unusual_devs entries and the string descriptors */
static int get_device_info(struct us_data *us, const struct usb_device_id *id,
@@ -518,8 +571,8 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id,
us->protocol = (unusual_dev->useTransport == USB_PR_DEVICE) ?
idesc->bInterfaceProtocol :
unusual_dev->useTransport;
- us->fflags = USB_US_ORIG_FLAGS(id->driver_info);
- adjust_quirks(us);
+ us->fflags = id->driver_info;
+ usb_stor_adjust_quirks(us->pusb_dev, &us->fflags);
if (us->fflags & US_FL_IGNORE_DEVICE) {
dev_info(pdev, "device ignored\n");
@@ -680,7 +733,7 @@ static int get_pipes(struct us_data *us)
}
if (!ep_in || !ep_out || (us->protocol == USB_PR_CBI && !ep_int)) {
- US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
+ usb_stor_dbg(us, "Endpoint sanity check failed! Rejecting dev.\n");
return -EIO;
}
@@ -689,7 +742,7 @@ static int get_pipes(struct us_data *us)
us->recv_ctrl_pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
us->send_bulk_pipe = usb_sndbulkpipe(us->pusb_dev,
usb_endpoint_num(ep_out));
- us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev,
+ us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev,
usb_endpoint_num(ep_in));
if (ep_int) {
us->recv_intr_pipe = usb_rcvintpipe(us->pusb_dev,
@@ -707,7 +760,7 @@ static int usb_stor_acquire_resources(struct us_data *us)
us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!us->current_urb) {
- US_DEBUGP("URB allocation failed\n");
+ usb_stor_dbg(us, "URB allocation failed\n");
return -ENOMEM;
}
@@ -734,20 +787,18 @@ static int usb_stor_acquire_resources(struct us_data *us)
/* Release all our dynamic resources */
static void usb_stor_release_resources(struct us_data *us)
{
- US_DEBUGP("-- %s\n", __func__);
-
/* Tell the control thread to exit. The SCSI host must
* already have been removed and the DISCONNECTING flag set
* so that we won't accept any more commands.
*/
- US_DEBUGP("-- sending exit command to thread\n");
+ usb_stor_dbg(us, "-- sending exit command to thread\n");
complete(&us->cmnd_ready);
if (us->ctl_thread)
kthread_stop(us->ctl_thread);
/* Call the destructor routine, if it exists */
if (us->extra_destructor) {
- US_DEBUGP("-- calling extra_destructor()\n");
+ usb_stor_dbg(us, "-- calling extra_destructor()\n");
us->extra_destructor(us->extra);
}
@@ -759,8 +810,6 @@ static void usb_stor_release_resources(struct us_data *us)
/* Dissociate from the USB device */
static void dissociate_dev(struct us_data *us)
{
- US_DEBUGP("-- %s\n", __func__);
-
/* Free the buffers */
kfree(us->cr);
usb_free_coherent(us->pusb_dev, US_IOBUF_SIZE, us->iobuf, us->iobuf_dma);
@@ -777,15 +826,19 @@ static void quiesce_and_remove_host(struct us_data *us)
struct Scsi_Host *host = us_to_host(us);
/* If the device is really gone, cut short reset delays */
- if (us->pusb_dev->state == USB_STATE_NOTATTACHED)
+ if (us->pusb_dev->state == USB_STATE_NOTATTACHED) {
set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+ wake_up(&us->delay_wait);
+ }
- /* Prevent SCSI-scanning (if it hasn't started yet)
- * and wait for the SCSI-scanning thread to stop.
+ /* Prevent SCSI scanning (if it hasn't started yet)
+ * or wait for the SCSI-scanning routine to stop.
*/
- set_bit(US_FLIDX_DONT_SCAN, &us->dflags);
- wake_up(&us->delay_wait);
- wait_for_completion(&us->scanning_done);
+ cancel_delayed_work_sync(&us->scan_dwork);
+
+ /* Balance autopm calls if scanning was cancelled */
+ if (test_bit(US_FLIDX_SCAN_PENDING, &us->dflags))
+ usb_autopm_put_interface_no_suspend(us->pusb_intf);
/* Removing the host will perform an orderly shutdown: caches
* synchronized, disks spun down, etc.
@@ -812,42 +865,28 @@ static void release_everything(struct us_data *us)
scsi_host_put(us_to_host(us));
}
-/* Thread to carry out delayed SCSI-device scanning */
-static int usb_stor_scan_thread(void * __us)
+/* Delayed-work routine to carry out SCSI-device scanning */
+static void usb_stor_scan_dwork(struct work_struct *work)
{
- struct us_data *us = (struct us_data *)__us;
+ struct us_data *us = container_of(work, struct us_data,
+ scan_dwork.work);
struct device *dev = &us->pusb_intf->dev;
- dev_dbg(dev, "device found\n");
+ dev_dbg(dev, "starting scan\n");
- set_freezable();
- /* Wait for the timeout to expire or for a disconnect */
- if (delay_use > 0) {
- dev_dbg(dev, "waiting for device to settle "
- "before scanning\n");
- wait_event_freezable_timeout(us->delay_wait,
- test_bit(US_FLIDX_DONT_SCAN, &us->dflags),
- delay_use * HZ);
+ /* For bulk-only devices, determine the max LUN value */
+ if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
+ mutex_lock(&us->dev_mutex);
+ us->max_lun = usb_stor_Bulk_max_lun(us);
+ mutex_unlock(&us->dev_mutex);
}
+ scsi_scan_host(us_to_host(us));
+ dev_dbg(dev, "scan complete\n");
- /* If the device is still connected, perform the scanning */
- if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
-
- /* For bulk-only devices, determine the max LUN value */
- if (us->protocol == USB_PR_BULK &&
- !(us->fflags & US_FL_SINGLE_LUN)) {
- mutex_lock(&us->dev_mutex);
- us->max_lun = usb_stor_Bulk_max_lun(us);
- mutex_unlock(&us->dev_mutex);
- }
- scsi_scan_host(us_to_host(us));
- dev_dbg(dev, "scan complete\n");
-
- /* Should we unbind if no devices were detected? */
- }
+ /* Should we unbind if no devices were detected? */
usb_autopm_put_interface(us->pusb_intf);
- complete_and_exit(&us->scanning_done, 0);
+ clear_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
}
static unsigned int usb_stor_sg_tablesize(struct usb_interface *intf)
@@ -870,7 +909,7 @@ int usb_stor_probe1(struct us_data **pus,
struct us_data *us;
int result;
- US_DEBUGP("USB Mass Storage device detected\n");
+ dev_info(&intf->dev, "USB Mass Storage device detected\n");
/*
* Ask the SCSI layer to allocate a host structure, with extra
@@ -878,8 +917,7 @@ int usb_stor_probe1(struct us_data **pus,
*/
host = scsi_host_alloc(&usb_stor_host_template, sizeof(*us));
if (!host) {
- dev_warn(&intf->dev,
- "Unable to allocate the scsi host\n");
+ dev_warn(&intf->dev, "Unable to allocate the scsi host\n");
return -ENOMEM;
}
@@ -889,12 +927,12 @@ int usb_stor_probe1(struct us_data **pus,
host->max_cmd_len = 16;
host->sg_tablesize = usb_stor_sg_tablesize(intf);
*pus = us = host_to_us(host);
- memset(us, 0, sizeof(struct us_data));
mutex_init(&(us->dev_mutex));
+ us_set_lock_class(&us->dev_mutex, intf);
init_completion(&us->cmnd_ready);
init_completion(&(us->notify));
init_waitqueue_head(&us->delay_wait);
- init_completion(&us->scanning_done);
+ INIT_DELAYED_WORK(&us->scan_dwork, usb_stor_scan_dwork);
/* Associate the us_data structure with the USB device */
result = associate_dev(us, intf);
@@ -916,7 +954,7 @@ int usb_stor_probe1(struct us_data **pus,
return 0;
BadDevice:
- US_DEBUGP("storage_probe() failed\n");
+ usb_stor_dbg(us, "storage_probe() failed\n");
release_everything(us);
return result;
}
@@ -925,7 +963,6 @@ EXPORT_SYMBOL_GPL(usb_stor_probe1);
/* Second part of general USB mass-storage probing */
int usb_stor_probe2(struct us_data *us)
{
- struct task_struct *th;
int result;
struct device *dev = &us->pusb_intf->dev;
@@ -934,18 +971,28 @@ int usb_stor_probe2(struct us_data *us)
result = -ENXIO;
goto BadDevice;
}
- US_DEBUGP("Transport: %s\n", us->transport_name);
- US_DEBUGP("Protocol: %s\n", us->protocol_name);
+ usb_stor_dbg(us, "Transport: %s\n", us->transport_name);
+ usb_stor_dbg(us, "Protocol: %s\n", us->protocol_name);
/* fix for single-lun devices */
if (us->fflags & US_FL_SINGLE_LUN)
us->max_lun = 0;
+ if (!(us->fflags & US_FL_SCM_MULT_TARG))
+ us_to_host(us)->max_id = 1;
+
/* Find the endpoints and calculate pipe values */
result = get_pipes(us);
if (result)
goto BadDevice;
+ /*
+ * If the device returns invalid data for the first READ(10)
+ * command, indicate the command should be retried.
+ */
+ if (us->fflags & US_FL_INITIAL_READ10)
+ set_bit(US_FLIDX_REDO_READ10, &us->dflags);
+
/* Acquire all the other resources and add the host */
result = usb_stor_acquire_resources(us);
if (result)
@@ -959,25 +1006,19 @@ int usb_stor_probe2(struct us_data *us)
goto BadDevice;
}
- /* Start up the thread for delayed SCSI-device scanning */
- th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
- if (IS_ERR(th)) {
- dev_warn(dev,
- "Unable to start the device-scanning thread\n");
- complete(&us->scanning_done);
- quiesce_and_remove_host(us);
- result = PTR_ERR(th);
- goto BadDevice;
- }
-
+ /* Submit the delayed_work for SCSI-device scanning */
usb_autopm_get_interface_no_resume(us->pusb_intf);
- wake_up_process(th);
+ set_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
+ if (delay_use > 0)
+ dev_dbg(dev, "waiting for device to settle before scanning\n");
+ queue_delayed_work(system_freezable_wq, &us->scan_dwork,
+ delay_use * HZ);
return 0;
/* We come here if there are any problems */
BadDevice:
- US_DEBUGP("storage_probe() failed\n");
+ usb_stor_dbg(us, "storage_probe() failed\n");
release_everything(us);
return result;
}
@@ -988,7 +1029,6 @@ void usb_stor_disconnect(struct usb_interface *intf)
{
struct us_data *us = usb_get_intfdata(intf);
- US_DEBUGP("storage_disconnect() called\n");
quiesce_and_remove_host(us);
release_everything(us);
}
@@ -998,17 +1038,22 @@ EXPORT_SYMBOL_GPL(usb_stor_disconnect);
static int storage_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
+ struct us_unusual_dev *unusual_dev;
struct us_data *us;
int result;
+ int size;
+
+ /* If uas is enabled and this device can do uas then ignore it. */
+#if IS_ENABLED(CONFIG_USB_UAS)
+ if (uas_use_uas_driver(intf, id))
+ return -ENXIO;
+#endif
/*
- * If libusual is configured, let it decide whether a standard
- * device should be handled by usb-storage or by ub.
* If the device isn't standard (is handled by a subdriver
* module) then don't accept it.
*/
- if (usb_usual_check_type(id, USB_US_TYPE_STOR) ||
- usb_usual_ignore_device(intf))
+ if (usb_usual_ignore_device(intf))
return -ENXIO;
/*
@@ -1018,8 +1063,18 @@ static int storage_probe(struct usb_interface *intf,
* table, so we use the index of the id entry to find the
* corresponding unusual_devs entry.
*/
- result = usb_stor_probe1(&us, intf, id,
- (id - usb_storage_usb_ids) + us_unusual_dev_list);
+
+ size = ARRAY_SIZE(us_unusual_dev_list);
+ if (id >= usb_storage_usb_ids && id < usb_storage_usb_ids + size) {
+ unusual_dev = (id - usb_storage_usb_ids) + us_unusual_dev_list;
+ } else {
+ unusual_dev = &for_dynamic_ids;
+
+ dev_dbg(&intf->dev, "Use Bulk-Only transport with the Transparent SCSI protocol for dynamic id: 0x%04x 0x%04x\n",
+ id->idVendor, id->idProduct);
+ }
+
+ result = usb_stor_probe1(&us, intf, id, unusual_dev);
if (result)
return result;
@@ -1029,10 +1084,6 @@ static int storage_probe(struct usb_interface *intf,
return result;
}
-/***********************************************************************
- * Initialization and registration
- ***********************************************************************/
-
static struct usb_driver usb_storage_driver = {
.name = "usb-storage",
.probe = storage_probe,
@@ -1047,34 +1098,4 @@ static struct usb_driver usb_storage_driver = {
.soft_unbind = 1,
};
-static int __init usb_stor_init(void)
-{
- int retval;
-
- pr_info("Initializing USB Mass Storage driver...\n");
-
- /* register the driver, return usb_register return code if error */
- retval = usb_register(&usb_storage_driver);
- if (retval == 0) {
- pr_info("USB Mass Storage support registered.\n");
- usb_usual_set_present(USB_US_TYPE_STOR);
- }
- return retval;
-}
-
-static void __exit usb_stor_exit(void)
-{
- US_DEBUGP("usb_stor_exit() called\n");
-
- /* Deregister the driver
- * This will cause disconnect() to be called for each
- * attached unit
- */
- US_DEBUGP("-- calling usb_deregister()\n");
- usb_deregister(&usb_storage_driver) ;
-
- usb_usual_clear_present(USB_US_TYPE_STOR);
-}
-
-module_init(usb_stor_init);
-module_exit(usb_stor_exit);
+module_usb_driver(usb_storage_driver);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 89d3bfff98d..307e339a947 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -47,6 +47,7 @@
#include <linux/blkdev.h>
#include <linux/completion.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#include <scsi/scsi_host.h>
struct us_data;
@@ -72,7 +73,9 @@ struct us_unusual_dev {
#define US_FLIDX_DISCONNECTING 3 /* disconnect in progress */
#define US_FLIDX_RESETTING 4 /* device reset in progress */
#define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */
-#define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */
+#define US_FLIDX_SCAN_PENDING 6 /* scanning not yet done */
+#define US_FLIDX_REDO_READ10 7 /* redo READ(10) command */
+#define US_FLIDX_READ10_WORKED 8 /* previous READ(10) succeeded */
#define USB_STOR_STRING_LEN 32
@@ -145,8 +148,8 @@ struct us_data {
/* mutual exclusion and synchronization structures */
struct completion cmnd_ready; /* to sleep thread on */
struct completion notify; /* thread begin/end */
- wait_queue_head_t delay_wait; /* wait during scan, reset */
- struct completion scanning_done; /* wait for scan thread */
+ wait_queue_head_t delay_wait; /* wait during reset */
+ struct delayed_work scan_dwork; /* for async scanning */
/* subdriver information */
void *extra; /* Any extra data */
@@ -198,4 +201,7 @@ extern int usb_stor_probe1(struct us_data **pus,
extern int usb_stor_probe2(struct us_data *us);
extern void usb_stor_disconnect(struct usb_interface *intf);
+extern void usb_stor_adjust_quirks(struct usb_device *dev,
+ unsigned long *fflags);
+
#endif
diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
index 468bde7d197..5ef8ce74aae 100644
--- a/drivers/usb/storage/usual-tables.c
+++ b/drivers/usb/storage/usual-tables.c
@@ -34,30 +34,37 @@
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
- .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
-
-#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
- vendorName, productName, useProtocol, useTransport, \
- initFunction, flags) \
-{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
.driver_info = (flags) }
-#define USUAL_DEV(useProto, useTrans, useType) \
-{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
- .driver_info = ((useType)<<24) }
+#define COMPLIANT_DEV UNUSUAL_DEV
+
+#define USUAL_DEV(useProto, useTrans) \
+{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans) }
+
+/* Define the device is matched with Vendor ID and interface descriptors */
+#define UNUSUAL_VENDOR_INTF(id_vendor, cl, sc, pr, \
+ vendorName, productName, useProtocol, useTransport, \
+ initFunction, flags) \
+{ \
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
+ | USB_DEVICE_ID_MATCH_VENDOR, \
+ .idVendor = (id_vendor), \
+ .bInterfaceClass = (cl), \
+ .bInterfaceSubClass = (sc), \
+ .bInterfaceProtocol = (pr), \
+ .driver_info = (flags) \
+}
struct usb_device_id usb_storage_usb_ids[] = {
# include "unusual_devs.h"
{ } /* Terminating entry */
};
-EXPORT_SYMBOL_GPL(usb_storage_usb_ids);
-
MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids);
#undef UNUSUAL_DEV
#undef COMPLIANT_DEV
#undef USUAL_DEV
-
+#undef UNUSUAL_VENDOR_INTF
/*
* The table of devices to ignore
@@ -80,11 +87,13 @@ static struct ignore_entry ignore_ids[] = {
# include "unusual_alauda.h"
# include "unusual_cypress.h"
# include "unusual_datafab.h"
+# include "unusual_ene_ub6250.h"
# include "unusual_freecom.h"
# include "unusual_isd200.h"
# include "unusual_jumpshot.h"
# include "unusual_karma.h"
# include "unusual_onetouch.h"
+# include "unusual_realtek.h"
# include "unusual_sddr09.h"
# include "unusual_sddr55.h"
# include "unusual_usbat.h"
@@ -93,7 +102,6 @@ static struct ignore_entry ignore_ids[] = {
#undef UNUSUAL_DEV
-
/* Return an error if a device is in the ignore_ids list */
int usb_usual_ignore_device(struct usb_interface *intf)
{
@@ -113,4 +121,3 @@ int usb_usual_ignore_device(struct usb_interface *intf)
}
return 0;
}
-EXPORT_SYMBOL_GPL(usb_usual_ignore_device);