# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.539   -> 1.540  
#	drivers/usb/storage/shuttle_usbat.c	1.7     -> 1.8    
#	drivers/usb/storage/protocol.c	1.6     -> 1.7    
#	drivers/usb/storage/jumpshot.c	1.8     -> 1.9    
#	drivers/usb/storage/debug.c	1.7     -> 1.8    
#	drivers/usb/storage/usb.c	1.16    -> 1.17   
#	drivers/usb/storage/transport.c	1.15    -> 1.16   
#	drivers/usb/storage/transport.h	1.6     -> 1.7    
#	drivers/usb/storage/freecom.c	1.10    -> 1.11   
#	drivers/usb/storage/isd200.c	1.7     -> 1.8    
#	drivers/usb/storage/scsiglue.c	1.16    -> 1.17   
#	drivers/usb/storage/usb.h	1.6     -> 1.7    
#	drivers/usb/storage/unusual_devs.h	1.11    -> 1.12   
#	drivers/usb/storage/sddr09.c	1.13    -> 1.14   
#	drivers/usb/storage/datafab.c	1.7     -> 1.8    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/05/11	greg@kroah.com	1.540
# USB storage
# 
# sync up with both the -dj and cvs version of the usb-storage code.
# --------------------------------------------
#
diff -Nru a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
--- a/drivers/usb/storage/datafab.c	Sat May 11 22:29:15 2002
+++ b/drivers/usb/storage/datafab.c	Sat May 11 22:29:15 2002
@@ -1,16 +1,25 @@
 /* Driver for Datafab USB Compact Flash reader
  *
+ * $Id: datafab.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $
+ *
  * datafab driver v0.1:
  *
  * First release
  *
  * Current development and maintenance by:
  *   (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org)
- *   many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
+ *
+ *   Many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
  *   which I used as a template for this driver.
+ *
  *   Some bugfixes and scatter-gather code by Gregory P. Smith 
  *   (greg-usb@electricrain.com)
  *
+ *   Fix for media change by Joerg Schneider (js@joergschneider.com)
+ *
+ * Other contributors:
+ *   (c) 2002 Alan Stern <stern@rowland.org>
+ *
  * 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
@@ -102,7 +111,7 @@
 	if (result == -EPIPE) {
 		US_DEBUGP("datafab_raw_bulk: EPIPE. clearing endpoint halt for"
 			  " pipe 0x%x, stalled at %d bytes\n", pipe, act_len);
-		usb_clear_halt(us->pusb_dev, pipe);
+		usb_stor_clear_halt(us, pipe);
 	}
 
 	if (result) {
@@ -800,6 +809,23 @@
 		//
 		return USB_STOR_TRANSPORT_GOOD;
 	}
+
+	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");
+		/* the first datafab_id_device after a media change returns
+		   an error (determined experimentally) */
+		rc = datafab_id_device(us, info);
+		if (rc == USB_STOR_TRANSPORT_GOOD) {
+			info->sense_key = NO_SENSE;
+			srb->result = SUCCESS;
+		} else {
+			info->sense_key = UNIT_ATTENTION;
+			srb->result = CHECK_CONDITION;
+		}
+		return rc;
+        }
 
 	US_DEBUGP("datafab_transport:  Gah! Unknown command: %d (0x%x)\n", srb->cmnd[0], srb->cmnd[0]);
 	return USB_STOR_TRANSPORT_ERROR;
diff -Nru a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
--- a/drivers/usb/storage/debug.c	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/debug.c	Sat May 11 22:29:14 2002
@@ -1,10 +1,13 @@
 /* Driver for USB Mass Storage compliant devices
  * Debugging Functions Source Code File
  *
- * $Id: debug.c,v 1.5 2001/06/27 23:20:45 mdharm Exp $
+ * $Id: debug.c,v 1.9 2002/04/22 03:39:43 mdharm Exp $
  *
  * Current development and maintenance by:
- *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ *
+ * Developed with the assistance of:
+ *   (c) 2002 Alan Stern <stern@rowland.org>
  *
  * Initial work by:
  *   (c) 1999 Michael Gee (michael@linuxspecific.com)
@@ -302,9 +305,11 @@
 	case 0x1902: what="defect list error in primary list"; break;
 	case 0x1903: what="defect list error in grown list"; break;
 	case 0x1C00: what="defect list not found"; break;
+	case 0x2000: what="invalid command operation code"; break;
 	case 0x2400: what="invalid field in CDB"; break;
 	case 0x2703: what="associated write protect"; break;
 	case 0x2800: what="not ready to ready transition"; break;
+	case 0x2900: what="device reset occurred"; break;
 	case 0x2903: what="bus device reset function occurred"; break;
 	case 0x2904: what="device internal reset"; break;
 	case 0x2B00: what="copy can't execute / host can't disconnect"; break;
@@ -327,7 +332,7 @@
 	case 0x3502: what="enclosure services unavailable"; break;
 	case 0x3503: what="enclosure services transfer failure"; break;
 	case 0x3504: what="enclosure services transfer refused"; break;
-	case 0x3A00: what="medium not present"; break;
+	case 0x3A00: what="media not present"; break;
 	case 0x3B0F: what="end of medium reached"; break;
 	case 0x3F02: what="changed operating definition"; break;
 	case 0x4100: what="data path failure (should use 40 NN)"; break;
diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
--- a/drivers/usb/storage/freecom.c	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/freecom.c	Sat May 11 22:29:14 2002
@@ -1,6 +1,6 @@
 /* Driver for Freecom USB/IDE adaptor
  *
- * $Id: freecom.c,v 1.21 2001/12/29 03:47:33 mdharm Exp $
+ * $Id: freecom.c,v 1.22 2002/04/22 03:39:43 mdharm Exp $
  *
  * Freecom v0.1:
  *
diff -Nru a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
--- a/drivers/usb/storage/isd200.c	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/isd200.c	Sat May 11 22:29:14 2002
@@ -1,9 +1,15 @@
 /* Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC
  *
- * First release
+ * $Id: isd200.c,v 1.16 2002/04/22 03:39:43 mdharm Exp $
  *
- * Current development and maintenance by:
- *   (c) 2000 In-System Design, Inc. (support@in-system.com)
+ * Current development and maintenance:
+ *   (C) 2001-2002 Björn Stenberg (bjorn@haxx.se)
+ *
+ * Developed with the assistance of:
+ *   (C) 2002 Alan Stern <stern@rowland.org>
+ *
+ * Initial work:
+ *   (C) 2000 In-System Design, Inc. (support@in-system.com)
  *
  * The ISD200 ASIC does not natively support ATA devices.  The chip
  * does implement an interface, the ATA Command Block (ATACB) which provides
@@ -27,6 +33,10 @@
  *
  *  2001-02-24: Removed lots of duplicate code and simplified the structure.
  *              (bjorn@haxx.se)
+ *  2002-01-16: Fixed endianness bug so it works on the ppc arch.
+ *              (Luc Saillard <luc@saillard.org>)
+ *  2002-01-17: All bitfields removed.
+ *              (bjorn@haxx.se)
  */
 
 
@@ -45,15 +55,6 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 
-/*
- * Inquiry defines. Used to interpret data returned from target as result
- * of inquiry command.
- *
- * DeviceType field
- */
-
-#define DIRECT_ACCESS_DEVICE            0x00    /* disks */
-
 /* Timeout defines (in Seconds) */
 
 #define ISD200_ENUM_BSY_TIMEOUT         35
@@ -88,6 +89,19 @@
 #define ACTION_SELECT_6             0x40
 #define ACTION_SELECT_7             0x80
 
+/* Register Select bits */
+#define REG_ALTERNATE_STATUS 0x01
+#define REG_DEVICE_CONTROL   0x01
+#define REG_ERROR            0x02
+#define REG_FEATURES         0x02
+#define REG_SECTOR_COUNT     0x04
+#define REG_SECTOR_NUMBER    0x08
+#define REG_CYLINDER_LOW     0x10
+#define REG_CYLINDER_HIGH    0x20
+#define REG_DEVICE_HEAD      0x40
+#define REG_STATUS           0x80
+#define REG_COMMAND          0x80
+
 /* ATA error definitions not in <linux/hdreg.h> */
 #define ATA_ERROR_MEDIA_CHANGE       0x20
 
