From 141804d401631f0384feabfa5fc3e2ce1321c0f0 Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Tue, 2 May 2006 18:30:12 +0100 Subject: [PATCH] USB: shuttle_usbat: Fix handling of scatter-gather buffers I've worked out what's going wrong. The scsi layer is now much more likely to pass down scatterlists instead of plain buffers. So you have to make sure that they're handled correctly. In one of the changes along the way, usbat_write_block and friends stopped obeying the srb->use_sg flag. Anyway, with the appended patch, and the one I'm putting in the next email, it all seems to work for the HP cd4e. Of course, someone's going to have to test it with the flash drives as well.... This patch teaches the usbat_{read,write}_block functions to obey the use_sg flag in the scsi-request. Signed-off-by: Peter Chubb Signed-off-by: Daniel Drake Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/shuttle_usbat.c | 54 ++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 24 deletions(-) (limited to 'drivers/usb/storage/shuttle_usbat.c') diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index f2bc5c9e23d..92095b858eb 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -131,28 +131,30 @@ static int usbat_write(struct us_data *us, * Convenience function to perform a bulk read */ static int usbat_bulk_read(struct us_data *us, - unsigned char *data, - unsigned int len) + unsigned char *data, + unsigned int len, + int use_sg) { if (len == 0) return USB_STOR_XFER_GOOD; US_DEBUGP("usbat_bulk_read: len = %d\n", len); - return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, data, len, NULL); + return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, data, len, use_sg, NULL); } /* * Convenience function to perform a bulk write */ static int usbat_bulk_write(struct us_data *us, - unsigned char *data, - unsigned int len) + unsigned char *data, + unsigned int len, + int use_sg) { if (len == 0) return USB_STOR_XFER_GOOD; US_DEBUGP("usbat_bulk_write: len = %d\n", len); - return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, data, len, NULL); + return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, data, len, use_sg, NULL); } /* @@ -317,7 +319,8 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes) */ static int usbat_read_block(struct us_data *us, unsigned char *content, - unsigned short len) + unsigned short len, + int use_sg) { int result; unsigned char *command = us->iobuf; @@ -338,7 +341,7 @@ static int usbat_read_block(struct us_data *us, if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - result = usbat_bulk_read(us, content, len); + result = usbat_bulk_read(us, content, len, use_sg); return (result == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); } @@ -350,7 +353,8 @@ static int usbat_write_block(struct us_data *us, unsigned char access, unsigned char *content, unsigned short len, - int minutes) + int minutes, + int use_sg) { int result; unsigned char *command = us->iobuf; @@ -372,7 +376,7 @@ static int usbat_write_block(struct us_data *us, if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - result = usbat_bulk_write(us, content, len); + result = usbat_bulk_write(us, content, len, use_sg); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -465,7 +469,7 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us, data[1+(j<<1)] = data_out[j]; } - result = usbat_bulk_write(us, data, num_registers*2); + result = usbat_bulk_write(us, data, num_registers*2, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -583,7 +587,7 @@ static int usbat_multiple_write(struct us_data *us, } /* Send the data */ - result = usbat_bulk_write(us, data, num_registers*2); + result = usbat_bulk_write(us, data, num_registers*2, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -606,8 +610,9 @@ static int usbat_multiple_write(struct us_data *us, * other related details) are defined beforehand with _set_shuttle_features(). */ static int usbat_read_blocks(struct us_data *us, - unsigned char *buffer, - int len) + unsigned char *buffer, + int len, + int use_sg) { int result; unsigned char *command = us->iobuf; @@ -627,7 +632,7 @@ static int usbat_read_blocks(struct us_data *us, return USB_STOR_TRANSPORT_FAILED; /* Read the blocks we just asked for */ - result = usbat_bulk_read(us, buffer, len); + result = usbat_bulk_read(us, buffer, len, use_sg); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_FAILED; @@ -648,7 +653,8 @@ static int usbat_read_blocks(struct us_data *us, */ static int usbat_write_blocks(struct us_data *us, unsigned char *buffer, - int len) + int len, + int use_sg) { int result; unsigned char *command = us->iobuf; @@ -668,7 +674,7 @@ static int usbat_write_blocks(struct us_data *us, return USB_STOR_TRANSPORT_FAILED; /* Write the data */ - result = usbat_bulk_write(us, buffer, len); + result = usbat_bulk_write(us, buffer, len, use_sg); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_FAILED; @@ -947,7 +953,7 @@ static int usbat_flash_get_sector_count(struct us_data *us, msleep(100); /* Read the device identification data */ - rc = usbat_read_block(us, reply, 512); + rc = usbat_read_block(us, reply, 512, 0); if (rc != USB_STOR_TRANSPORT_GOOD) goto leave; @@ -1031,7 +1037,7 @@ static int usbat_flash_read_data(struct us_data *us, goto leave; /* Read the data we just requested */ - result = usbat_read_blocks(us, buffer, len); + result = usbat_read_blocks(us, buffer, len, 0); if (result != USB_STOR_TRANSPORT_GOOD) goto leave; @@ -1125,7 +1131,7 @@ static int usbat_flash_write_data(struct us_data *us, goto leave; /* Write the data */ - result = usbat_write_blocks(us, buffer, len); + result = usbat_write_blocks(us, buffer, len, 0); if (result != USB_STOR_TRANSPORT_GOOD) goto leave; @@ -1503,10 +1509,10 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) * AT SPEED 4 IS UNRELIABLE!!! */ - if ( (result = usbat_write_block(us, + if ((result = usbat_write_block(us, USBAT_ATA, srb->cmnd, 12, - srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) != - USB_STOR_TRANSPORT_GOOD) { + (srb->cmnd[0]==GPCMD_BLANK ? 75 : 10), 0) != + USB_STOR_TRANSPORT_GOOD)) { return result; } @@ -1533,7 +1539,7 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) len = *status; - result = usbat_read_block(us, srb->request_buffer, len); + result = usbat_read_block(us, srb->request_buffer, len, srb->use_sg); /* Debug-print the first 32 bytes of the transfer */ -- cgit v1.2.3-70-g09d2 From bdcfd9e349eff9398a1d85eaa517294f493bb3c8 Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Tue, 2 May 2006 18:29:34 +0100 Subject: [PATCH] USB: shuttle_usbat: Hardcode detection of HP CDRW devices Use USB vendor and product IDs to determine whether the attached device is a CDROM or a Flash device. Daniel Drake says that the *same* vendor and product IDs for non-HP vendor ID could be either flash or cdrom, so try to probe for them. Signed-off-by: Peter Chubb Signed-off-by: Daniel Drake Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/shuttle_usbat.c | 51 ++++++++++++++++++++++++++----------- drivers/usb/storage/shuttle_usbat.h | 4 ++- drivers/usb/storage/unusual_devs.h | 8 +++--- 3 files changed, 43 insertions(+), 20 deletions(-) (limited to 'drivers/usb/storage/shuttle_usbat.c') diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index 92095b858eb..8fcec01dc62 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -893,22 +893,28 @@ static int usbat_identify_device(struct us_data *us, * Set the transport function based on the device type */ static int usbat_set_transport(struct us_data *us, - struct usbat_info *info) + struct usbat_info *info, + int devicetype) { - int rc; - if (!info->devicetype) { - rc = usbat_identify_device(us, info); - if (rc != USB_STOR_TRANSPORT_GOOD) { - US_DEBUGP("usbat_set_transport: Could not identify device\n"); - return 1; - } - } + if (!info->devicetype) + info->devicetype = devicetype; - if (usbat_get_device_type(us) == USBAT_DEV_HP8200) + if (!info->devicetype) + usbat_identify_device(us, info); + + switch (info->devicetype) { + default: + return USB_STOR_TRANSPORT_ERROR; + + case USBAT_DEV_HP8200: us->transport = usbat_hp8200e_transport; - else if (usbat_get_device_type(us) == USBAT_DEV_FLASH) + break; + + case USBAT_DEV_FLASH: us->transport = usbat_flash_transport; + break; + } return 0; } @@ -1316,7 +1322,7 @@ static int usbat_select_and_test_registers(struct us_data *us) /* * Initialize the USBAT processor and the storage device */ -int init_usbat(struct us_data *us) +static int init_usbat(struct us_data *us, int devicetype) { int rc; struct usbat_info *info; @@ -1398,7 +1404,7 @@ int init_usbat(struct us_data *us) US_DEBUGP("INIT 9\n"); /* At this point, we need to detect which device we are using */ - if (usbat_set_transport(us, info)) + if (usbat_set_transport(us, info, devicetype)) return USB_STOR_TRANSPORT_ERROR; US_DEBUGP("INIT 10\n"); @@ -1701,6 +1707,22 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; } +int init_usbat_cd(struct us_data *us) +{ + return init_usbat(us, USBAT_DEV_HP8200); +} + + +int init_usbat_flash(struct us_data *us) +{ + return init_usbat(us, USBAT_DEV_FLASH); +} + +int init_usbat_probe(struct us_data *us) +{ + return init_usbat(us, 0); +} + /* * Default transport function. Attempts to detect which transport function * should be called, makes it the new default, and calls it. @@ -1714,9 +1736,8 @@ int usbat_transport(struct scsi_cmnd *srb, struct us_data *us) { struct usbat_info *info = (struct usbat_info*) (us->extra); - if (usbat_set_transport(us, info)) + if (usbat_set_transport(us, info, 0)) return USB_STOR_TRANSPORT_ERROR; return us->transport(srb, us); } - diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h index 25e7d8b340b..3ddf143a1de 100644 --- a/drivers/usb/storage/shuttle_usbat.h +++ b/drivers/usb/storage/shuttle_usbat.h @@ -106,7 +106,9 @@ #define USBAT_FEAT_ET2 0x01 extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int init_usbat(struct us_data *us); +extern int init_usbat_cd(struct us_data *us); +extern int init_usbat_flash(struct us_data *us); +extern int init_usbat_probe(struct us_data *us); struct usbat_info { int devicetype; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index aec5ea8682d..f24fa12eaed 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -78,12 +78,12 @@ UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, "HP", "CD-Writer+ 8200e", - US_SC_8070, US_PR_USBAT, init_usbat, 0), + US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, "HP", "CD-Writer+ CD-4e", - US_SC_8070, US_PR_USBAT, init_usbat, 0), + US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), #endif /* Reported by Sebastian Kapfer @@ -393,7 +393,7 @@ UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100, UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, "Shuttle/SCM", "USBAT-02", - US_SC_SCSI, US_PR_USBAT, init_usbat, + US_SC_SCSI, US_PR_USBAT, init_usbat_probe, US_FL_SINGLE_LUN), #endif @@ -797,7 +797,7 @@ UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, "Sandisk", "ImageMate SDDR-05b", - US_SC_SCSI, US_PR_USBAT, init_usbat, + US_SC_SCSI, US_PR_USBAT, init_usbat_flash, US_FL_SINGLE_LUN ), #endif -- cgit v1.2.3-70-g09d2