[USBSTOR]
authorMichael Martin <michael.martin@reactos.org>
Tue, 17 May 2011 11:26:25 +0000 (11:26 +0000)
committerMichael Martin <michael.martin@reactos.org>
Tue, 17 May 2011 11:26:25 +0000 (11:26 +0000)
- Add error handling to USBSTOR_CSWCompletionRoutine for errors that can be recovered via reset of pipe/port/controller. Only pipe reset is attempted. WIP.

svn path=/branches/usb-bringup/; revision=51808

drivers/usb/usbstor/error.c
drivers/usb/usbstor/scsi.c
drivers/usb/usbstor/usbstor.h

index 58d3004..936caae 100644 (file)
@@ -103,7 +103,7 @@ USBSTOR_HandleTransferError(
                                break;
                        }
 
-                       DPRINT1("Failed to reset pipe %x\n");
+                       DPRINT1("Failed to reset pipe %x\n", Status);
 
                        //
                        // FIXME: Reset of pipe failed, attempt to reset port
index 8e81327..cc58623 100644 (file)
@@ -102,6 +102,9 @@ USBSTOR_CSWCompletionRoutine(
     PREAD_CAPACITY_DATA_EX CapacityDataEx;
     PREAD_CAPACITY_DATA CapacityData;
     PUFI_CAPACITY_RESPONSE Response;
+    PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData;
+    NTSTATUS Status;
+    PURB Urb;
 
     DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p\n", Irp, Ctx);
 
@@ -153,16 +156,75 @@ USBSTOR_CSWCompletionRoutine(
         Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
         ASSERT(Request);
 
-        //
-        // FIXME: check status
-        //
-        Request->SrbStatus = SRB_STATUS_SUCCESS;
+        Status = Irp->IoStatus.Status;
+
+        Urb = &Context->Urb;
 
         //
         // get SCSI command data block
         //
         pCDB = (PCDB)Request->Cdb;
 
+        //
+        // check status
+        //
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Status %x\n", Status);
+            DPRINT1("UrbStatus %x\n", Urb->UrbHeader.Status);
+
+            //
+            // Check for errors that can be handled
+            // FIXME: Verify all usb errors that can be recovered via pipe reset/port reset/controller reset
+            //
+            if ((Urb->UrbHeader.Status & USB_RECOVERABLE_ERRORS) == Urb->UrbHeader.Status)
+            {
+                DPRINT1("Attempting Error Recovery\n");
+                //
+                // If a Read Capacity Request free TransferBuffer
+                //
+                if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
+                {
+                    FreeItem(Context->TransferData);
+                }
+
+                //
+                // Clean up the rest
+                //
+                FreeItem(Context->cbw);
+                FreeItem(Context);
+
+                //
+                // Allocate Work Item Data
+                //
+                ErrorHandlerWorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(ERRORHANDLER_WORKITEM_DATA), USB_STOR_TAG);
+                if (!ErrorHandlerWorkItemData)
+                {
+                    DPRINT1("Failed to allocate memory\n");
+                    Status = STATUS_INSUFFICIENT_RESOURCES;
+                }
+                else
+                {
+                    //
+                    // Initialize and queue the work item to handle the error
+                    //
+                    ExInitializeWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem,
+                                        ErrorHandlerWorkItemRoutine,
+                                        ErrorHandlerWorkItemData);
+    
+                    ErrorHandlerWorkItemData->DeviceObject = Context->FDODeviceExtension->FunctionalDeviceObject;
+                    ErrorHandlerWorkItemData->Irp = Irp;
+                    ErrorHandlerWorkItemData->Context = Context;
+                    DPRINT1("Queuing WorkItemROutine\n");
+                    ExQueueWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem, DelayedWorkQueue);
+
+                    return STATUS_MORE_PROCESSING_REQUIRED;
+                }
+            }
+        }
+
+        Request->SrbStatus = SRB_STATUS_SUCCESS;
+
         //
         // read capacity needs special work
         //
index 0da2c56..6e12ffe 100644 (file)
@@ -35,6 +35,9 @@
                   ((((unsigned long)(n) & 0xFF0000)) >> 8) | \
                   ((((unsigned long)(n) & 0xFF000000)) >> 24))
 
+#define USB_RECOVERABLE_ERRORS (USBD_STATUS_STALL_PID | USBD_STATUS_DEV_NOT_RESPONDING \
+       | USBD_STATUS_ENDPOINT_HALTED | USBD_STATUS_NO_BANDWIDTH)
+
 NTSTATUS NTAPI
 IoAttachDeviceToDeviceStackSafe(
   IN PDEVICE_OBJECT SourceDevice,
@@ -278,6 +281,13 @@ typedef struct
     PKEVENT Event;
 }IRP_CONTEXT, *PIRP_CONTEXT;
 
+typedef struct _ERRORHANDLER_WORKITEM_DATA
+{
+       PDEVICE_OBJECT DeviceObject;
+       PIRP Irp;
+       PIRP_CONTEXT Context;
+       WORK_QUEUE_ITEM WorkQueueItem;
+} ERRORHANDLER_WORKITEM_DATA, *PERRORHANDLER_WORKITEM_DATA;
 
 
 //---------------------------------------------------------------------
@@ -424,6 +434,11 @@ VOID
 USBSTOR_QueueInitialize(
     PFDO_DEVICE_EXTENSION FDODeviceExtension);
 
+VOID
+NTAPI
+ErrorHandlerWorkItemRoutine(
+       PVOID Context);
+
 VOID
 USBSTOR_QueueNextRequest(
     IN PDEVICE_OBJECT DeviceObject);
@@ -431,4 +446,4 @@ USBSTOR_QueueNextRequest(
 VOID
 USBSTOR_QueueTerminateRequest(
     IN PDEVICE_OBJECT DeviceObject,
-    IN BOOLEAN ModifySrbState);
\ No newline at end of file
+    IN BOOLEAN ModifySrbState);