@@ -152,20 +166,8 @@
 	struct {
 		unsigned char SignatureByte0;
 		unsigned char SignatureByte1;
-		unsigned char ReadRegisterAccessBit : 1;
-		unsigned char NoDeviceSelectionBit : 1;
-		unsigned char NoBSYPollBit : 1;
-		unsigned char IgnorePhaseErrorBit : 1;
-		unsigned char IgnoreDeviceErrorBit : 1;
-		unsigned char Reserved0Bit : 3;
-		unsigned char SelectAlternateStatus : 1;
-		unsigned char SelectError : 1;
-		unsigned char SelectSectorCount : 1;
-		unsigned char SelectSectorNumber : 1;
-		unsigned char SelectCylinderLow : 1;
-		unsigned char SelectCylinderHigh : 1;
-		unsigned char SelectDeviceHead : 1;
-		unsigned char SelectStatus : 1;
+		unsigned char ActionSelect;
+		unsigned char RegisterSelect;
 		unsigned char TransferBlockSize;
 		unsigned char AlternateStatusByte;
 		unsigned char ErrorByte;
@@ -181,20 +183,8 @@
         struct {
 		unsigned char SignatureByte0;
 		unsigned char SignatureByte1;
-		unsigned char ReadRegisterAccessBit : 1;
-		unsigned char NoDeviceSelectionBit : 1;
-		unsigned char NoBSYPollBit : 1;
-		unsigned char IgnorePhaseErrorBit : 1;
-		unsigned char IgnoreDeviceErrorBit : 1;
-		unsigned char Reserved0Bit : 3;
-		unsigned char SelectDeviceControl : 1;
-		unsigned char SelectFeatures : 1;
-		unsigned char SelectSectorCount : 1;
-		unsigned char SelectSectorNumber : 1;
-		unsigned char SelectCylinderLow : 1;
-		unsigned char SelectCylinderHigh : 1;
-		unsigned char SelectDeviceHead : 1;
-		unsigned char SelectCommand : 1;
+		unsigned char ActionSelect;
+		unsigned char RegisterSelect;
 		unsigned char TransferBlockSize;
 		unsigned char DeviceControlByte;
 		unsigned char FeaturesByte;
@@ -218,27 +208,20 @@
  * includes fields through ProductRevisionLevel.
  */
 
+/*
+ * DeviceType field
+ */
+#define DIRECT_ACCESS_DEVICE            0x00    /* disks */
+#define DEVICE_REMOVABLE                0x80
+
 struct inquiry_data {
-	unsigned char DeviceType : 5;
-	unsigned char DeviceTypeQualifier : 3;
-	unsigned char DeviceTypeModifier : 7;
-	unsigned char RemovableMedia : 1;
+   	unsigned char DeviceType;
+	unsigned char DeviceTypeModifier;
 	unsigned char Versions;
-	unsigned char ResponseDataFormat : 4;
-	unsigned char HiSupport : 1;
-	unsigned char NormACA : 1;
-	unsigned char ReservedBit : 1;
-	unsigned char AERC : 1;
+	unsigned char Format; 
 	unsigned char AdditionalLength;
 	unsigned char Reserved[2];
-	unsigned char SoftReset : 1;
-	unsigned char CommandQueue : 1;
-	unsigned char Reserved2 : 1;
-	unsigned char LinkedCommands : 1;
-	unsigned char Synchronous : 1;
-	unsigned char Wide16Bit : 1;
-	unsigned char Wide32Bit : 1;
-	unsigned char RelativeAddressing : 1;
+	unsigned char Capability;
 	unsigned char VendorId[8];
 	unsigned char ProductId[16];
 	unsigned char ProductRevisionLevel[4];
@@ -257,25 +240,30 @@
  * ISD200 CONFIG data struct
  */
 
+#define ATACFG_TIMING          0x0f
+#define ATACFG_ATAPI_RESET     0x10
+#define ATACFG_MASTER          0x20
+#define ATACFG_BLOCKSIZE       0xa0
+
+#define ATACFGE_LAST_LUN       0x07
+#define ATACFGE_DESC_OVERRIDE  0x08
+#define ATACFGE_STATE_SUSPEND  0x10
+#define ATACFGE_SKIP_BOOT      0x20
+#define ATACFGE_CONF_DESC2     0x40
+#define ATACFGE_INIT_STATUS    0x80
+
+#define CFG_CAPABILITY_SRST    0x01
+
 struct isd200_config {
         unsigned char EventNotification;
         unsigned char ExternalClock;
         unsigned char ATAInitTimeout;
-        unsigned char ATATiming : 4;
-        unsigned char ATAPIReset : 1;
-        unsigned char MasterSlaveSelection : 1;
-        unsigned char ATAPICommandBlockSize : 2;
+	unsigned char ATAConfig;
         unsigned char ATAMajorCommand;
         unsigned char ATAMinorCommand;
-        unsigned char LastLUNIdentifier : 3;
-        unsigned char DescriptOverride : 1;
-        unsigned char ATA3StateSuspend : 1;
-        unsigned char SkipDeviceBoot : 1;
-        unsigned char ConfigDescriptor2 : 1;
-        unsigned char InitStatus : 1;
-        unsigned char SRSTEnable : 1;
-        unsigned char Reserved0 : 7;
-};
+	unsigned char ATAExtraConfig;
+	unsigned char Capability;
+}__attribute__ ((packed));
 
 
 /*
@@ -321,15 +309,16 @@
  * Sense Data Format
  */
 
+#define SENSE_ERRCODE           0x7f
+#define SENSE_ERRCODE_VALID     0x80
+#define SENSE_FLAG_SENSE_KEY    0x0f
+#define SENSE_FLAG_BAD_LENGTH   0x20
+#define SENSE_FLAG_END_OF_MEDIA 0x40
+#define SENSE_FLAG_FILE_MARK    0x80
 struct sense_data {
-        unsigned char ErrorCode:7;
-        unsigned char Valid:1;
-        unsigned char SegmentNumber;
-        unsigned char SenseKey:4;
-        unsigned char Reserved:1;
-        unsigned char IncorrectLength:1;
-        unsigned char EndOfMedia:1;
-        unsigned char FileMark:1;
+	unsigned char ErrorCode;
+	unsigned char SegmentNumber;
+	unsigned char Flags;
         unsigned char Information[4];
         unsigned char AdditionalSenseLength;
         unsigned char CommandSpecificInformation[4];
@@ -349,7 +338,6 @@
  * Helper routines
  ***********************************************************************/
 
-
 /**************************************************************************
  * isd200_build_sense
  *                                                                         
@@ -366,38 +354,33 @@
         unsigned char error = info->ATARegs[IDE_ERROR_OFFSET];
 
 	if(error & ATA_ERROR_MEDIA_CHANGE) {
-		buf->ErrorCode = 0x70;
-		buf->Valid     = 1;
+		buf->ErrorCode = 0x70 | SENSE_ERRCODE_VALID;
 		buf->AdditionalSenseLength = 0xb;
-		buf->SenseKey =  UNIT_ATTENTION;
+		buf->Flags = UNIT_ATTENTION;
 		buf->AdditionalSenseCode = 0;
 		buf->AdditionalSenseCodeQualifier = 0;
         } else if(error & MCR_ERR) {
-		buf->ErrorCode = 0x70;
-		buf->Valid     = 1;
+		buf->ErrorCode = 0x70 | SENSE_ERRCODE_VALID;
 		buf->AdditionalSenseLength = 0xb;
-		buf->SenseKey =  UNIT_ATTENTION;
+		buf->Flags =  UNIT_ATTENTION;
 		buf->AdditionalSenseCode = 0;
 		buf->AdditionalSenseCodeQualifier = 0;
         } else if(error & TRK0_ERR) {
-		buf->ErrorCode = 0x70;
-		buf->Valid     = 1;
+		buf->ErrorCode = 0x70 | SENSE_ERRCODE_VALID;
 		buf->AdditionalSenseLength = 0xb;
-		buf->SenseKey =  NOT_READY;
+		buf->Flags =  NOT_READY;
 		buf->AdditionalSenseCode = 0;
 		buf->AdditionalSenseCodeQualifier = 0;
         } else if(error & ECC_ERR) {
-		buf->ErrorCode = 0x70;
-		buf->Valid     = 1;
+		buf->ErrorCode = 0x70 | SENSE_ERRCODE_VALID;
 		buf->AdditionalSenseLength = 0xb;
-		buf->SenseKey =  DATA_PROTECT;
+		buf->Flags =  DATA_PROTECT;
 		buf->AdditionalSenseCode = 0;
 		buf->AdditionalSenseCodeQualifier = 0;
         } else {
 		buf->ErrorCode = 0;
-		buf->Valid     = 0;
 		buf->AdditionalSenseLength = 0;
-		buf->SenseKey =  0;
+		buf->Flags =  0;
 		buf->AdditionalSenseCode = 0;
 		buf->AdditionalSenseCodeQualifier = 0;
         }
@@ -442,7 +425,7 @@
         /* if we stall, we need to clear it before we go on */
         if (result == -EPIPE) {
                 US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
-                usb_stor_clear_halt(us->pusb_dev, pipe);
+                usb_stor_clear_halt(us, pipe);
         }
     
         /* did we send all the data? */
@@ -524,7 +507,7 @@
                         } else
                                 result = isd200_transfer_partial(us, 
                                                                  srb->sc_data_direction,                            
-                                                                 page_address(sg[i].page) + sg[i].offset,
+                                                                 page_address(sg[i].page) + sg[i].offset, 
                                                                  transfer_amount - total_transferred);
 
                         /* if we get an error, end the loop here */
@@ -593,7 +576,7 @@
         US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
                   le32_to_cpu(bcb.Signature), bcb.Tag,
                   (bcb.Lun >> 4), (bcb.Lun & 0xFF), 
-                  bcb.DataTransferLength, bcb.Flags, bcb.Length);
+                  le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length);
         result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN, 
 				   &partial);
         US_DEBUGP("Bulk command transfer result=%d\n", result);
@@ -603,7 +586,7 @@
 	else if (result == -EPIPE) {
 		/* if we stall, we need to clear it before we go on */
                 US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
-                usb_stor_clear_halt(us->pusb_dev, pipe);
+                usb_stor_clear_halt(us, pipe);
 	} else if (result)  
                 return ISD200_TRANSPORT_ERROR;
     
@@ -633,7 +616,7 @@
         /* did the attempt to read the CSW fail? */
         if (result == -EPIPE) {
                 US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
-                usb_stor_clear_halt(us->pusb_dev, pipe);
+                usb_stor_clear_halt(us, pipe);
            
                 /* get the status again */
                 US_DEBUGP("Attempting to get CSW (2nd try)...\n");
@@ -647,7 +630,7 @@
                 /* if it fails again, we need a reset and return an error*/
                 if (result == -EPIPE) {
                         US_DEBUGP("clearing halt for pipe 0x%x\n", pipe);
-                        usb_stor_clear_halt(us->pusb_dev, pipe);
+                        usb_stor_clear_halt(us, pipe);
                         return ISD200_TRANSPORT_ERROR;
                 }
         }
@@ -716,10 +699,9 @@
 	case ACTION_READ_STATUS:
 		US_DEBUGP("   isd200_action(READ_STATUS)\n");
 		ata.generic.ActionSelect = ACTION_SELECT_0|ACTION_SELECT_2;
-		ata.read.SelectStatus = 1;
-		ata.read.SelectError = 1;
-		ata.read.SelectCylinderHigh = 1;
-		ata.read.SelectCylinderLow = 1;
+		ata.generic.RegisterSelect =
+		  REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
+		  REG_STATUS | REG_ERROR;
 		srb.sc_data_direction = SCSI_DATA_READ;
 		srb.request_buffer = pointer;
 		srb.request_bufflen = value;
@@ -730,7 +712,7 @@
 		ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
 			                   ACTION_SELECT_3|ACTION_SELECT_4|
 		                           ACTION_SELECT_5;
-		ata.write.SelectDeviceHead = 1;
+		ata.generic.RegisterSelect = REG_DEVICE_HEAD;
 		ata.write.DeviceHeadByte = value;
 		srb.sc_data_direction = SCSI_DATA_NONE;
 		break;
@@ -739,7 +721,7 @@
 		US_DEBUGP("   isd200_action(RESET)\n");
 		ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
 			                   ACTION_SELECT_3|ACTION_SELECT_4;
-		ata.write.SelectDeviceControl = 1;
+		ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
 		ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER;
 		srb.sc_data_direction = SCSI_DATA_NONE;
 		break;
@@ -748,7 +730,7 @@
 		US_DEBUGP("   isd200_action(REENABLE)\n");
 		ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
 			                   ACTION_SELECT_3|ACTION_SELECT_4;
-		ata.write.SelectDeviceControl = 1;
+		ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
 		ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER;
 		srb.sc_data_direction = SCSI_DATA_NONE;
 		break;
@@ -756,16 +738,15 @@
 	case ACTION_SOFT_RESET:
 		US_DEBUGP("   isd200_action(SOFT_RESET)\n");
 		ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_5;
-		ata.write.SelectDeviceHead = 1;
+		ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND;
 		ata.write.DeviceHeadByte = info->DeviceHead;
-		ata.write.SelectCommand = 1;
 		ata.write.CommandByte = WIN_SRST;
 		srb.sc_data_direction = SCSI_DATA_NONE;
 		break;
 
 	case ACTION_IDENTIFY:
 		US_DEBUGP("   isd200_action(IDENTIFY)\n");
-		ata.write.SelectCommand = 1;
+		ata.generic.RegisterSelect = REG_COMMAND;
 		ata.write.CommandByte = WIN_IDENTIFY;
 		srb.sc_data_direction = SCSI_DATA_READ;
 		srb.request_buffer = (void *)&info->drive;
@@ -886,6 +867,43 @@
 		srb->result = CHECK_CONDITION;
 }
 
+#ifdef CONFIG_USB_STORAGE_DEBUG
+static void isd200_log_config( 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);
+}
+#endif
 
 /**************************************************************************
  * isd200_write_config
@@ -901,26 +919,11 @@
 	int retStatus = ISD200_GOOD;
 	int result;
 
-
+#ifdef CONFIG_USB_STORAGE_DEBUG
 	US_DEBUGP("Entering isd200_write_config\n");
-
 	US_DEBUGP("   Writing the following ISD200 Config Data:\n");
-	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.ATAPICommandBlockSize);
-	US_DEBUGP("      Master/Slave Selection: 0x%x\n", info->ConfigData.MasterSlaveSelection);
-	US_DEBUGP("      ATAPI Reset: 0x%x\n", info->ConfigData.ATAPIReset);
-	US_DEBUGP("      ATA Timing: 0x%x\n", info->ConfigData.ATATiming);
-	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.InitStatus);
-	US_DEBUGP("      Config Descriptor 2: 0x%x\n", info->ConfigData.ConfigDescriptor2);
-	US_DEBUGP("      Skip Device Boot: 0x%x\n", info->ConfigData.SkipDeviceBoot);
-	US_DEBUGP("      ATA 3 State Supsend: 0x%x\n", info->ConfigData.ATA3StateSuspend);
-	US_DEBUGP("      Descriptor Override: 0x%x\n", info->ConfigData.DescriptOverride);
-	US_DEBUGP("      Last LUN Identifier: 0x%x\n", info->ConfigData.LastLUNIdentifier);
-	US_DEBUGP("      SRST Enable: 0x%x\n", info->ConfigData.SRSTEnable);
+	isd200_log_config(info);
+#endif
 
 	/* let's send the command via the control pipe */
 	result = usb_stor_control_msg(
@@ -941,8 +944,8 @@
 		/* STALL must be cleared when they are detected */
 		if (result == -EPIPE) {
 			US_DEBUGP("-- Stall on control pipe. Clearing\n");
-			result = usb_stor_clear_halt(us->pusb_dev,
-						     usb_sndctrlpipe(us->pusb_dev, 0));
+			result = usb_stor_clear_halt(us,
+					usb_sndctrlpipe(us->pusb_dev, 0));
 			US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
 
 		}
@@ -986,30 +989,17 @@
 
 	if (result >= 0) {
 		US_DEBUGP("   Retrieved the following ISD200 Config Data:\n");
-		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.ATAPICommandBlockSize);
-		US_DEBUGP("      Master/Slave Selection: 0x%x\n", info->ConfigData.MasterSlaveSelection);
-		US_DEBUGP("      ATAPI Reset: 0x%x\n", info->ConfigData.ATAPIReset);
-		US_DEBUGP("      ATA Timing: 0x%x\n", info->ConfigData.ATATiming);
-		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.InitStatus);
-		US_DEBUGP("      Config Descriptor 2: 0x%x\n", info->ConfigData.ConfigDescriptor2);
-		US_DEBUGP("      Skip Device Boot: 0x%x\n", info->ConfigData.SkipDeviceBoot);
-		US_DEBUGP("      ATA 3 State Supsend: 0x%x\n", info->ConfigData.ATA3StateSuspend);
-		US_DEBUGP("      Descriptor Override: 0x%x\n", info->ConfigData.DescriptOverride);
-		US_DEBUGP("      Last LUN Identifier: 0x%x\n", info->ConfigData.LastLUNIdentifier);
-		US_DEBUGP("      SRST Enable: 0x%x\n", info->ConfigData.SRSTEnable);
+#ifdef CONFIG_USB_STORAGE_DEBUG
+		isd200_log_config(info);
+#endif
         } else {
 		US_DEBUGP("   Request to get ISD200 Config Data failed!\n");
 
 		/* STALL must be cleared when they are detected */
 		if (result == -EPIPE) {
 			US_DEBUGP("-- Stall on control pipe. Clearing\n");
-			result = usb_stor_clear_halt(us->pusb_dev,   
-						     usb_sndctrlpipe(us->pusb_dev, 0));
+			result = usb_stor_clear_halt(us,   
+					usb_sndctrlpipe(us->pusb_dev, 0));
 			US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
 
 		}
@@ -1175,11 +1165,12 @@
 				break;
 			}
 		} else {
-			US_DEBUGP("   Not ATA, not ATAPI. Weird.\n");
+ 			US_DEBUGP("   Not ATA, not ATAPI. Weird.\n");
+			break;
 		}
 
 		/* check for timeout on this request */
