Author: janderwald
Date: Wed Feb 15 03:52:37 2012
New Revision: 55601
URL:
http://svn.reactos.org/svn/reactos?rev=55601&view=rev
Log:
[USBSTOR]
- Rewrite error handling
- Check if CSW is valid
- Check if the error handling was already started
- Reset device if required
- Error handling was completely broken and did not follow the reset procedure as defined
in USB Mass Storage Specification Bulk Only Section 5.3.4
- Mass storage device now longer hang when receiving the read capacity request and ReactOS
assigns a symbolic link
- Mass storage devices not yet fully working
Modified:
trunk/reactos/drivers/usb/usbstor/error.c
trunk/reactos/drivers/usb/usbstor/misc.c
trunk/reactos/drivers/usb/usbstor/scsi.c
trunk/reactos/drivers/usb/usbstor/usbstor.h
Modified: trunk/reactos/drivers/usb/usbstor/error.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbstor/error.…
==============================================================================
--- trunk/reactos/drivers/usb/usbstor/error.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbstor/error.c [iso-8859-1] Wed Feb 15 03:52:37 2012
@@ -110,104 +110,157 @@
PDEVICE_OBJECT DeviceObject,
PIRP_CONTEXT Context)
{
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION Stack;
- USBD_PIPE_HANDLE PipeHandle;
+ //USBD_PIPE_HANDLE PipeHandle;
PSCSI_REQUEST_BLOCK Request;
PCDB pCDB;
- DPRINT1("Entered Handle Transfer Error\n");
- //
- // Determine pipehandle
- //
- if (Context->cbw->CommandBlock[0] == SCSIOP_WRITE)
- {
- //
- // write request used bulk out pipe
- //
- PipeHandle =
Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkOutPipeIndex].PipeHandle;
+
+ //
+ // first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only
Specification
+ //
+ Status = USBSTOR_ResetDevice(Context->FDODeviceExtension->LowerDeviceObject,
Context->FDODeviceExtension);
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // step 2 reset bulk in pipe section 5.3.4
+ //
+ Status =
USBSTOR_ResetPipeWithHandle(Context->FDODeviceExtension->LowerDeviceObject,
Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle);
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // finally reset bulk out pipe
+ //
+ Status =
USBSTOR_ResetPipeWithHandle(Context->FDODeviceExtension->LowerDeviceObject,
Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkOutPipeIndex].PipeHandle);
+ }
+ }
+
+ if (Context->Irp)
+ {
+ //
+ // get next stack location
+ //
+ Stack = IoGetCurrentIrpStackLocation(Context->Irp);
+
+ //
+ // get request block
+ //
+ Request = (PSCSI_REQUEST_BLOCK)Stack->Parameters.Others.Argument1;
+ ASSERT(Request);
+
+ //
+ // obtain request type
+ //
+ pCDB = (PCDB)Request->Cdb;
+ ASSERT(pCDB);
+
+ //
+ // Cleanup the IRP context
+ if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
+ {
+ FreeItem(Context->TransferData);
+ }
+
+ if (Status != STATUS_SUCCESS)
+ {
+ //
+ // Complete the master IRP
+ //
+ Context->Irp->IoStatus.Status = Status;
+ Context->Irp->IoStatus.Information = 0;
+
USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject,
Context->Irp);
+ IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
+
+ //
+ // Start the next request
+ //
+
USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject);
+ }
}
else
{
- //
- // default bulk in pipe
- //
- PipeHandle =
Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle;
- }
-
- switch (Context->Urb.UrbHeader.Status)
- {
- case USBD_STATUS_STALL_PID:
- {
- //
- // First attempt to reset the pipe
- //
- DPRINT1("Resetting Pipe\n");
- Status =
USBSTOR_ResetPipeWithHandle(Context->FDODeviceExtension->LowerDeviceObject,
PipeHandle);
- if (NT_SUCCESS(Status))
- {
- Status = STATUS_SUCCESS;
- break;
- }
-
- DPRINT1("Failed to reset pipe %x\n", Status);
-
- //
- // FIXME: Reset of pipe failed, attempt to reset port
- //
-
- Status = STATUS_UNSUCCESSFUL;
- break;
- }
- //
- // FIXME: Handle more errors
- //
- default:
- {
- DPRINT1("Error not handled\n");
- Status = STATUS_UNSUCCESSFUL;
- }
- }
-
- Stack = IoGetCurrentIrpStackLocation(Context->Irp);
- Request = (PSCSI_REQUEST_BLOCK)Stack->Parameters.Others.Argument1;
- pCDB = (PCDB)Request->Cdb;
- if (Status != STATUS_SUCCESS)
- {
- /* Complete the master IRP */
- Context->Irp->IoStatus.Status = Status;
- Context->Irp->IoStatus.Information = 0;
-
USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject,
Context->Irp);
- IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
-
- /* Start the next request */
- USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject);
-
- /* Signal the context event */
- if (Context->Event)
+ if (Status != STATUS_SUCCESS)
+ {
+ //
+ // Signal the context event
+ //
+ ASSERT(Context->Event);
KeSetEvent(Context->Event, 0, FALSE);
-
- /* Cleanup the IRP context */
- if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
- FreeItem(Context->TransferData);
- FreeItem(Context->cbw);
- FreeItem(Context);
- }
- else
- {
-
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
DPRINT1("Retrying\n");
- Status =
USBSTOR_HandleExecuteSCSI(*Context->PDODeviceExtension->PDODeviceObject,
Context->Irp);
-
- /* Cleanup the old IRP context */
- if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
- FreeItem(Context->TransferData);
- FreeItem(Context->cbw);
- FreeItem(Context);
- }
+ USBSTOR_HandleExecuteSCSI(*Context->PDODeviceExtension->PDODeviceObject,
Context->Irp);
+ }
+
+ //
+ // cleanup irp context
+ //
+ FreeItem(Context->cbw);
+ FreeItem(Context);
+
DPRINT1("USBSTOR_HandleTransferError returning with Status %x\n", Status);
return Status;
+}
+
+VOID
+NTAPI
+USBSTOR_ResetHandlerWorkItemRoutine(
+ PVOID Context)
+{
+ NTSTATUS Status;
+ USHORT Value;
+ PIO_STACK_LOCATION IoStack;
+
+ PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
+
+ //
+ // clear stall on BulkIn pipe
+ //
+ Status =
USBSTOR_ResetPipeWithHandle(WorkItemData->Context->FDODeviceExtension->LowerDeviceObject,
WorkItemData->Context->FDODeviceExtension->InterfaceInformation->Pipes[WorkItemData->Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle);
+ DPRINT1("USBSTOR_ResetPipeWithHandle Status %x\n", Status);
+
+ //
+ // get next stack location
+ //
+
+ IoStack = IoGetNextIrpStackLocation(WorkItemData->Irp);
+
+ //
+ // now initialize the urb for sending the csw
+ //
+ UsbBuildInterruptOrBulkTransferRequest(&WorkItemData->Context->Urb,
+ sizeof(struct
_URB_BULK_OR_INTERRUPT_TRANSFER),
+
WorkItemData->Context->FDODeviceExtension->InterfaceInformation->Pipes[WorkItemData->Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
+ WorkItemData->Context->csw,
+ NULL,
+ 512, //FIXME
+ USBD_TRANSFER_DIRECTION_IN |
USBD_SHORT_TRANSFER_OK,
+ NULL);
+
+ //
+ // initialize stack location
+ //
+ IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+ IoStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
+ IoStack->Parameters.Others.Argument1 =
(PVOID)&WorkItemData->Context->Urb;
+ IoStack->Parameters.DeviceIoControl.InputBufferLength =
WorkItemData->Context->Urb.UrbHeader.Length;
+ WorkItemData->Irp->IoStatus.Status = STATUS_SUCCESS;
+
+
+ //
+ // setup completion routine
+ //
+ IoSetCompletionRoutine(WorkItemData->Irp, USBSTOR_CSWCompletionRoutine, Context,
TRUE, TRUE, TRUE);
+
+ //
+ // call driver
+ //
+ IoCallDriver(WorkItemData->Context->FDODeviceExtension->LowerDeviceObject,
WorkItemData->Irp);
}
VOID
@@ -217,8 +270,21 @@
{
NTSTATUS Status;
PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
-
- Status = USBSTOR_HandleTransferError(WorkItemData->DeviceObject,
WorkItemData->Context);
+
+ if (WorkItemData->Context->ErrorIndex == 2)
+ {
+ //
+ // reset device
+ //
+ Status = USBSTOR_HandleTransferError(WorkItemData->DeviceObject,
WorkItemData->Context);
+ }
+ else
+ {
+ //
+ // clear stall
+ //
+ USBSTOR_ResetHandlerWorkItemRoutine(WorkItemData);
+ }
//
// Free Work Item Data
Modified: trunk/reactos/drivers/usb/usbstor/misc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbstor/misc.c…
==============================================================================
--- trunk/reactos/drivers/usb/usbstor/misc.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbstor/misc.c [iso-8859-1] Wed Feb 15 03:52:37 2012
@@ -411,7 +411,6 @@
// execute request
//
Status = USBSTOR_ClassRequest(DeviceObject, DeviceExtension, USB_BULK_RESET_DEVICE,
DeviceExtension->InterfaceInformation->InterfaceNumber, USBD_TRANSFER_DIRECTION_OUT,
0, NULL);
- DPRINT1("Status %x\n", Status);
//
// done
Modified: trunk/reactos/drivers/usb/usbstor/scsi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbstor/scsi.c…
==============================================================================
--- trunk/reactos/drivers/usb/usbstor/scsi.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbstor/scsi.c [iso-8859-1] Wed Feb 15 03:52:37 2012
@@ -83,6 +83,75 @@
}
+BOOLEAN
+USBSTOR_IsCSWValid(
+ PIRP_CONTEXT Context)
+{
+ //
+ // sanity checks
+ //
+ if (Context->csw->Signature != CSW_SIGNATURE)
+ {
+ DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE,
Context->csw->Signature);
+ return FALSE;
+ }
+
+ if (Context->csw->Tag != (ULONG)Context->csw)
+ {
+ DPRINT1("[USBSTOR] Expected Tag %x but got %x\n",
(ULONG)Context->csw, Context->csw->Tag);
+ return FALSE;
+ }
+
+ if (Context->csw->Status != 0x00)
+ {
+ DPRINT1("[USBSTOR] Expected Status 0x00 but got %x\n",
Context->csw->Status);
+ return FALSE;
+ }
+
+ //
+ // CSW is valid
+ //
+ return TRUE;
+
+}
+
+NTSTATUS
+USBSTOR_QueueWorkItem(
+ PIRP_CONTEXT Context,
+ PIRP Irp)
+{
+ PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData;
+
+ //
+ // Allocate Work Item Data
+ //
+ ErrorHandlerWorkItemData = ExAllocatePoolWithTag(NonPagedPool,
sizeof(ERRORHANDLER_WORKITEM_DATA), USB_STOR_TAG);
+ if (!ErrorHandlerWorkItemData)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Initialize and queue the work item to handle the error
+ //
+ ExInitializeWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem,
+ ErrorHandlerWorkItemRoutine,
+ ErrorHandlerWorkItemData);
+
+ ErrorHandlerWorkItemData->DeviceObject =
Context->FDODeviceExtension->FunctionalDeviceObject;
+ ErrorHandlerWorkItemData->Context = Context;
+ ErrorHandlerWorkItemData->Irp = Irp;
+ ErrorHandlerWorkItemData->DeviceObject =
Context->FDODeviceExtension->FunctionalDeviceObject;
+
+ DPRINT1("Queuing WorkItemROutine\n");
+ ExQueueWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem, DelayedWorkQueue);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+
//
// driver verifier
//
@@ -102,7 +171,7 @@
PREAD_CAPACITY_DATA_EX CapacityDataEx;
PREAD_CAPACITY_DATA CapacityData;
PUFI_CAPACITY_RESPONSE Response;
- PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData;
+
NTSTATUS Status;
PURB Urb;
@@ -143,6 +212,48 @@
}
}
+ DPRINT1("USBSTOR_CSWCompletionRoutine Status %x\n",
Irp->IoStatus.Status);
+
+ if (!NT_SUCCESS(Irp->IoStatus.Information))
+ {
+ if (Context->ErrorIndex == 0)
+ {
+ //
+ // increment error index
+ //
+ Context->ErrorIndex = 1;
+
+ //
+ // clear stall and resend cbw
+ //
+ Status = USBSTOR_QueueWorkItem(Context, Irp);
+ ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+ //
+ // perform reset recovery
+ //
+ Context->ErrorIndex = 2;
+ IoFreeIrp(Irp);
+ Status = USBSTOR_QueueWorkItem(Context, NULL);
+ ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+ if (!USBSTOR_IsCSWValid(Context))
+ {
+ //
+ // perform reset recovery
+ //
+ Context->ErrorIndex = 2;
+ IoFreeIrp(Irp);
+ Status = USBSTOR_QueueWorkItem(Context, NULL);
+ ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+
if (Context->Irp)
{
//
@@ -164,55 +275,6 @@
// 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");
- //
- // free the allocated irp
- //
- IoFreeIrp(Irp);
-
- //
- // 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->Context = Context;
- DPRINT1("Queuing WorkItemROutine\n");
- ExQueueWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem,
DelayedWorkQueue);
-
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- }
-
Request->SrbStatus = SRB_STATUS_SUCCESS;
//
@@ -268,28 +330,9 @@
}
//
- // sanity checks
- //
- if (Context->csw->Signature != CSW_SIGNATURE)
- {
- DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE,
Context->csw->Signature);
- }
-
- if (Context->csw->Tag != (ULONG)Context->csw)
- {
- DPRINT1("[USBSTOR] Expected Tag %x but got %x\n",
(ULONG)Context->csw, Context->csw->Tag);
- }
-
- if (Context->csw->Status != 0x00)
- {
- DPRINT1("[USBSTOR] Expected Status 0x00 but got %x\n",
Context->csw->Status);
- }
-
- //
// free cbw
//
FreeItem(Context->cbw);
-
if (Context->Irp)
{
@@ -510,6 +553,19 @@
return STATUS_MORE_PROCESSING_REQUIRED;
}
+
+VOID
+DumpCBW(
+ PUCHAR Block)
+{
+ DPRINT1("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x
%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x
%02x\n",
+ Block[0] & 0xFF, Block[1] & 0xFF, Block[2] & 0xFF, Block[3] &
0xFF, Block[4] & 0xFF, Block[5] & 0xFF, Block[6] & 0xFF, Block[7] & 0xFF,
Block[8] & 0xFF, Block[9] & 0xFF,
+ Block[10] & 0xFF, Block[11] & 0xFF, Block[12] & 0xFF, Block[13] &
0xFF, Block[14] & 0xFF, Block[15] & 0xFF, Block[16] & 0xFF, Block[17] &
0xFF, Block[18] & 0xFF, Block[19] & 0xFF,
+ Block[20] & 0xFF, Block[21] & 0xFF, Block[22] & 0xFF, Block[23] &
0xFF, Block[24] & 0xFF, Block[25] & 0xFF, Block[26] & 0xFF, Block[27] &
0xFF, Block[28] & 0xFF, Block[29] & 0xFF,
+ Block[30] & 0xFF);
+
+}
+
NTSTATUS
USBSTOR_SendRequest(
@@ -561,6 +617,7 @@
Context->cbw);
DPRINT("CBW %p\n", Context->cbw);
+ DumpCBW((PUCHAR)Context->cbw);
//
// now initialize the urb
@@ -777,21 +834,6 @@
//
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
- KeResetEvent(&Event);
- DPRINT("Resending request\n");
-
- //
- // now send the request
- //
- Status = USBSTOR_SendRequest(DeviceObject, NULL, &Event, UFI_INQUIRY_CMD_LEN,
(PUCHAR)&Cmd, sizeof(UFI_INQUIRY_RESPONSE), (PUCHAR)Response);
-
- //
- // wait for the action to complete
- //
- KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-
-
-
DPRINT1("Response %p\n", Response);
DPRINT1("DeviceType %x\n", Response->DeviceType);
DPRINT1("RMB %x\n", Response->RMB);
Modified: trunk/reactos/drivers/usb/usbstor/usbstor.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbstor/usbsto…
==============================================================================
--- trunk/reactos/drivers/usb/usbstor/usbstor.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbstor/usbstor.h [iso-8859-1] Wed Feb 15 03:52:37 2012
@@ -279,6 +279,7 @@
PPDO_DEVICE_EXTENSION PDODeviceExtension;
PMDL TransferBufferMDL;
PKEVENT Event;
+ ULONG ErrorIndex;
}IRP_CONTEXT, *PIRP_CONTEXT;
typedef struct _ERRORHANDLER_WORKITEM_DATA
@@ -286,6 +287,7 @@
PDEVICE_OBJECT DeviceObject;
PIRP_CONTEXT Context;
WORK_QUEUE_ITEM WorkQueueItem;
+ PIRP Irp;
} ERRORHANDLER_WORKITEM_DATA, *PERRORHANDLER_WORKITEM_DATA;
@@ -390,6 +392,13 @@
USBSTOR_SendInquiryCmd(
IN PDEVICE_OBJECT DeviceObject);
+NTSTATUS
+NTAPI
+USBSTOR_CSWCompletionRoutine(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Ctx);
+
//---------------------------------------------------------------------
//
// disk.c routines
@@ -443,6 +452,13 @@
PVOID Context);
VOID
+NTAPI
+ResetHandlerWorkItemRoutine(
+ PVOID Context);
+
+
+
+VOID
USBSTOR_QueueNextRequest(
IN PDEVICE_OBJECT DeviceObject);
@@ -458,3 +474,8 @@
IN UCHAR bEndpointAddress,
OUT PUSHORT Value);
+NTSTATUS
+USBSTOR_ResetPipeWithHandle(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN USBD_PIPE_HANDLE PipeHandle);
+