-		if (jiffies >= endTime) {
+		if (time_after_eq(jiffies, endTime)) {
 			if (!detect)
 				US_DEBUGP("   BSY check timeout, just continue with next operation...\n");
 			else
@@ -1223,9 +1214,10 @@
 		}
 
 		isslave = (info->DeviceHead & ATA_ADDRESS_DEVHEAD_SLAVE) ? 1 : 0;
-		if (info->ConfigData.MasterSlaveSelection != isslave) {
+		if (!(info->ConfigData.ATAConfig & ATACFG_MASTER)) {
 			US_DEBUGP("   Setting Master/Slave selection to %d\n", isslave);
-			info->ConfigData.MasterSlaveSelection = isslave;
+			info->ConfigData.ATAConfig &= 0x3f;
+			info->ConfigData.ATAConfig |= (isslave<<6);
 			retStatus = isd200_write_config(us);
 		}
 	}
@@ -1272,6 +1264,8 @@
 			} else {
 				/* ATA Command Identify successful */
 				int i;
+				__u16 *src, *dest;
+				ide_fix_driveid(&info->drive);
 
 				US_DEBUGP("   Identify Data Structure:\n");
 				US_DEBUGP("      config = 0x%x\n", info->drive.config);
@@ -1317,31 +1311,25 @@
 
 				if (info->drive.command_set_1 & COMMANDSET_MEDIA_STATUS) {
 					/* set the removable bit */
-					info->InquiryData.RemovableMedia = 1;
+					info->InquiryData.DeviceTypeModifier = DEVICE_REMOVABLE;
 					info->DeviceFlags |= DF_REMOVABLE_MEDIA;
 				}
 
 				/* Fill in vendor identification fields */
-				for (i = 0; i < 20; i += 2) {
-					info->InquiryData.VendorId[i] = 
-						info->drive.model[i + 1];
-					info->InquiryData.VendorId[i+1] = 
-						info->drive.model[i];
-				}
-
-				/* Initialize unused portion of product id */
-				for (i = 0; i < 4; i++) {
-					info->InquiryData.ProductId[12+i] = ' ';
-				}
-
-				/* Move firmware revision from IDENTIFY data to */
-				/* product revision in INQUIRY data             */
-				for (i = 0; i < 4; i += 2) {
-					info->InquiryData.ProductRevisionLevel[i] =
-						info->drive.fw_rev[i+1];
-					info->InquiryData.ProductRevisionLevel[i+1] =
-						info->drive.fw_rev[i];
-				}
+				src = (__u16*)info->drive.model;
+				dest = (__u16*)info->InquiryData.VendorId;
+				for (i=0;i<4;i++)
+					dest[i] = be16_to_cpu(src[i]);
+
+				src = (__u16*)(info->drive.model+8);
+				dest = (__u16*)info->InquiryData.ProductId;
+				for (i=0;i<8;i++)
+					dest[i] = be16_to_cpu(src[i]);
+
+				src = (__u16*)info->drive.fw_rev;
+				dest = (__u16*)info->InquiryData.ProductRevisionLevel;
+				for (i=0;i<2;i++)
+					dest[i] = be16_to_cpu(src[i]);
 
 				/* determine if it supports Media Status Notification */
 				if (info->drive.command_set_2 & COMMANDSET_MEDIA_STATUS) {
@@ -1483,7 +1471,7 @@
 			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
 			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
 			ataCdb->generic.TransferBlockSize = 1;
-			ataCdb->write.SelectCommand = 1;
+			ataCdb->generic.RegisterSelect = REG_COMMAND;
 			ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
 			srb->request_bufflen = 0;
 		} else {
@@ -1504,7 +1492,7 @@
 			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
 			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
 			ataCdb->generic.TransferBlockSize = 1;
-			ataCdb->write.SelectCommand = 1;
+			ataCdb->generic.RegisterSelect = REG_COMMAND;
 			ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
 			srb->request_bufflen = 0;
 		} else {
@@ -1561,17 +1549,15 @@
 		ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
 		ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
 		ataCdb->generic.TransferBlockSize = 1;
-		ataCdb->write.SelectSectorCount = 1;
+		ataCdb->generic.RegisterSelect =
+		  REG_SECTOR_COUNT | REG_SECTOR_NUMBER |
+		  REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
+		  REG_DEVICE_HEAD  | REG_COMMAND;
 		ataCdb->write.SectorCountByte = (unsigned char)blockCount;
-		ataCdb->write.SelectSectorNumber = 1;
 		ataCdb->write.SectorNumberByte = sectnum;
-		ataCdb->write.SelectCylinderHigh = 1;
 		ataCdb->write.CylinderHighByte = (unsigned char)(cylinder>>8);
-		ataCdb->write.SelectCylinderLow = 1;
 		ataCdb->write.CylinderLowByte = (unsigned char)cylinder;
-		ataCdb->write.SelectDeviceHead = 1;
 		ataCdb->write.DeviceHeadByte = (head | ATA_ADDRESS_DEVHEAD_STD);
-		ataCdb->write.SelectCommand = 1;
 		ataCdb->write.CommandByte = WIN_READ;
 		break;
 
@@ -1594,17 +1580,15 @@
 		ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
 		ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
 		ataCdb->generic.TransferBlockSize = 1;
-		ataCdb->write.SelectSectorCount = 1;
+		ataCdb->generic.RegisterSelect =
+		  REG_SECTOR_COUNT | REG_SECTOR_NUMBER |
+		  REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
+		  REG_DEVICE_HEAD  | REG_COMMAND;
 		ataCdb->write.SectorCountByte = (unsigned char)blockCount;
-		ataCdb->write.SelectSectorNumber = 1;
 		ataCdb->write.SectorNumberByte = sectnum;
-		ataCdb->write.SelectCylinderHigh = 1;
 		ataCdb->write.CylinderHighByte = (unsigned char)(cylinder>>8);
-		ataCdb->write.SelectCylinderLow = 1;
 		ataCdb->write.CylinderLowByte = (unsigned char)cylinder;
-		ataCdb->write.SelectDeviceHead = 1;
 		ataCdb->write.DeviceHeadByte = (head | ATA_ADDRESS_DEVHEAD_STD);
-		ataCdb->write.SelectCommand = 1;
 		ataCdb->write.CommandByte = WIN_WRITE;
 		break;
 
@@ -1617,7 +1601,7 @@
 			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
 			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
 			ataCdb->generic.TransferBlockSize = 1;
-			ataCdb->write.SelectCommand = 1;
+			ataCdb->generic.RegisterSelect = REG_COMMAND;
 			ataCdb->write.CommandByte = (srb->cmnd[4] & 0x1) ?
 				WIN_DOORLOCK : WIN_DOORUNLOCK;
 			srb->request_bufflen = 0;
@@ -1640,14 +1624,14 @@
 			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
 			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
 			ataCdb->generic.TransferBlockSize = 0;
-			ataCdb->write.SelectCommand = 1;
+			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");
 			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
 			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
 			ataCdb->generic.TransferBlockSize = 1;
-			ataCdb->write.SelectCommand = 1;
+			ataCdb->generic.RegisterSelect = REG_COMMAND;
 			ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
 			srb->request_bufflen = 0;
 		} else {
diff -Nru a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
--- a/drivers/usb/storage/jumpshot.c	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/jumpshot.c	Sat May 11 22:29:14 2002
@@ -1,16 +1,26 @@
 /* Driver for Lexar "Jumpshot" Compact Flash reader
  *
+ * $Id: jumpshot.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $
+ *
  * jumpshot driver v0.1:
  *
  * First release
  *
  * Current development and maintenance by:
  *   (c) 2000 Jimmie Mayfield (mayfield+usb@sackheads.org)
- *   many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
+ *
+ *   Many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
  *   which I used as a template for this driver.
+ *
  *   Some bugfixes and scatter-gather code by Gregory P. Smith 
  *   (greg-usb@electricrain.com)
  *
+ *   Fix for media change by Joerg Schneider (js@joergschneider.com)
+ *
+ * Developed with the assistance of:
+ *
+ *   (C) 2002 Alan Stern <stern@rowland.org>
+ *
  * 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
@@ -128,8 +138,8 @@
 		/* a stall is a fatal condition from the device */
 		if (result == -EPIPE) {
 			US_DEBUGP("jumpshot_send_control:  -- Stall on control pipe. Clearing\n");
-			result = usb_clear_halt(us->pusb_dev, pipe);
-			US_DEBUGP("jumpshot_send_control:  -- usb_clear_halt() returns %d\n", result);
+			result = usb_stor_clear_halt(us, pipe);
+			US_DEBUGP("jumpshot_send_control:  -- usb_stor_clear_halt() returns %d\n", result);
 			return USB_STOR_TRANSPORT_FAILED;
 		}
 
@@ -161,7 +171,7 @@
 	if (result == -EPIPE) {
 		US_DEBUGP("jumpshot_raw_bulk:  EPIPE. clearing endpoint halt for"
 			  " pipe 0x%x, stalled at %d bytes\n", pipe, act_len);
-		usb_clear_halt(us->pusb_dev, pipe);
+		usb_stor_clear_halt(us, pipe);
 	}
 
 	if (result) {
@@ -798,6 +808,23 @@
 		//
 		return USB_STOR_TRANSPORT_GOOD;
 	}
+	
+	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");
+		/* the first jumpshot_id_device after a media change returns
+		   an error (determined experimentally) */
+		rc = jumpshot_id_device(us, info);
+		if (rc == USB_STOR_TRANSPORT_GOOD) {
+			info->sense_key = NO_SENSE;
+			srb->result = SUCCESS;
+		} else {
+			info->sense_key = UNIT_ATTENTION;
+			srb->result = CHECK_CONDITION;
+		}
+		return rc;
+        }
 
 	US_DEBUGP("jumpshot_transport:  Gah! Unknown command: %d (0x%x)\n", srb->cmnd[0], srb->cmnd[0]);
 	return USB_STOR_TRANSPORT_ERROR;
diff -Nru a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
--- a/drivers/usb/storage/protocol.c	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/protocol.c	Sat May 11 22:29:14 2002
@@ -1,12 +1,13 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * $Id: protocol.c,v 1.11 2002/01/13 06:40:25 mdharm Exp $
+ * $Id: protocol.c,v 1.14 2002/04/22 03:39:43 mdharm Exp $
  *
  * Current development and maintenance by:
- *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
  * Developed with the assistance of:
  *   (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
+ *   (c) 2002 Alan Stern (stern@rowland.org)
  *
  * Initial work by:
  *   (c) 1999 Michael Gee (michael@linuxspecific.com)
@@ -67,10 +68,16 @@
 	US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2\n");
 
 	/* find the location of the data */
-	if (srb->use_sg)
-		BUG();
-
-	data_ptr = (unsigned char *) srb->request_buffer;
+	if (srb->use_sg) {
+		/* this piece of code only works if the first page is big enough to
+		 * hold more than 3 bytes -- which is _very_ likely
+		 */
+		struct scatterlist *sg;
+
+		sg = (struct scatterlist *) srb->request_buffer;
+		data_ptr = (unsigned char *) page_address(sg[0].page) + sg[0].offset;
+	} else
+		data_ptr = (unsigned char *)srb->request_buffer;
 
 	/* Change the SCSI revision number */
 	data_ptr[2] = (data_ptr[2] & ~7) | 2;
@@ -94,9 +101,11 @@
 
 	/* send the command to the transport layer */
 	usb_stor_invoke_transport(srb, us);
+	if (srb->result == GOOD << 1) {
 
-	/* fix the INQUIRY data if necessary */
-	fix_inquiry_data(srb);
+		/* fix the INQUIRY data if necessary */
+		fix_inquiry_data(srb);
+	}
 }
 
 void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
@@ -165,13 +174,15 @@
 
 	/* send the command to the transport layer */
 	usb_stor_invoke_transport(srb, us);
+	if (srb->result == GOOD << 1) {
 
-	/* Fix the MODE_SENSE data if we translated the command */
-	if ((old_cmnd == MODE_SENSE) && (status_byte(srb->result) == GOOD))
-		usb_stor_scsiSense10to6(srb);
-
-	/* fix the INQUIRY data if necessary */
-	fix_inquiry_data(srb);
+		/* Fix the MODE_SENSE data if we translated the command */
+		if (old_cmnd == MODE_SENSE)
+			usb_stor_scsiSense10to6(srb);
+
+		/* fix the INQUIRY data if necessary */
+		fix_inquiry_data(srb);
+	}
 }
 
 
@@ -260,13 +271,15 @@
 
 	/* send the command to the transport layer */
 	usb_stor_invoke_transport(srb, us);
+	if (srb->result == GOOD << 1) {
 
-	/* Fix the MODE_SENSE data if we translated the command */
-	if ((old_cmnd == MODE_SENSE) && (status_byte(srb->result) == GOOD))
-		usb_stor_scsiSense10to6(srb);
-
-	/* Fix the data for an INQUIRY, if necessary */
-	fix_inquiry_data(srb);
+		/* Fix the MODE_SENSE data if we translated the command */
+		if (old_cmnd == MODE_SENSE)
+			usb_stor_scsiSense10to6(srb);
+
+		/* Fix the data for an INQUIRY, if necessary */
+		fix_inquiry_data(srb);
+	}
 }
 
 void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
@@ -327,13 +340,14 @@
 
 	/* send the command to the transport layer */
 	usb_stor_invoke_transport(srb, us);
+	if (srb->result == GOOD << 1) {
 
-	/* Fix the MODE_SENSE data if we translated the command */
-	if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SENSE)
-			&& (status_byte(srb->result) == GOOD))
-		usb_stor_scsiSense10to6(srb);
-
-	/* fix the INQUIRY data if necessary */
-	fix_inquiry_data(srb);
+		/* Fix the MODE_SENSE data if we translated the command */
+		if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SENSE))
+			usb_stor_scsiSense10to6(srb);
+
+		/* fix the INQUIRY data if necessary */
+		fix_inquiry_data(srb);
+	}
 }
 
diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
--- a/drivers/usb/storage/scsiglue.c	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/scsiglue.c	Sat May 11 22:29:14 2002
@@ -1,7 +1,7 @@
 /* Driver for USB Mass Storage compliant devices
  * SCSI layer glue code
  *
- * $Id: scsiglue.c,v 1.24 2001/11/11 03:33:58 mdharm Exp $
+ * $Id: scsiglue.c,v 1.26 2002/04/22 03:39:43 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -177,22 +177,8 @@
 
 	US_DEBUGP("command_abort() called\n");
 
-	/* if we're stuck waiting for an IRQ, simulate it */
-	if (atomic_read(us->ip_wanted)) {
-		US_DEBUGP("-- simulating missing IRQ\n");
-		up(&(us->ip_waitq));
-	}
-
-	/* if the device has been removed, this worked */
-	if (!us->pusb_dev) {
-		US_DEBUGP("-- device removed already\n");
-		return SUCCESS;
-	}
-
-	/* if we have an urb pending, let's wake the control thread up */
-	if (us->current_urb->status == -EINPROGRESS) {
-		/* cancel the URB -- this will automatically wake the thread */
-		usb_unlink_urb(us->current_urb);
+	if (atomic_read(&us->sm_state) == US_STATE_RUNNING) {
+		usb_stor_abort_transport(us);
 
 		/* wait for us to be done */
 		wait_for_completion(&(us->notify));
@@ -208,47 +194,57 @@
 static int device_reset( Scsi_Cmnd *srb )
 {
 	struct us_data *us = (struct us_data *)srb->host->hostdata[0];
+	int result;
 
 	US_DEBUGP("device_reset() called\n" );
-	return us->transport_reset(us);
+
+	/* if the device was removed, then we're already reset */
+	if (atomic_read(&us->sm_state) == US_STATE_DETACHED)
+		return SUCCESS;
+
+	/* lock the device pointers */
+	down(&(us->dev_semaphore));
+	us->srb = srb;
+	atomic_set(&us->sm_state, US_STATE_RESETTING);
+	result = us->transport_reset(us);
+	atomic_set(&us->sm_state, US_STATE_IDLE);
+
+	/* unlock the device pointers */
+	up(&(us->dev_semaphore));
+	return result;
 }
 
 /* This resets the device port, and simulates the device
- * disconnect/reconnect for all drivers which have claimed other
- * interfaces. */
+ * disconnect/reconnect for all drivers which have claimed
+ * interfaces, including ourself. */
 static int bus_reset( Scsi_Cmnd *srb )
 {
 	struct us_data *us = (struct us_data *)srb->host->hostdata[0];
 	int i;
 	int result;
+	struct usb_device *pusb_dev_save = us->pusb_dev;
 
 	/* we use the usb_reset_device() function to handle this for us */
 	US_DEBUGP("bus_reset() called\n");
 
 	/* if the device has been removed, this worked */
-	if (!us->pusb_dev) {
+	if (atomic_read(&us->sm_state) == US_STATE_DETACHED) {
 		US_DEBUGP("-- device removed already\n");
 		return SUCCESS;
 	}
 
-	/* release the IRQ, if we have one */
-	down(&(us->irq_urb_sem));
-	if (us->irq_urb) {
-		US_DEBUGP("-- releasing irq URB\n");
-		result = usb_unlink_urb(us->irq_urb);
-		US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
-	}
-	up(&(us->irq_urb_sem));
-
 	/* attempt to reset the port */
-	if (usb_reset_device(us->pusb_dev) < 0)
+	result = usb_reset_device(pusb_dev_save);
+	US_DEBUGP("usb_reset_device returns %d\n", result);
+	if (result < 0)
 		return FAILED;
 
 	/* FIXME: This needs to lock out driver probing while it's working
 	 * or we can have race conditions */
-        for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) {
+	/* Is that still true?  I don't see how...  AS */
+        for (i = 0; i < pusb_dev_save->actconfig->bNumInterfaces; i++) {
  		struct usb_interface *intf =
-			&us->pusb_dev->actconfig->interface[i];
+			&pusb_dev_save->actconfig->interface[i];
 		const struct usb_device_id *id;
 
 		/* if this is an unclaimed interface, skip it */
@@ -256,33 +252,17 @@
 			continue;
 		}
 
-		US_DEBUGP("Examinging driver %s...", intf->driver->name);
-		/* skip interfaces which we've claimed */
-		if (intf->driver == &usb_storage_driver) {
-			US_DEBUGPX("skipping ourselves.\n");
-			continue;
-		}
+		US_DEBUGP("Examining driver %s...", intf->driver->name);
 
 		/* simulate a disconnect and reconnect for all interfaces */
 		US_DEBUGPX("simulating disconnect/reconnect.\n");
 		down(&intf->driver->serialize);
-		intf->driver->disconnect(us->pusb_dev, intf->private_data);
-		id = usb_match_id(us->pusb_dev, intf, intf->driver->id_table);
-		intf->driver->probe(us->pusb_dev, i, id);
+		intf->driver->disconnect(pusb_dev_save, intf->private_data);
+		id = usb_match_id(pusb_dev_save, intf, intf->driver->id_table);
+		intf->driver->probe(pusb_dev_save, i, id);
 		up(&intf->driver->serialize);
 	}
 
-	/* re-allocate the IRQ URB and submit it to restore connectivity
-	 * for CBI devices
-	 */
-	if (us->protocol == US_PR_CBI) {
-		down(&(us->irq_urb_sem));
-		us->irq_urb->dev = us->pusb_dev;
-		result = usb_submit_urb(us->irq_urb, GFP_NOIO);
-		US_DEBUGP("usb_submit_urb() returns %d\n", result);
-		up(&(us->irq_urb_sem));
-	}
-
 	US_DEBUGP("bus_reset() complete\n");
 	return SUCCESS;
 }
@@ -346,7 +326,8 @@
 
 	/* show the GUID of the device */
 	SPRINTF("         GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));
-	SPRINTF("     Attached: %s\n", us->pusb_dev ? "Yes" : "No");
+	SPRINTF("     Attached: %s\n", (atomic_read(&us->sm_state) ==
+			US_STATE_DETACHED) ? "Yes" : "No");
 
 	/*
 	 * Calculate start of next buffer, and return value.
@@ -565,11 +546,11 @@
 
 	  /* copy one byte */
 	  {
-		  char *src = page_address(sg[sb].page) + sg[sb].offset + si;
-		  char *dst = page_address(sg[db].page) + sg[db].offset + di;
+	        char *src = page_address(sg[sb].page) + sg[sb].offset + si;
+	        char *dst = page_address(sg[db].page) + sg[db].offset + di;
 
-		  *dst = *src;
-	  }
+                 *dst = *src;
+          }
 
 	  /* get next destination */
 	  if ( sg[db].length-1 == di )
@@ -607,7 +588,7 @@
 	      break;
 	    }
 
-	  *(char *)(page_address(sg[db].page) + sg[db].offset) = 0;
+	  *(char*)(page_address(sg[db].page) + sg[db].offset) = 0;
 
 	  /* get next destination */
 	  if ( sg[db].length-1 == di )
@@ -758,11 +739,11 @@
 
 	  /* copy one byte */
 	  {
-		  char *src = page_address(sg[sb].page) + sg[sb].offset + si;
-		  char *dst = page_address(sg[db].page) + sg[db].offset + di;
+	        char *src = page_address(sg[sb].page) + sg[sb].offset + si;
+	        char *dst = page_address(sg[db].page) + sg[db].offset + di;
 
-		  *dst = *src;
-	  }
+                 *dst = *src;
+          }
 
 	  /* get next destination */
 	  if ( di == 0 )
@@ -799,11 +780,12 @@
 	      break;
 	    }
 
-	  {
-		  char *dst = page_address(sg[db].page) + sg[db].offset + di;
+         {
+                 char *dst = page_address(sg[db].page) + sg[db].offset + di;
+
+                 *dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
+         }
 
-		  *dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
-	  }
 
 	  /* get next destination */
 	  if ( di == 0 )
@@ -853,19 +835,18 @@
 		  if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
 		    {
 		      /* fill in the pointers for both header types */
-		      the6->array[element] =
-			      page_address(sg[i].page) +
-			      sg[i].offset + j;
-		      the10->array[element] =
-			      page_address(sg[i].page) +
-			      sg[i].offset + j;
+		      the6->array[element] = page_address(sg[i].page) +
+			      			sg[i].offset + j;
+		      the10->array[element] = page_address(sg[i].page) +
+			                        sg[i].offset + j;
+
 		    }
 		  else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
 		    {
 		      /* only the longer headers still cares now */
-		      the10->array[element] =
-			      page_address(sg[i].page) +
-			      sg[i].offset + j;
+		      the10->array[element] = page_address(sg[i].page) +
+			                        sg[i].offset + j;
+		       
 		    }
 		  /* increase element counter */
 		  element++;
diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
--- a/drivers/usb/storage/sddr09.c	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/sddr09.c	Sat May 11 22:29:15 2002
@@ -1,7 +1,10 @@
 /* Driver for SanDisk SDDR-09 SmartMedia reader
  *
+ * $Id: sddr09.c,v 1.24 2002/04/22 03:39:43 mdharm Exp $
  *   (c) 2000, 2001 Robert Baruch (autophile@starband.net)
  *   (c) 2002 Andries Brouwer (aeb@cwi.nl)
+ * Developed with the assistance of:
+ *   (c) 2002 Alan Stern <stern@rowland.org>
  *
  * The SanDisk SDDR-09 SmartMedia reader uses the Shuttle EUSB-01 chip.
  * This chip is a programmable USB controller. In the SDDR-09, it has
@@ -262,8 +265,8 @@
 		/* a stall is a fatal condition from the device */
 		if (result == -EPIPE) {
 			US_DEBUGP("-- Stall on control pipe. Clearing\n");
-			result = usb_clear_halt(us->pusb_dev, pipe);
-			US_DEBUGP("-- usb_clear_halt() returns %d\n", result);
+			result = usb_stor_clear_halt(us, pipe);
+			US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
 			return USB_STOR_TRANSPORT_FAILED;
 		}
 
@@ -317,13 +320,13 @@
 
 	result = usb_stor_bulk_msg(us, data, pipe, len, &act_len);
 
-	/* if we stall, we need to clear it before we go on */
-	if (result == -EPIPE) {
-		US_DEBUGP("EPIPE: clearing endpoint halt for"
-			  " pipe 0x%x, stalled at %d bytes\n",
-			  pipe, act_len);
-		usb_clear_halt(us->pusb_dev, pipe);
-	}
+        /* if we stall, we need to clear it before we go on */
+        if (result == -EPIPE) {
+       	        US_DEBUGP("EPIPE: clearing endpoint halt for"
+			" pipe 0x%x, stalled at %d bytes\n",
+			pipe, act_len);
+               	usb_stor_clear_halt(us, pipe);
+        }
 
 	if (result) {
 		/* -ENOENT -- we canceled this transfer */
@@ -1386,15 +1389,6 @@
 	// Each block is 64 bytes of control data, so block i is located in
 	// scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11)
 
-#if 0
-	/* No translation */
-	for (i=0; i<numblocks; i++) {
-		lba = i;
-		info->pba_to_lba[i] = lba;
-		info->lba_to_pba[lba] = i;
-	}
-	printk("sddr09: no translation today\n");
-#else
 	for (i=0; i<numblocks; i++) {
 		ptr = page_address(sg[i>>11].page) +
 			sg[i>>11].offset + ((i&0x7ff)<<6);
@@ -1482,7 +1476,6 @@
 		info->pba_to_lba[i] = lba;
 		info->lba_to_pba[lba] = i;
 	}
-#endif
 
 	/*
 	 * Approximate capacity. This is not entirely correct yet,
@@ -1508,7 +1501,7 @@
 	US_DEBUGP("Found %d LBA's\n", lbact);
 
 	for (i=0; i<alloc_blocks; i++)
-		kfree(page_address(sg[i].page)+sg[i].offset);
+		kfree(page_address(sg[i].page) + sg[i].offset);
 	kfree(sg);
 	return 0;
 }
diff -Nru a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
--- a/drivers/usb/storage/shuttle_usbat.c	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/shuttle_usbat.c	Sat May 11 22:29:14 2002
@@ -1,10 +1,13 @@
 /* Driver for SCM Microsystems USB-ATAPI cable
  *
- * $Id: shuttle_usbat.c,v 1.15 2001/12/08 23:32:48 mdharm Exp $
+ * $Id: shuttle_usbat.c,v 1.17 2002/04/22 03:39:43 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 2000, 2001 Robert Baruch (autophile@starband.net)
  *
+ * Developed with the assistance of:
+ *   (c) 2002 Alan Stern <stern@rowland.org>
+ *
  * Many originally ATAPI devices were slightly modified to meet the USB
  * market by using some kind of translation from ATAPI to USB on the host,
  * and the peripheral would translate from USB back to ATAPI.
@@ -107,8 +110,8 @@
 		/* a stall is a fatal condition from the device */
 		if (result == -EPIPE) {
 			US_DEBUGP("-- Stall on control pipe. Clearing\n");
-			result = usb_clear_halt(us->pusb_dev, pipe);
-			US_DEBUGP("-- usb_clear_halt() returns %d\n", result);
+			result = usb_stor_clear_halt(us, pipe);
+			US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
 			return USB_STOR_TRANSPORT_FAILED;
 		}
 
@@ -140,7 +143,7 @@
        	        US_DEBUGP("EPIPE: clearing endpoint halt for"
 			" pipe 0x%x, stalled at %d bytes\n",
 			pipe, act_len);
-               	usb_clear_halt(us->pusb_dev, pipe);
+               	usb_stor_clear_halt(us, pipe);
         }
 
 	if (result) {
@@ -214,7 +217,7 @@
 		sg = (struct scatterlist *)data;
 		for (i=0; i<use_sg && transferred<len; i++) {
 			result = usbat_raw_bulk(us, direction,
-				page_address(sg[i].page) + sg[i].offset,
+				page_address(sg[i].page) + sg[i].offset, 
 				len-transferred > sg[i].length ?
 					sg[i].length : len-transferred);
 			if (result!=US_BULK_TRANSFER_GOOD)
@@ -515,7 +518,7 @@
 			 */
 
 			if (direction==SCSI_DATA_READ && i==0)
-				usb_clear_halt(us->pusb_dev,
+				usb_stor_clear_halt(us,
 					usb_sndbulkpipe(us->pusb_dev,
 					  us->ep_out));
 			/*
@@ -675,9 +678,15 @@
 		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);
 		srb->transfersize = srb->request_bufflen/len;
 	}
 
+	if (!srb->transfersize)  {
+		srb->transfersize = 2048; /* A guess */
+		US_DEBUGP("handle_read10: transfersize 0, forcing %d\n",
+			srb->transfersize);
+	}
 
 	len = (65535/srb->transfersize) * srb->transfersize;
 	US_DEBUGP("Max read is %d bytes\n", len);
@@ -734,7 +743,7 @@
 				if (len - amount >= 
 					  sg[sg_segment].length-sg_offset) {
 				  memcpy(page_address(sg[sg_segment].page) +
-					 sg[sg_segment].offset + sg_offset,
+					 sg[sg_sgement].offset + sg_offset,
 					 buffer + amount,
 					 sg[sg_segment].length - sg_offset);
 				  amount += 
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/transport.c	Sat May 11 22:29:14 2002
@@ -1,13 +1,14 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * $Id: transport.c,v 1.42 2001/12/08 23:32:48 mdharm Exp $
+ * $Id: transport.c,v 1.47 2002/04/22 03:39:43 mdharm Exp $
  *
  * Current development and maintenance by:
- *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
  * Developed with the assistance of:
  *   (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
  *   (c) 2000 Stephen J. Gowdy (SGowdy@lbl.gov)
+ *   (c) 2002 Alan Stern <stern@rowland.org>
  *
  * Initial work by:
  *   (c) 1999 Michael Gee (michael@linuxspecific.com)
@@ -329,37 +330,21 @@
 			   for (i = 0; i < srb->use_sg; i++)
 				   total += sg[i].length;
 			   len = total;
+
+			   /* Double-check to see if the advertised buffer
+			    * length less than the actual buffer length --
+			    * in other words, we should tend towards the
+			    * conservative side for data transfers.
+			    */
+			   if (len > srb->request_bufflen)
+				   len = srb->request_bufflen;
 		   }
 		   else
 			   /* Just return the length of the buffer */
 			   len = srb->request_bufflen;
 	   }
 
-return len;
-}
-
-/* This is a version of usb_clear_halt() that doesn't read the status from
- * the device -- this is because some devices crash their internal firmware
- * when the status is requested after a halt
- */
-int usb_stor_clear_halt(struct usb_device *dev, int pipe)
-{
-	int result;
-	int endp = usb_pipeendpoint(pipe) | (usb_pipein(pipe) << 7);
-
-	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
-				 endp, NULL, 0, HZ * 3);
-
-	/* this is a failure case */
-	if (result < 0)
-		return result;
-
-	/* reset the toggles and endpoint flags */
-	usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
-	usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
-
-	return 0;
+	return len;
 }
 
 /***********************************************************************
@@ -376,109 +361,142 @@
 	complete(urb_done_ptr);
 }
 
-/* This is our function to emulate usb_control_msg() but give us enough
- * access to make aborts/resets work
+/* This is the common part of the URB message submission code
+ * This function expects the current_urb_sem to be held upon entry.
+ */
+static int usb_stor_msg_common(struct us_data *us)
+{
+	struct completion urb_done;
+	int status;
+
+	/* set up data structures for the wakeup system */
+	init_completion(&urb_done);
+
+	/* fill the common fields in the URB */
+	us->current_urb->context = &urb_done;
+	us->current_urb->actual_length = 0;
+	us->current_urb->error_count = 0;
+	us->current_urb->transfer_flags = USB_ASYNC_UNLINK;
+
+	/* submit the URB */
+	status = usb_submit_urb(us->current_urb, GFP_NOIO);
+	if (status) {
+		/* something went wrong */
+		return status;
+	}
+
+	/* has the current command been aborted? */
+	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
+
+		/* avoid a race with usb_stor_abort_transport():
+		 *  if the abort took place before we submitted
+		 *  the URB, we must cancel it ourselves */
+		if (us->current_urb->status == -EINPROGRESS)
+			usb_unlink_urb(us->current_urb);
+		}
+
+	/* wait for the completion of the URB */
+	up(&(us->current_urb_sem));
+	wait_for_completion(&urb_done);
+	down(&(us->current_urb_sem));
+
+	/* return the URB status */
+	return us->current_urb->status;
+}
+
+/* This is our function to emulate usb_control_msg() with enough control
+ * to make aborts/resets/timeouts work
  */
 int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
 			 u8 request, u8 requesttype, u16 value, u16 index, 
 			 void *data, u16 size)
 {
-	struct completion urb_done;
 	int status;
 	struct usb_ctrlrequest *dr;
 
-	/* allocate the device request structure */
 	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
 	if (!dr)
 		return -ENOMEM;
 
-	/* fill in the structure */
+	/* fill in the devrequest structure */
 	dr->bRequestType = requesttype;
 	dr->bRequest = request;
 	dr->wValue = cpu_to_le16(value);
 	dr->wIndex = cpu_to_le16(index);
 	dr->wLength = cpu_to_le16(size);
 
-	/* set up data structures for the wakeup system */
-	init_completion(&urb_done);
-
 	/* lock the URB */
 	down(&(us->current_urb_sem));
 
 	/* fill the URB */
 	FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe, 
-			 (unsigned char*) dr, data, size, 
-			 usb_stor_blocking_completion, &urb_done);
-	us->current_urb->actual_length = 0;
-	us->current_urb->error_count = 0;
-	us->current_urb->transfer_flags = USB_ASYNC_UNLINK;
+			 (unsigned char*) &dr, data, size, 
+			 usb_stor_blocking_completion, NULL);
 
 	/* submit the URB */
-	status = usb_submit_urb(us->current_urb, GFP_NOIO);
-	if (status) {
-		/* something went wrong */
-		up(&(us->current_urb_sem));
-		kfree(dr);
-		return status;
-	}
-
-	/* wait for the completion of the URB */
-	up(&(us->current_urb_sem));
-	wait_for_completion(&urb_done);
-	down(&(us->current_urb_sem));
+	status = usb_stor_msg_common(us);
 
 	/* return the actual length of the data transferred if no error*/
-	status = us->current_urb->status;
 	if (status >= 0)
 		status = us->current_urb->actual_length;
 
 	/* release the lock and return status */
 	up(&(us->current_urb_sem));
-	kfree(dr);
-  	return status;
+	return status;
 }
 
-/* This is our function to emulate usb_bulk_msg() but give us enough
- * access to make aborts/resets work
+/* This is our function to emulate usb_bulk_msg() with enough control
+ * to make aborts/resets/timeouts work
  */
 int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
 		      unsigned int len, unsigned int *act_len)
 {
-	struct completion urb_done;
 	int status;
 
-	/* set up data structures for the wakeup system */
-	init_completion(&urb_done);
-
 	/* lock the URB */
 	down(&(us->current_urb_sem));
 
 	/* fill the URB */
 	FILL_BULK_URB(us->current_urb, us->pusb_dev, pipe, data, len,
-		      usb_stor_blocking_completion, &urb_done);
-	us->current_urb->actual_length = 0;
-	us->current_urb->error_count = 0;
-	us->current_urb->transfer_flags = USB_ASYNC_UNLINK;
+		      usb_stor_blocking_completion, NULL);
 
 	/* submit the URB */
-	status = usb_submit_urb(us->current_urb, GFP_NOIO);
-	if (status) {
-		/* something went wrong */
-		up(&(us->current_urb_sem));
-		return status;
-	}
-
-	/* wait for the completion of the URB */
-	up(&(us->current_urb_sem));
-	wait_for_completion(&urb_done);
-	down(&(us->current_urb_sem));
+	status = usb_stor_msg_common(us);
 
 	/* return the actual length of the data transferred */
 	*act_len = us->current_urb->actual_length;
 
 	/* release the lock and return status */
 	up(&(us->current_urb_sem));
-	return us->current_urb->status;
+	return status;
+}
+
+/* This is a version of usb_clear_halt() that doesn't read the status from
+ * the device -- this is because some devices crash their internal firmware
+ * when the status is requested after a halt
+ */
+int usb_stor_clear_halt(struct us_data *us, int pipe)
+{
+	int result;
+	int endp = usb_pipeendpoint(pipe) | (usb_pipein(pipe) << 7);
+
+	result = usb_stor_control_msg(us,
+		usb_sndctrlpipe(us->pusb_dev, 0),
+		USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
+		endp, NULL, 0);		/* note: no 3*HZ timeout */
+	US_DEBUGP("usb_stor_clear_halt: result=%d\n", result);
+
+	/* this is a failure case */
+	if (result < 0)
+		return result;
+
+	/* reset the toggles and endpoint flags */
+	usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe),
+		usb_pipeout(pipe));
+	usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
+		usb_pipeout(pipe), 0);
+
+	return 0;
 }
 
 /*
@@ -513,7 +531,13 @@
 	/* if we stall, we need to clear it before we go on */
 	if (result == -EPIPE) {
 		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
-		usb_stor_clear_halt(us->pusb_dev, pipe);
+		usb_stor_clear_halt(us, pipe);
+	}
+
+	/* did we abort this command? */
+	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
+		US_DEBUGP("usb_stor_transfer_partial(): transfer aborted\n");
+		return US_BULK_TRANSFER_ABORTED;
 	}
 
 	/* did we send all the data? */
@@ -522,21 +546,14 @@
 		return US_BULK_TRANSFER_GOOD;
 	}
 
-	/* uh oh... we have an error code, so something went wrong. */
-	if (result) {
-		/* NAK - that means we've retried a few times already */
-		if (result == -ETIMEDOUT) {
-			US_DEBUGP("usb_stor_transfer_partial(): device NAKed\n");
-			return US_BULK_TRANSFER_FAILED;
-		}
-
-		/* -ENOENT -- we canceled this transfer */
-		if (result == -ENOENT) {
-			US_DEBUGP("usb_stor_transfer_partial(): transfer aborted\n");
-			return US_BULK_TRANSFER_ABORTED;
-		}
+	/* NAK - that means we've retried a few times already */
+	if (result == -ETIMEDOUT) {
+		US_DEBUGP("usb_stor_transfer_partial(): device NAKed\n");
+		return US_BULK_TRANSFER_FAILED;
+	}
 
-		/* the catch-all case */
+	/* the catch-all error case */
+	if (result) {
 		US_DEBUGP("usb_stor_transfer_partial(): unknown error\n");
 		return US_BULK_TRANSFER_FAILED;
 	}
@@ -550,7 +567,7 @@
  * Transfer an entire SCSI command's worth of data payload over the bulk
  * pipe.
  *
- * Note that this uses usb_stor_transfer_partial to achieve it's goals -- this
+ * Note that this uses usb_stor_transfer_partial to achieve its goals -- this
  * function simply determines if we're going to use scatter-gather or not,
  * and acts appropriately.  For now, it also re-interprets the error codes.
  */
@@ -631,6 +648,14 @@
 		return;
 	}
 
+	/* 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");
+		us->transport_reset(us);
+		srb->result = DID_ERROR << 16;
+		return;
+	}
+
 	/* Determine if we need to auto-sense
 	 *
 	 * I normally don't use a flag like this, but it's almost impossible
@@ -660,7 +685,7 @@
 	}
 
 	/*
-	 * If we have an error, we're going to do a REQUEST_SENSE 
+	 * If we have a failure, we're going to do a REQUEST_SENSE 
 	 * automatically.  Note that we differentiate between a command
 	 * "failure" and an "error" in the transport mechanism.
 	 */
@@ -668,13 +693,6 @@
 		US_DEBUGP("-- transport indicates command failure\n");
 		need_auto_sense = 1;
 	}
-	if (result == USB_STOR_TRANSPORT_ERROR) {
-		us->transport_reset(us);
-		US_DEBUGP("-- transport indicates transport failure\n");
-		need_auto_sense = 0;
-		srb->result = DID_ERROR << 16;
-		return;
-	}
 
 	/*
 	 * Also, if we have a short transfer on a command that can't have
@@ -730,6 +748,19 @@
 
 		/* issue the auto-sense command */
 		temp_result = us->transport(us->srb, us);
+
+		/* let's clean up right away */
+		srb->request_buffer = old_request_buffer;
+		srb->request_bufflen = old_request_bufflen;
+		srb->use_sg = old_sg;
+		srb->sc_data_direction = old_sc_data_direction;
+		memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
+
+		if (temp_result == USB_STOR_TRANSPORT_ABORTED) {
+			US_DEBUGP("-- auto-sense aborted\n");
+			srb->result = DID_ABORT << 16;
+			return;
+		}
 		if (temp_result != USB_STOR_TRANSPORT_GOOD) {
 			US_DEBUGP("-- auto-sense failure\n");
 
@@ -760,13 +791,6 @@
 		/* set the result so the higher layers expect this data */
 		srb->result = CHECK_CONDITION << 1;
 
-		/* we're done here, let's clean up */
-		srb->request_buffer = old_request_buffer;
-		srb->request_bufflen = old_request_bufflen;
-		srb->use_sg = old_sg;
-		srb->sc_data_direction = old_sc_data_direction;
-		memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
-
 		/* If things are really okay, then let's show that */
 		if ((srb->sense_buffer[2] & 0xf) == 0x0)
 			srb->result = GOOD << 1;
@@ -789,6 +813,39 @@
 		srb->sense_buffer[0] = 0x0;
 }
 
+/* Abort the currently running scsi command or device reset.
+ */
+void usb_stor_abort_transport(struct us_data *us)
+{
+	int state = atomic_read(&us->sm_state);
+
+	US_DEBUGP("usb_stor_abort_transport called\n");
+
+	/* If the current state is wrong or if there's
+	 *  no srb, then there's nothing to do */
+	if ( !(state == US_STATE_RUNNING || state == US_STATE_RESETTING)
+		    || !us->srb) {
+		US_DEBUGP("-- invalid current state\n");
+		return;
+	}
+	atomic_set(&us->sm_state, US_STATE_ABORTING);
+
+	/* If the state machine is blocked waiting for an URB or an IRQ,
+	 *  let's wake it up */
+
+	/* if we have an URB pending, cancel it */
+	if (us->current_urb->status == -EINPROGRESS) {
+		US_DEBUGP("-- cancelling URB\n");
+		usb_unlink_urb(us->current_urb);
+	}
+
+	/* if we are waiting for an IRQ, simulate it */
+	else if (test_bit(IP_WANTED, &us->bitflags)) {
+		US_DEBUGP("-- simulating missing IRQ\n");
+		usb_stor_CBI_irq(us->irq_urb);
+	}
+}
+
 /*
  * Control/Bulk/Interrupt transport
  */
@@ -804,15 +861,40 @@
 	US_DEBUGP("-- Interrupt Status (0x%x, 0x%x)\n",
 			us->irqbuf[0], us->irqbuf[1]);
 
-	/* reject improper IRQs */
-	if (urb->actual_length != 2) {
-		US_DEBUGP("-- IRQ too short\n");
+	/* has the current command been aborted? */
+	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
+
+		/* was this a wanted interrupt? */
+		if (!test_and_clear_bit(IP_WANTED, &us->bitflags)) {
+			US_DEBUGP("ERROR: Unwanted interrupt received!\n");
+			return;
+		}
+		US_DEBUGP("-- command aborted\n");
+
+		/* wake up the command thread */
+		up(&us->ip_waitq);
 		return;
 	}
 
 	/* is the device removed? */
 	if (urb->status == -ENOENT) {
 		US_DEBUGP("-- device has been removed\n");
+
+		/* was this a wanted interrupt? */
+		if (!test_and_clear_bit(IP_WANTED, &us->bitflags))
+			return;
+
+		/* indicate a transport error -- this is the best we can do */
+		us->irqdata[0] = us->irqdata[1] = 0xFF;
+
+		/* wake up the command thread */
+		up(&us->ip_waitq);
+		return;
+	}
+
+	/* reject improper IRQs */
+	if (urb->actual_length != 2) {
+		US_DEBUGP("-- IRQ too short\n");
 		return;
 	}
 
@@ -823,21 +905,16 @@
 	}
 
 	/* was this a wanted interrupt? */
-	if (!atomic_read(us->ip_wanted)) {
+	if (!test_and_clear_bit(IP_WANTED, &us->bitflags)) {
 		US_DEBUGP("ERROR: Unwanted interrupt received!\n");
 		return;
 	}
-
-	/* adjust the flag */
-	atomic_set(us->ip_wanted, 0);
 		
 	/* copy the valid data */
 	us->irqdata[0] = us->irqbuf[0];
 	us->irqdata[1] = us->irqbuf[1];
 
 	/* wake up the command thread */
-	US_DEBUGP("-- Current value of ip_waitq is: %d\n",
-			atomic_read(&us->ip_waitq.count));
 	up(&(us->ip_waitq));
 }
 
@@ -845,13 +922,13 @@
 {
 	int result;
 
-	/* Set up for status notification */
-	atomic_set(us->ip_wanted, 1);
-
 	/* re-initialize the mutex so that we avoid any races with
 	 * early/late IRQs from previous commands */
 	init_MUTEX_LOCKED(&(us->ip_waitq));
 
+	/* Set up for status notification */
+	set_bit(IP_WANTED, &us->bitflags);
+
 	/* COMMAND STAGE */
 	/* let's send the command via the control pipe */
 	result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0),
@@ -863,22 +940,26 @@
 	US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);
 	if (result < 0) {
 		/* Reset flag for status notification */
-		atomic_set(us->ip_wanted, 0);
+		clear_bit(IP_WANTED, &us->bitflags);
+	}
+
+	/* if the command was aborted, indicate that */
+	if (result == -ENOENT)
+		return USB_STOR_TRANSPORT_ABORTED;
+
+	/* STALL must be cleared when it is detected */
+	if (result == -EPIPE) {
+		US_DEBUGP("-- Stall on control pipe. Clearing\n");
+		result = usb_stor_clear_halt(us,	
+			usb_sndctrlpipe(us->pusb_dev, 0));
 
 		/* if the command was aborted, indicate that */
 		if (result == -ENOENT)
 			return USB_STOR_TRANSPORT_ABORTED;
+		return USB_STOR_TRANSPORT_FAILED;
+	}
 
-		/* STALL must be cleared when they are detected */
-		if (result == -EPIPE) {
-			US_DEBUGP("-- Stall on control pipe. Clearing\n");
-			result = usb_stor_clear_halt(us->pusb_dev,	
-					    usb_sndctrlpipe(us->pusb_dev,
-							    0));
-			US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
-			return USB_STOR_TRANSPORT_FAILED;
-		}
-
+	if (result < 0) {
 		/* Uh oh... serious problem here */
 		return USB_STOR_TRANSPORT_ERROR;
 	}
@@ -887,24 +968,28 @@
 	/* transfer the data payload for this command, if one exists*/
 	if (usb_stor_transfer_length(srb)) {
 		usb_stor_transfer(srb, us);
-		US_DEBUGP("CBI data stage result is 0x%x\n", srb->result);
+		result = srb->result;
+		US_DEBUGP("CBI data stage result is 0x%x\n", result);
 
-		/* if it was aborted, we need to indicate that */
-		if (srb->result == USB_STOR_TRANSPORT_ABORTED) {
+		/* report any errors */
+		if (result == US_BULK_TRANSFER_ABORTED) {
+			clear_bit(IP_WANTED, &us->bitflags);
 			return USB_STOR_TRANSPORT_ABORTED;
 		}
+		if (result == US_BULK_TRANSFER_FAILED) {
+			clear_bit(IP_WANTED, &us->bitflags);
+			return USB_STOR_TRANSPORT_FAILED;
+		}
 	}
 
 	/* STATUS STAGE */
 
 	/* go to sleep until we get this interrupt */
-	US_DEBUGP("Current value of ip_waitq is: %d\n", atomic_read(&us->ip_waitq.count));
 	down(&(us->ip_waitq));
 
-	/* if we were woken up by an abort instead of the actual interrupt */
-	if (atomic_read(us->ip_wanted)) {
-		US_DEBUGP("Did not get interrupt on CBI\n");
-		atomic_set(us->ip_wanted, 0);
+	/* has the current command been aborted? */
+	if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
+		US_DEBUGP("CBI interrupt aborted\n");
 		return USB_STOR_TRANSPORT_ABORTED;
 	}
 
@@ -922,11 +1007,12 @@
 		if (srb->cmnd[0] == REQUEST_SENSE ||
 		    srb->cmnd[0] == INQUIRY)
 			return USB_STOR_TRANSPORT_GOOD;
-		else
-			if (((unsigned char*)us->irq_urb->transfer_buffer)[0])
+		else {
+			if (us->irqdata[0])
 				return USB_STOR_TRANSPORT_FAILED;
 			else
 				return USB_STOR_TRANSPORT_GOOD;
+		}
 	}
 
 	/* If not UFI, we interpret the data as a result code 
@@ -976,10 +1062,12 @@
 		/* a stall is a fatal condition from the device */
 		if (result == -EPIPE) {
 			US_DEBUGP("-- Stall on control pipe. Clearing\n");
-			result = usb_stor_clear_halt(us->pusb_dev, 
-					    usb_sndctrlpipe(us->pusb_dev,
-							    0));
-			US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
+			result = usb_stor_clear_halt(us,
+				usb_sndctrlpipe(us->pusb_dev, 0));
+
+			/* if the command was aborted, indicate that */
+			if (result == -ENOENT)
+				return USB_STOR_TRANSPORT_ABORTED;
 			return USB_STOR_TRANSPORT_FAILED;
 		}
 
@@ -991,11 +1079,16 @@
 	/* transfer the data payload for this command, if one exists*/
 	if (usb_stor_transfer_length(srb)) {
 		usb_stor_transfer(srb, us);
-		US_DEBUGP("CB data stage result is 0x%x\n", srb->result);
+		result = srb->result;
+		US_DEBUGP("CB data stage result is 0x%x\n", result);
 
-		/* if it was aborted, we need to indicate that */
-		if (srb->result == USB_STOR_TRANSPORT_ABORTED)
+		/* report any errors */
+		if (result == US_BULK_TRANSFER_ABORTED) {
 			return USB_STOR_TRANSPORT_ABORTED;
+		}
+		if (result == US_BULK_TRANSFER_FAILED) {
+			return USB_STOR_TRANSPORT_FAILED;
+		}
 	}
 
 	/* STATUS STAGE */
@@ -1016,7 +1109,8 @@
 	int result;
 	int pipe;
 
-	/* issue the command */
+	/* issue the command -- use usb_control_msg() because
+	 *  the state machine is not yet alive */
 	pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
 	result = usb_control_msg(us->pusb_dev, pipe,
 				 US_BULK_GET_MAX_LUN, 
@@ -1034,15 +1128,16 @@
 	/* if we get a STALL, clear the stall */
 	if (result == -EPIPE) {
 		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
-		usb_stor_clear_halt(us->pusb_dev, pipe);
+
+		/* Use usb_clear_halt() because the state machine
+		 *  is not yet alive */
+		usb_clear_halt(us->pusb_dev, pipe);
 	}
 
 	/* return the default -- no LUNs */
 	return 0;
 }
 
-int usb_stor_Bulk_reset(struct us_data *us);
-
 int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
 {
 	struct bulk_cb_wrap bcb;
@@ -1051,10 +1146,6 @@
 	int pipe;
 	int partial;
 
-	/* if the device was removed, then we're already reset */
-	if (!us->pusb_dev)
-		return SUCCESS;
-
 	/* set up the command wrapper */
 	bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb.DataTransferLength = cpu_to_le32(usb_stor_transfer_length(srb));
@@ -1088,7 +1179,12 @@
 	/* if we stall, we need to clear it before we go on */
 	if (result == -EPIPE) {
 		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
-		usb_stor_clear_halt(us->pusb_dev, pipe);
+		result = usb_stor_clear_halt(us, pipe);
+
+		/* if the command was aborted, indicate that */
+		if (result == -ENOENT)
+			return USB_STOR_TRANSPORT_ABORTED;
+		result = -EPIPE;
 	} else if (result) {
 		/* unknown error -- we've got a problem */
 		return USB_STOR_TRANSPORT_ERROR;
@@ -1099,11 +1195,11 @@
 		/* send/receive data payload, if there is any */
 		if (bcb.DataTransferLength) {
 			usb_stor_transfer(srb, us);
-			US_DEBUGP("Bulk data transfer result 0x%x\n", 
-				  srb->result);
+			result = srb->result;
+			US_DEBUGP("Bulk data transfer result 0x%x\n", result);
 
 			/* if it was aborted, we need to indicate that */
-			if (srb->result == USB_STOR_TRANSPORT_ABORTED)
+			if (result == US_BULK_TRANSFER_ABORTED)
 				return USB_STOR_TRANSPORT_ABORTED;
 		}
 	}
@@ -1127,8 +1223,12 @@
 	/* did the attempt to read the CSW fail? */
 	if (result == -EPIPE) {
 		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
-		usb_stor_clear_halt(us->pusb_dev, pipe);
-	       
+		result = usb_stor_clear_halt(us, pipe);
+
+		/* if the command was aborted, indicate that */
+		if (result == -ENOENT)
+			return USB_STOR_TRANSPORT_ABORTED;
+
 		/* get the status again */
 		US_DEBUGP("Attempting to get CSW (2nd try)...\n");
 		result = usb_stor_bulk_msg(us, &bcs, pipe,
@@ -1141,7 +1241,11 @@
 		/* if it fails again, we need a reset and return an error*/
 		if (result == -EPIPE) {
 			US_DEBUGP("clearing halt for pipe 0x%x\n", pipe);
-			usb_stor_clear_halt(us->pusb_dev, pipe);
+			result = usb_stor_clear_halt(us, pipe);
+
+			/* if the command was aborted, indicate that */
+			if (result == -ENOENT)
+				return USB_STOR_TRANSPORT_ABORTED;
 			return USB_STOR_TRANSPORT_ERROR;
 		}
 	}
@@ -1188,46 +1292,117 @@
  * Reset routines
  ***********************************************************************/
 
-/* This issues a CB[I] Reset to the device in question
+struct us_timeout {
+	struct us_data *us;
+	spinlock_t timer_lock;
+};
+
+/* The timeout event handler
  */
-int usb_stor_CB_reset(struct us_data *us)
+static void usb_stor_timeout_handler(unsigned long to__)
 {
-	unsigned char cmd[12];
-	int result;
+	struct us_timeout *to = (struct us_timeout *) to__;
+	struct us_data *us = to->us;
 
-	US_DEBUGP("CB_reset() called\n");
+	US_DEBUGP("Timeout occurred\n");
 
-	/* if the device was removed, then we're already reset */
-	if (!us->pusb_dev)
-		return SUCCESS;
+	/* abort the current request */
+	usb_stor_abort_transport(us);
 
-	memset(cmd, 0xFF, sizeof(cmd));
-	cmd[0] = SEND_DIAGNOSTIC;
-	cmd[1] = 4;
-	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
-				 US_CBI_ADSC, 
-				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-				 0, us->ifnum, cmd, sizeof(cmd), HZ*5);
+	/* let the reset routine know we have finished */
+	spin_unlock(&to->timer_lock);
+}
 
-	if (result < 0) {
-		US_DEBUGP("CB[I] soft reset failed %d\n", result);
-		return FAILED;
-	}
+/* This is the common part of the device reset code.
+ *
+ * It's handy that every transport mechanism uses the control endpoint for
+ * resets.
+ *
+ * Basically, we send a reset with a 20-second timeout, so we don't get
+ * jammed attempting to do the reset.
+ */
+void usb_stor_reset_common(struct us_data *us, u8 request, u8 requesttype,
+		u16 value, u16 index, void *data, u16 size)
+{
+	int result;
+	struct us_timeout timeout_data = {us, SPIN_LOCK_UNLOCKED};
+	struct timer_list timeout_list;
+
+	/* prepare the timeout handler */
+	spin_lock(&timeout_data.timer_lock);
+	init_timer(&timeout_list);
+
+	/* A 20-second timeout may seem rather long, but a LaCie
+	 *  StudioDrive USB2 device takes 16+ seconds to get going
+	 *  following a powerup or USB attach event. */
+
+	timeout_list.expires = jiffies + 20 * HZ;
+	timeout_list.data = (unsigned long) &timeout_data;
+	timeout_list.function = usb_stor_timeout_handler;
+	add_timer(&timeout_list);
+
+	result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0),
+			 request, requesttype, value, index, data, size);
+	if (result < 0)
+		goto Done;
 
 	/* long wait for reset */
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ*6);
 	set_current_state(TASK_RUNNING);
 
-	US_DEBUGP("CB_reset: clearing endpoint halt\n");
-	usb_stor_clear_halt(us->pusb_dev, 
-			    usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
-	usb_stor_clear_halt(us->pusb_dev, 
-			    usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
+	US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
+	result = usb_stor_clear_halt(us,
+		usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
+	if (result < 0)
+		goto Done;
+
+	US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n");
+	result = usb_stor_clear_halt(us,
+		usb_sndbulkpipe(us->pusb_dev, us->ep_out));
+
+	Done:
+
+	/* prevent the timer from coming back to haunt us */
+	if (!del_timer(&timeout_list)) {
+		/* the handler has already started; wait for it to finish */
+		spin_lock(&timeout_data.timer_lock);
+		/* change the abort into a timeout */
+		if (result == -ENOENT)
+			result = -ETIMEDOUT;
+	}
 
-	US_DEBUGP("CB_reset done\n");
 	/* return a result code based on the result of the control message */
-	return SUCCESS;
+	if (result >= 0)
+		US_DEBUGP("Soft reset done\n");
+	else
+		US_DEBUGP("Soft reset failed: %d\n", result);
+
+	if (result == -ETIMEDOUT)
+		us->srb->result = DID_TIME_OUT << 16;
+	else if (result == -ENOENT)
+		us->srb->result = DID_ABORT << 16;
+	else if (result < 0)
+		us->srb->result = DID_ERROR << 16;
+	else
+		us->srb->result = GOOD << 1;
+}
+
+/* This issues a CB[I] Reset to the device in question
+ */
+int usb_stor_CB_reset(struct us_data *us)
+{
+	unsigned char cmd[12];
+
+	US_DEBUGP("CB_reset() called\n");
+
+	memset(cmd, 0xFF, sizeof(cmd));
+	cmd[0] = SEND_DIAGNOSTIC;
+	cmd[1] = 4;
+	usb_stor_reset_common(us, US_CBI_ADSC, 
+				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+				 0, us->ifnum, cmd, sizeof(cmd));
+	return (us->srb->result == GOOD << 1 ? SUCCESS : FAILED);
 }
 
 /* This issues a Bulk-only Reset to the device in question, including
@@ -1235,34 +1410,10 @@
  */
 int usb_stor_Bulk_reset(struct us_data *us)
 {
-	int result;
-
 	US_DEBUGP("Bulk reset requested\n");
 
-	/* if the device was removed, then we're already reset */
-	if (!us->pusb_dev)
-		return SUCCESS;
-
-	result = usb_control_msg(us->pusb_dev, 
-				 usb_sndctrlpipe(us->pusb_dev,0), 
-				 US_BULK_RESET_REQUEST, 
+	usb_stor_reset_common(us, US_BULK_RESET_REQUEST, 
 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-				 0, us->ifnum, NULL, 0, HZ*5);
-
-	if (result < 0) {
-		US_DEBUGP("Bulk soft reset failed %d\n", result);
-		return FAILED;
-	}
-
-	/* long wait for reset */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ*6);
-	set_current_state(TASK_RUNNING);
-
-	usb_stor_clear_halt(us->pusb_dev, 
-			    usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
-	usb_stor_clear_halt(us->pusb_dev, 
-			    usb_sndbulkpipe(us->pusb_dev, us->ep_out));
-	US_DEBUGP("Bulk soft reset completed\n");
-	return SUCCESS;
+				 0, us->ifnum, NULL, 0);
+	return (us->srb->result == GOOD << 1 ? SUCCESS : FAILED);
 }
diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
--- a/drivers/usb/storage/transport.h	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/transport.h	Sat May 11 22:29:14 2002
@@ -1,7 +1,7 @@
 /* Driver for USB Mass Storage compliant devices
  * Transport Functions Header File
  *
- * $Id: transport.h,v 1.15 2001/03/17 20:06:23 jrmayfield Exp $
+ * $Id: transport.h,v 1.18 2002/04/21 02:57:59 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -146,11 +146,12 @@
 
 extern unsigned int usb_stor_transfer_length(Scsi_Cmnd*);
 extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
+extern void usb_stor_abort_transport(struct us_data*);
 extern int usb_stor_transfer_partial(struct us_data*, char*, int);
 extern int usb_stor_bulk_msg(struct us_data*, void*, int, unsigned int,
 		unsigned int*);
 extern int usb_stor_control_msg(struct us_data*, unsigned int, u8, u8,
 		u16, u16, void*, u16);
+extern int usb_stor_clear_halt(struct us_data*, int );
 extern void usb_stor_transfer(Scsi_Cmnd*, struct us_data*);
-extern int usb_stor_clear_halt(struct usb_device*, int );
 #endif
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/unusual_devs.h	Sat May 11 22:29:14 2002
@@ -1,10 +1,10 @@
 /* Driver for USB Mass Storage compliant devices
  * Ununsual Devices File
  *
- * $Id: unusual_devs.h,v 1.25 2002/01/13 06:39:17 mdharm Exp $
+ * $Id: unusual_devs.h,v 1.32 2002/02/25 02:41:24 mdharm Exp $
  *
  * Current development and maintenance by:
- *   (c) 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ *   (c) 2000-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
  * Initial work by:
  *   (c) 2000 Adam J. Richter (adam@yggdrasil.com), Yggdrasil Computing, Inc.
@@ -110,6 +110,13 @@
                "LS-120 Camera",
                US_SC_UFI, US_PR_CBI, NULL, 0),
 
+/* Reported by Peter Wächtler <pwaechtler@loewe-komp.de> */
+UNUSUAL_DEV(  0x04ce, 0x0002, 0x0074, 0x0074,
+		"ScanLogic",
+		"SL11R-IDE 0049SQFP-1.2 A002",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_FIX_INQUIRY ),
+
 /* Most of the following entries were developed with the help of
  * Shuttle/SCM directly.
  */
@@ -198,7 +205,7 @@
 /* This entry is needed because the device reports Sub=ff */
 UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0422, 
 		"Sony",
-		"DSC-S30/S70/S75/505V/F505", 
+		"DSC-S30/S70/S75/505V/F505/F707", 
 		US_SC_SCSI, US_PR_CB, NULL,
 		US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ),
 
@@ -289,9 +296,36 @@
 		"Lexar",
 		"Jumpshot USB CF Reader",
 		US_SC_SCSI, US_PR_JUMPSHOT, NULL,
-		US_FL_MODE_XLATE | US_FL_START_STOP ),
+		US_FL_MODE_XLATE ),
 #endif
 
+/* Reported by Carlos Villegas <cav@uniscope.co.jp>
+ * This device needs an INQUIRY of exactly 36-bytes to function.
+ * That is the only reason this entry is needed.
+ */
+UNUSUAL_DEV(  0x05e3, 0x0700, 0x0000, 0xffff,
+		"SIIG",
+		"CompactFlash Card Reader",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_FIX_INQUIRY ),
+
+/* Reported by Peter Marks <peter.marks@turner.com>
+ * Like the SIIG unit above, this unit needs an INQUIRY to ask for exactly
+ * 36 bytes of data.  No more, no less. That is the only reason this entry
+ * is needed.
+ */
+UNUSUAL_DEV(  0x05e3, 0x0702, 0x0000, 0xffff,
+		"EagleTec",
+		"External Hard Disk",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_FIX_INQUIRY ),
+
+UNUSUAL_DEV(  0x05e3, 0x0700, 0x0000, 0x9999,
+		"Unknown",
+		"GL641USB based CF Card reader",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_FIX_INQUIRY | US_FL_MODE_XLATE),
+
 UNUSUAL_DEV(  0x0644, 0x0000, 0x0100, 0x0100, 
 		"TEAC",
 		"Floppy Drive",
@@ -305,6 +339,14 @@
 		US_FL_SINGLE_LUN | US_FL_START_STOP ),
 #endif
 
+/* Submitted by kedar@centillium
+ * Needed for START_STOP flag, but that is unconfirmed */
+UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0001,
+                "Minolta",
+                "Dimage S304",
+                US_SC_SCSI, US_PR_BULK, NULL,
+                US_FL_START_STOP ),
+
 /* Submitted by f.brugmans@hccnet.nl
  * Needed for START_STOP flag */
 UNUSUAL_DEV( 0x0686, 0x4007, 0x0001, 0x0001,
@@ -381,7 +423,7 @@
 		"Datafab",
 		"MDCFE-B USB CF Reader",
 		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		US_FL_MODE_XLATE | US_FL_START_STOP ),
+		US_FL_MODE_XLATE ),
 
 	/*
 	 * The following Datafab-based devices may or may not work
@@ -398,38 +440,38 @@
 		"SIIG/Datafab",
 		"SIIG/Datafab Memory Stick+CF Reader/Writer",
 		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		US_FL_MODE_XLATE | US_FL_START_STOP ),
+		US_FL_MODE_XLATE ),
 
 UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
 		"Datafab/Unknown",
 		"Datafab-based Reader",
 		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		US_FL_MODE_XLATE | US_FL_START_STOP ),
+		US_FL_MODE_XLATE ),
 
 UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff,
 		"Datafab/Unknown",
 		"Datafab-based Reader",
 		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		US_FL_MODE_XLATE | US_FL_START_STOP ),
+		US_FL_MODE_XLATE ),
 
 UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff,
 		"PNY/Datafab",
 		"PNY/Datafab CF+SM Reader",
 		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		US_FL_MODE_XLATE | US_FL_START_STOP ),
+		US_FL_MODE_XLATE ),
 
 UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
 		"Simple Tech/Datafab",
 		"Simple Tech/Datafab CF+SM Reader",
 		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		US_FL_MODE_XLATE | US_FL_START_STOP ),
+		US_FL_MODE_XLATE ),
 
 /* Submitted by Olaf Hering <olh@suse.de> */
 UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
 		"Datafab Systems, Inc.",
 		"USB to CF + SM Combo (LC1)",
 		US_SC_SCSI, US_PR_DATAFAB, NULL,
-		US_FL_MODE_XLATE | US_FL_START_STOP ),
+		US_FL_MODE_XLATE ),
 #endif
 
 /* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
@@ -451,6 +493,12 @@
  		US_SC_SCSI, US_PR_CB, NULL,
 		US_FL_MODE_XLATE ),
 
+UNUSUAL_DEV(  0x0a16, 0x8888, 0x0100, 0x0100,
+		"IBM",
+		"IBM USB Memory Key",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_FIX_INQUIRY ),
+
 #ifdef CONFIG_USB_STORAGE_ISD200
 UNUSUAL_DEV(  0x0bf6, 0xa001, 0x0100, 0x0110,
                 "ATI",
@@ -459,6 +507,13 @@
                 0 ),
 #endif
 
+/* EasyDisk support. Submitted by Stanislav Karchebny <berk@madfire.net> */
+UNUSUAL_DEV(  0x1065, 0x2136, 0x0000, 0x0001,
+		"Global Channel Solutions",
+		"EasyDisk EDxxxx",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_MODE_XLATE | US_FL_START_STOP | US_FL_FIX_INQUIRY ),
+
 /* Submitted by Brian Hall <brihall@bigfoot.com>
  * Needed for START_STOP flag */
 UNUSUAL_DEV(  0x0c76, 0x0003, 0x0100, 0x0100,
@@ -469,6 +524,8 @@
 
 /* Reported by Dan Pilone <pilone@slac.com>
  * The device needs the flags only.
+ * Also reported by Brian Hall <brihall@bigfoot.com>, again for flags.
+ * I also suspect this device may have a broken serial number.
  */
 UNUSUAL_DEV(  0x1065, 0x2136, 0x0000, 0x9999,
 		"CCYU TECHNOLOGY",
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/usb.c	Sat May 11 22:29:14 2002
@@ -1,9 +1,9 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * $Id: usb.c,v 1.70 2002/01/06 07:14:12 mdharm Exp $
+ * $Id: usb.c,v 1.75 2002/04/22 03:39:43 mdharm Exp $
  *
  * Current development and maintenance by:
- *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
  * Developed with the assistance of:
  *   (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
@@ -315,6 +315,7 @@
 	 * so get rid of all our resources..
 	 */
 	daemonize();
+	reparent_to_init();
 
 	/* avoid getting signals */
 	spin_lock_irq(&current->sigmask_lock);
@@ -409,7 +410,7 @@
 			down(&(us->dev_semaphore));
 
 			/* our device has gone - pretend not ready */
-			if (!us->pusb_dev) {
+			if (atomic_read(&us->sm_state) == US_STATE_DETACHED) {
 				US_DEBUGP("Request is for removed device\n");
 				/* For REQUEST_SENSE, it's the data.  But
 				 * for anything else, it should look like
@@ -433,7 +434,7 @@
 					       sizeof(usb_stor_sense_notready));
 					us->srb->result = CHECK_CONDITION << 1;
 				}
-			} else { /* !us->pusb_dev */
+			} else { /* atomic_read(&us->sm_state) == STATE_DETACHED */
 
 				/* Handle those devices which need us to fake 
 				 * their inquiry data */
@@ -449,7 +450,9 @@
 				} else {
 					/* we've got a command, let's do it! */
 					US_DEBUG(usb_stor_show_command(us->srb));
+					atomic_set(&us->sm_state, US_STATE_RUNNING);
 					us->proto_handler(us->srb, us);
+					atomic_set(&us->sm_state, US_STATE_IDLE);
 				}
 			}
 
@@ -713,6 +716,7 @@
 		/* establish the connection to the new device upon reconnect */
 		ss->ifnum = ifnum;
 		ss->pusb_dev = dev;
+		atomic_set(&ss->sm_state, US_STATE_IDLE);
 
 		/* copy over the endpoint data */
 		if (ep_in)
@@ -955,6 +959,7 @@
 			ss->protocol_name = "Unknown";
 			kfree(ss->current_urb);
 			kfree(ss);
+			usb_dec_dev_use(dev);
 			return NULL;
 			break;
 		}
@@ -962,6 +967,8 @@
 
 		/* allocate an IRQ callback if one is needed */
 		if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) {
+			kfree(ss->current_urb);
+			kfree(ss);
 			usb_dec_dev_use(dev);
 			return NULL;
 		}
@@ -990,6 +997,7 @@
 			unusual_dev->initFunction(ss);
 
 		/* start up our control thread */
+		atomic_set(&ss->sm_state, US_STATE_IDLE);
 		ss->pid = kernel_thread(usb_stor_control_thread, ss,
 					CLONE_VM);
 		if (ss->pid < 0) {
@@ -1006,7 +1014,7 @@
 
 		/* now register	 - our detect function will be called */
 		ss->htmplt.module = THIS_MODULE;
-		scsi_register_host(&ss->htmplt);
+		scsi_register_host(&(ss->htmplt));
 
 		/* lock access to the data structures */
 		down(&us_list_semaphore);
@@ -1066,6 +1074,7 @@
 	/* mark the device as gone */
 	usb_dec_dev_use(ss->pusb_dev);
 	ss->pusb_dev = NULL;
+	atomic_set(&ss->sm_state, US_STATE_DETACHED);
 
 	/* unlock access to the device data structure */
 	up(&(ss->dev_semaphore));
@@ -1112,7 +1121,7 @@
 	 */
 	for (next = us_list; next; next = next->next) {
 		US_DEBUGP("-- calling scsi_unregister_host()\n");
-		scsi_unregister_host(&next->htmplt);
+		scsi_unregister_host(&(next->htmplt));
 	}
 
 	/* While there are still structures, free them.  Note that we are
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h	Sat May 11 22:29:14 2002
+++ b/drivers/usb/storage/usb.h	Sat May 11 22:29:14 2002
@@ -1,7 +1,7 @@
 /* Driver for USB Mass Storage compliant devices
  * Main Header File
  *
- * $Id: usb.h,v 1.18 2001/07/30 00:27:59 mdharm Exp $
+ * $Id: usb.h,v 1.21 2002/04/21 02:57:59 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -102,6 +102,12 @@
 #define US_FL_SCM_MULT_TARG   0x00000020 /* supports multiple targets */
 #define US_FL_FIX_INQUIRY     0x00000040 /* INQUIRY response needs fixing */
 
+#define US_STATE_DETACHED	1	/* State machine states */
+#define US_STATE_IDLE		2
+#define US_STATE_RUNNING	3
+#define US_STATE_RESETTING	4
+#define US_STATE_ABORTING	5
+
 #define USB_STOR_STRING_LEN 32
 
 typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
@@ -152,10 +158,12 @@
 	Scsi_Cmnd		*queue_srb;	 /* the single queue slot */
 	int			action;		 /* what to do		  */
 	int			pid;		 /* control thread	  */
+	atomic_t		sm_state;
 
 	/* interrupt info for CBI devices -- only good if attached */
 	struct semaphore	ip_waitq;	 /* for CBI interrupts	 */
-	atomic_t		ip_wanted[1];	 /* is an IRQ expected?	 */
+	unsigned long		bitflags;	 /* single-bit flags:	 */
+#define IP_WANTED	1			 /* is an IRQ expected?	 */
 
 	/* interrupt communications data */
 	struct semaphore	irq_urb_sem;	 /* to protect irq_urb	 */
@@ -188,4 +196,5 @@
 /* Function to fill an inquiry response. See usb.c for details */
 extern void fill_inquiry_response(struct us_data *us,
 	unsigned char *data, unsigned int data_len);
+
 #endif
