mirror of
https://github.com/reactos/reactos.git
synced 2025-07-27 20:32:18 +00:00
[USBSTOR] Refactor device reset and pipe reset code.
Return correct status codes from completion routines. Reject requests while the device is being reset
This commit is contained in:
parent
aaa90f6986
commit
7bb93db372
6 changed files with 175 additions and 184 deletions
|
@ -5,6 +5,7 @@
|
||||||
* COPYRIGHT: 2005-2006 James Tabor
|
* COPYRIGHT: 2005-2006 James Tabor
|
||||||
* 2011-2012 Michael Martin (michael.martin@reactos.org)
|
* 2011-2012 Michael Martin (michael.martin@reactos.org)
|
||||||
* 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
|
* 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||||
|
* 2019 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "usbstor.h"
|
#include "usbstor.h"
|
||||||
|
@ -69,104 +70,97 @@ USBSTOR_ResetPipeWithHandle(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
USBSTOR_HandleTransferError(
|
|
||||||
PDEVICE_OBJECT DeviceObject,
|
|
||||||
PIRP_CONTEXT Context)
|
|
||||||
{
|
|
||||||
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
|
||||||
PIO_STACK_LOCATION Stack;
|
|
||||||
PSCSI_REQUEST_BLOCK Request;
|
|
||||||
PCDB pCDB;
|
|
||||||
|
|
||||||
ASSERT(Context);
|
|
||||||
ASSERT(Context->Irp);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Stack = IoGetCurrentIrpStackLocation(Context->Irp);
|
|
||||||
ASSERT(Stack->DeviceObject);
|
|
||||||
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)Stack->DeviceObject->DeviceExtension;
|
|
||||||
|
|
||||||
Request = (PSCSI_REQUEST_BLOCK)Stack->Parameters.Others.Argument1;
|
|
||||||
ASSERT(Request);
|
|
||||||
|
|
||||||
// obtain request type
|
|
||||||
pCDB = (PCDB)Request->Cdb;
|
|
||||||
ASSERT(pCDB);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
// Complete the master IRP
|
|
||||||
Context->Irp->IoStatus.Status = Status;
|
|
||||||
Context->Irp->IoStatus.Information = 0;
|
|
||||||
USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Context->Irp);
|
|
||||||
IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
|
|
||||||
|
|
||||||
// Start the next request
|
|
||||||
USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
|
|
||||||
|
|
||||||
// srb handling finished
|
|
||||||
Context->FDODeviceExtension->SrbErrorHandlingActive = FALSE;
|
|
||||||
|
|
||||||
// clear timer srb
|
|
||||||
Context->FDODeviceExtension->LastTimerActiveSrb = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeItem(Context);
|
|
||||||
|
|
||||||
DPRINT1("USBSTOR_HandleTransferError returning with Status %x\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
USBSTOR_ResetHandlerWorkItemRoutine(
|
USBSTOR_ResetPipeWorkItemRoutine(
|
||||||
PVOID Context)
|
IN PDEVICE_OBJECT FdoDevice,
|
||||||
|
IN PVOID Ctx)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
|
PIRP_CONTEXT Context = (PIRP_CONTEXT)Ctx;
|
||||||
|
PFDO_DEVICE_EXTENSION FDODeviceExtension = (PFDO_DEVICE_EXTENSION)FdoDevice->DeviceExtension;
|
||||||
|
|
||||||
// clear stall on BulkIn pipe
|
// clear stall on the corresponding pipe
|
||||||
Status = USBSTOR_ResetPipeWithHandle(WorkItemData->Context->FDODeviceExtension->LowerDeviceObject, WorkItemData->Context->FDODeviceExtension->InterfaceInformation->Pipes[WorkItemData->Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle);
|
Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, Context->Urb.UrbBulkOrInterruptTransfer.PipeHandle);
|
||||||
DPRINT1("USBSTOR_ResetPipeWithHandle Status %x\n", Status);
|
DPRINT1("USBSTOR_ResetPipeWithHandle Status %x\n", Status);
|
||||||
|
|
||||||
// now resend the csw as the stall got cleared
|
// now resend the csw as the stall got cleared
|
||||||
USBSTOR_SendCSWRequest(WorkItemData->Context, WorkItemData->Irp);
|
USBSTOR_SendCSWRequest(Context, Context->Irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
ErrorHandlerWorkItemRoutine(
|
USBSTOR_ResetDeviceWorkItemRoutine(
|
||||||
PVOID Context)
|
IN PDEVICE_OBJECT FdoDevice,
|
||||||
|
IN PVOID Context)
|
||||||
{
|
{
|
||||||
PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||||
|
UINT32 ix;
|
||||||
|
NTSTATUS Status;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
if (WorkItemData->Context->ErrorIndex == 2)
|
DPRINT("USBSTOR_ResetDeviceWorkItemRoutine\n");
|
||||||
|
|
||||||
|
FDODeviceExtension = FdoDevice->DeviceExtension;
|
||||||
|
|
||||||
|
for (ix = 0; ix < 3; ++ix)
|
||||||
{
|
{
|
||||||
// reset device
|
// first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification
|
||||||
USBSTOR_HandleTransferError(WorkItemData->DeviceObject, WorkItemData->Context);
|
Status = USBSTOR_ResetDevice(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension);
|
||||||
}
|
if (NT_SUCCESS(Status))
|
||||||
else
|
{
|
||||||
{
|
// step 2 reset bulk in pipe section 5.3.4
|
||||||
// clear stall
|
Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle);
|
||||||
USBSTOR_ResetHandlerWorkItemRoutine(WorkItemData);
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
// finally reset bulk out pipe
|
||||||
|
Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free Work Item Data
|
KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldIrql);
|
||||||
ExFreePoolWithTag(WorkItemData, USB_STOR_TAG);
|
FDODeviceExtension->Flags &= ~USBSTOR_FDO_FLAGS_DEVICE_RESETTING;
|
||||||
|
KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldIrql);
|
||||||
|
|
||||||
|
USBSTOR_QueueNextRequest(FdoDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
USBSTOR_QueueResetPipe(
|
||||||
|
IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
|
||||||
|
IN PIRP_CONTEXT Context)
|
||||||
|
{
|
||||||
|
DPRINT("USBSTOR_QueueResetPipe\n");
|
||||||
|
|
||||||
|
IoQueueWorkItem(FDODeviceExtension->ResetDeviceWorkItem,
|
||||||
|
USBSTOR_ResetPipeWorkItemRoutine,
|
||||||
|
CriticalWorkQueue,
|
||||||
|
Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
USBSTOR_QueueResetDevice(
|
||||||
|
IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
DPRINT("USBSTOR_QueueResetDevice\n");
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldIrql);
|
||||||
|
FDODeviceExtension->Flags |= USBSTOR_FDO_FLAGS_DEVICE_RESETTING;
|
||||||
|
KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldIrql);
|
||||||
|
|
||||||
|
IoQueueWorkItem(FDODeviceExtension->ResetDeviceWorkItem,
|
||||||
|
USBSTOR_ResetDeviceWorkItemRoutine,
|
||||||
|
CriticalWorkQueue,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -219,12 +213,12 @@ USBSTOR_TimerRoutine(
|
||||||
|
|
||||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Context;
|
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Context;
|
||||||
DPRINT1("[USBSTOR] TimerRoutine entered\n");
|
DPRINT1("[USBSTOR] TimerRoutine entered\n");
|
||||||
DPRINT1("[USBSTOR] ActiveSrb %p ResetInProgress %x LastTimerActiveSrb %p\n", FDODeviceExtension->ActiveSrb, FDODeviceExtension->ResetInProgress, FDODeviceExtension->LastTimerActiveSrb);
|
// DPRINT1("[USBSTOR] ActiveSrb %p ResetInProgress %x LastTimerActiveSrb %p\n", FDODeviceExtension->ActiveSrb, FDODeviceExtension->ResetInProgress, FDODeviceExtension->LastTimerActiveSrb);
|
||||||
|
|
||||||
KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
|
KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
|
||||||
|
|
||||||
// is there an active srb and no global reset is in progress
|
// is there an active srb and no global reset is in progress
|
||||||
if (FDODeviceExtension->ActiveSrb && FDODeviceExtension->ResetInProgress == FALSE && FDODeviceExtension->TimerWorkQueueEnabled)
|
if (FDODeviceExtension->ActiveSrb && /* FDODeviceExtension->ResetInProgress == FALSE && */ FDODeviceExtension->TimerWorkQueueEnabled)
|
||||||
{
|
{
|
||||||
if (FDODeviceExtension->LastTimerActiveSrb != NULL && FDODeviceExtension->LastTimerActiveSrb == FDODeviceExtension->ActiveSrb)
|
if (FDODeviceExtension->LastTimerActiveSrb != NULL && FDODeviceExtension->LastTimerActiveSrb == FDODeviceExtension->ActiveSrb)
|
||||||
{
|
{
|
||||||
|
|
|
@ -129,6 +129,7 @@ USBSTOR_FdoHandleStartDevice(
|
||||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
|
PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
UCHAR Index = 0;
|
UCHAR Index = 0;
|
||||||
|
PIO_WORKITEM WorkItem;
|
||||||
|
|
||||||
// forward irp to lower device
|
// forward irp to lower device
|
||||||
Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
|
Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
|
||||||
|
@ -138,6 +139,17 @@ USBSTOR_FdoHandleStartDevice(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!DeviceExtension->ResetDeviceWorkItem)
|
||||||
|
{
|
||||||
|
WorkItem = IoAllocateWorkItem(DeviceObject);
|
||||||
|
DeviceExtension->ResetDeviceWorkItem = WorkItem;
|
||||||
|
|
||||||
|
if (!WorkItem)
|
||||||
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// initialize irp queue
|
// initialize irp queue
|
||||||
USBSTOR_QueueInitialize(DeviceExtension);
|
USBSTOR_QueueInitialize(DeviceExtension);
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ USBSTOR_QueueAddIrp(
|
||||||
KeClearEvent(&FDODeviceExtension->NoPendingRequests);
|
KeClearEvent(&FDODeviceExtension->NoPendingRequests);
|
||||||
|
|
||||||
// check if queue is freezed
|
// check if queue is freezed
|
||||||
IrpListFreeze = FDODeviceExtension->IrpListFreeze;
|
IrpListFreeze = BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE);
|
||||||
|
|
||||||
KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
|
KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ USBSTOR_QueueNextRequest(
|
||||||
|
|
||||||
// check first if there's already a request pending or the queue is frozen
|
// check first if there's already a request pending or the queue is frozen
|
||||||
if (FDODeviceExtension->ActiveSrb != NULL ||
|
if (FDODeviceExtension->ActiveSrb != NULL ||
|
||||||
FDODeviceExtension->IrpListFreeze)
|
BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE))
|
||||||
{
|
{
|
||||||
// no work to do yet
|
// no work to do yet
|
||||||
return;
|
return;
|
||||||
|
@ -274,7 +274,7 @@ USBSTOR_QueueRelease(
|
||||||
KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
|
KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
|
||||||
|
|
||||||
// clear freezed status
|
// clear freezed status
|
||||||
FDODeviceExtension->IrpListFreeze = FALSE;
|
FDODeviceExtension->Flags &= ~USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE;
|
||||||
|
|
||||||
KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
|
KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
|
||||||
|
|
||||||
|
@ -302,6 +302,7 @@ USBSTOR_StartIo(
|
||||||
PIRP Irp)
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PSCSI_REQUEST_BLOCK Request;
|
||||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||||
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
KIRQL OldLevel;
|
KIRQL OldLevel;
|
||||||
|
@ -332,26 +333,26 @@ USBSTOR_StartIo(
|
||||||
|
|
||||||
IoReleaseCancelSpinLock(OldLevel);
|
IoReleaseCancelSpinLock(OldLevel);
|
||||||
|
|
||||||
KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
|
KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldLevel);
|
||||||
|
ResetInProgress = BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_DEVICE_RESETTING);
|
||||||
ResetInProgress = FDODeviceExtension->ResetInProgress;
|
KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldLevel);
|
||||||
ASSERT(ResetInProgress == FALSE);
|
|
||||||
|
|
||||||
KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
|
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
|
||||||
|
Request = IoStack->Parameters.Scsi.Srb;
|
||||||
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
|
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
|
||||||
|
|
||||||
// TODO: this condition is always false
|
|
||||||
if (ResetInProgress)
|
if (ResetInProgress)
|
||||||
{
|
{
|
||||||
// hard reset is in progress
|
// hard reset is in progress
|
||||||
|
Request->SrbStatus = SRB_STATUS_NO_DEVICE;
|
||||||
|
Request->DataTransferLength = 0;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
|
Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
|
||||||
USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
|
USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
USBSTOR_QueueNextRequest(DeviceObject);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,40 +116,6 @@ USBSTOR_IsCSWValid(
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
USBSTOR_QueueWorkItem(
|
|
||||||
PIRP_CONTEXT Context,
|
|
||||||
PIRP Irp)
|
|
||||||
{
|
|
||||||
PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData;
|
|
||||||
|
|
||||||
ErrorHandlerWorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(ERRORHANDLER_WORKITEM_DATA), USB_STOR_TAG);
|
|
||||||
if (!ErrorHandlerWorkItemData)
|
|
||||||
{
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
// error handling started
|
|
||||||
Context->FDODeviceExtension->SrbErrorHandlingActive = TRUE;
|
|
||||||
|
|
||||||
// srb error handling finished
|
|
||||||
Context->FDODeviceExtension->TimerWorkQueueEnabled = FALSE;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
USBSTOR_IssueRequestSense(
|
USBSTOR_IssueRequestSense(
|
||||||
|
@ -172,12 +138,17 @@ USBSTOR_CSWCompletionRoutine(
|
||||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||||
PSCSI_REQUEST_BLOCK Request;
|
PSCSI_REQUEST_BLOCK Request;
|
||||||
PUFI_CAPACITY_RESPONSE Response;
|
PUFI_CAPACITY_RESPONSE Response;
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
Context = (PIRP_CONTEXT)Ctx;
|
Context = (PIRP_CONTEXT)Ctx;
|
||||||
|
|
||||||
DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
|
DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
|
||||||
|
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
|
||||||
|
FDODeviceExtension = Context->FDODeviceExtension;
|
||||||
|
Request = IoStack->Parameters.Scsi.Srb;
|
||||||
|
ASSERT(Request);
|
||||||
|
|
||||||
// first check for Irp errors
|
// first check for Irp errors
|
||||||
if (!NT_SUCCESS(Irp->IoStatus.Status))
|
if (!NT_SUCCESS(Irp->IoStatus.Status))
|
||||||
{
|
{
|
||||||
|
@ -188,9 +159,7 @@ USBSTOR_CSWCompletionRoutine(
|
||||||
++Context->StallRetryCount;
|
++Context->StallRetryCount;
|
||||||
|
|
||||||
// clear stall and resend cbw
|
// clear stall and resend cbw
|
||||||
Context->ErrorIndex = 1;
|
USBSTOR_QueueResetPipe(FDODeviceExtension, Context);
|
||||||
Status = USBSTOR_QueueWorkItem(Context, Irp);
|
|
||||||
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
|
||||||
|
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
}
|
}
|
||||||
|
@ -200,29 +169,15 @@ USBSTOR_CSWCompletionRoutine(
|
||||||
DPRINT1("USBSTOR_CSWCompletionRoutine: Urb.Hdr.Status - %x\n", Context->Urb.UrbHeader.Status);
|
DPRINT1("USBSTOR_CSWCompletionRoutine: Urb.Hdr.Status - %x\n", Context->Urb.UrbHeader.Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// perform reset recovery
|
goto ResetRecovery;
|
||||||
Context->ErrorIndex = 2;
|
|
||||||
Status = USBSTOR_QueueWorkItem(Context, NULL);
|
|
||||||
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// now check the CSW packet validity
|
// now check the CSW packet validity
|
||||||
if (!USBSTOR_IsCSWValid(Context) || Context->csw.Status == CSW_STATUS_PHASE_ERROR)
|
if (!USBSTOR_IsCSWValid(Context) || Context->csw.Status == CSW_STATUS_PHASE_ERROR)
|
||||||
{
|
{
|
||||||
// perform reset recovery
|
goto ResetRecovery;
|
||||||
Context->ErrorIndex = 2;
|
|
||||||
Status = USBSTOR_QueueWorkItem(Context, NULL);
|
|
||||||
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
||||||
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
|
|
||||||
FDODeviceExtension = Context->FDODeviceExtension;
|
|
||||||
Request = IoStack->Parameters.Scsi.Srb;
|
|
||||||
ASSERT(Request);
|
|
||||||
|
|
||||||
// finally check for CSW errors
|
// finally check for CSW errors
|
||||||
if (Context->csw.Status == CSW_STATUS_COMMAND_PASSED)
|
if (Context->csw.Status == CSW_STATUS_COMMAND_PASSED)
|
||||||
{
|
{
|
||||||
|
@ -247,7 +202,7 @@ USBSTOR_CSWCompletionRoutine(
|
||||||
PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
|
PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = USBSTOR_SrbStatusToNtStatus(Request);
|
Irp->IoStatus.Status = USBSTOR_SrbStatusToNtStatus(Request);
|
||||||
}
|
}
|
||||||
else if (Context->csw.Status == CSW_STATUS_COMMAND_FAILED)
|
else if (Context->csw.Status == CSW_STATUS_COMMAND_FAILED)
|
||||||
{
|
{
|
||||||
|
@ -272,10 +227,9 @@ USBSTOR_CSWCompletionRoutine(
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = STATUS_IO_DEVICE_ERROR;
|
Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Status = Status;
|
|
||||||
Irp->IoStatus.Information = Request->DataTransferLength;
|
Irp->IoStatus.Information = Request->DataTransferLength;
|
||||||
|
|
||||||
// terminate current request
|
// terminate current request
|
||||||
|
@ -283,7 +237,21 @@ USBSTOR_CSWCompletionRoutine(
|
||||||
USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
|
USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
|
||||||
|
|
||||||
ExFreePoolWithTag(Context, USB_STOR_TAG);
|
ExFreePoolWithTag(Context, USB_STOR_TAG);
|
||||||
return Status;
|
return STATUS_CONTINUE_COMPLETION;
|
||||||
|
|
||||||
|
ResetRecovery:
|
||||||
|
|
||||||
|
Request = FDODeviceExtension->ActiveSrb;
|
||||||
|
IoStack->Parameters.Scsi.Srb = Request;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
|
||||||
|
Request->SrbStatus = SRB_STATUS_BUS_RESET;
|
||||||
|
|
||||||
|
USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
|
||||||
|
USBSTOR_QueueResetDevice(FDODeviceExtension);
|
||||||
|
|
||||||
|
ExFreePoolWithTag(Context, USB_STOR_TAG);
|
||||||
|
return STATUS_CONTINUE_COMPLETION;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -312,15 +280,16 @@ USBSTOR_DataCompletionRoutine(
|
||||||
PVOID Ctx)
|
PVOID Ctx)
|
||||||
{
|
{
|
||||||
PIRP_CONTEXT Context;
|
PIRP_CONTEXT Context;
|
||||||
NTSTATUS Status;
|
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
PSCSI_REQUEST_BLOCK Request;
|
PSCSI_REQUEST_BLOCK Request;
|
||||||
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
|
|
||||||
DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
|
DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
|
||||||
|
|
||||||
Context = (PIRP_CONTEXT)Ctx;
|
Context = (PIRP_CONTEXT)Ctx;
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
Request = IoStack->Parameters.Scsi.Srb;
|
Request = IoStack->Parameters.Scsi.Srb;
|
||||||
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
// for Sense Request a partial MDL was already freed (if existed)
|
// for Sense Request a partial MDL was already freed (if existed)
|
||||||
if (Request == Context->FDODeviceExtension->ActiveSrb &&
|
if (Request == Context->FDODeviceExtension->ActiveSrb &&
|
||||||
|
@ -351,16 +320,19 @@ USBSTOR_DataCompletionRoutine(
|
||||||
Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength;
|
Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength;
|
||||||
|
|
||||||
// clear stall and resend cbw
|
// clear stall and resend cbw
|
||||||
Context->ErrorIndex = 1;
|
USBSTOR_QueueResetPipe(Context->FDODeviceExtension, Context);
|
||||||
Status = USBSTOR_QueueWorkItem(Context, Irp);
|
|
||||||
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// perform reset recovery
|
Irp->IoStatus.Information = 0;
|
||||||
Context->ErrorIndex = 2;
|
Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
|
||||||
Status = USBSTOR_QueueWorkItem(Context, NULL);
|
Request->SrbStatus = SRB_STATUS_BUS_RESET;
|
||||||
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
|
||||||
|
USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
|
||||||
|
USBSTOR_QueueResetDevice(Context->FDODeviceExtension);
|
||||||
|
|
||||||
|
ExFreePoolWithTag(Context, USB_STOR_TAG);
|
||||||
|
return STATUS_CONTINUE_COMPLETION;
|
||||||
}
|
}
|
||||||
|
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
|
@ -378,17 +350,18 @@ USBSTOR_CBWCompletionRoutine(
|
||||||
PIRP_CONTEXT Context;
|
PIRP_CONTEXT Context;
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
PSCSI_REQUEST_BLOCK Request;
|
PSCSI_REQUEST_BLOCK Request;
|
||||||
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
USBD_PIPE_HANDLE PipeHandle;
|
USBD_PIPE_HANDLE PipeHandle;
|
||||||
ULONG TransferFlags;
|
ULONG TransferFlags;
|
||||||
PMDL Mdl = NULL;
|
PMDL Mdl = NULL;
|
||||||
PVOID TransferBuffer = NULL;
|
PVOID TransferBuffer = NULL;
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
|
DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
|
||||||
|
|
||||||
Context = (PIRP_CONTEXT)Ctx;
|
Context = (PIRP_CONTEXT)Ctx;
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
Request = IoStack->Parameters.Scsi.Srb;
|
Request = IoStack->Parameters.Scsi.Srb;
|
||||||
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
if (!NT_SUCCESS(Irp->IoStatus.Status))
|
if (!NT_SUCCESS(Irp->IoStatus.Status))
|
||||||
{
|
{
|
||||||
|
@ -455,13 +428,8 @@ USBSTOR_CBWCompletionRoutine(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ASSERT(Request->DataBuffer);
|
||||||
TransferBuffer = Request->DataBuffer;
|
TransferBuffer = Request->DataBuffer;
|
||||||
|
|
||||||
if (!Request->DataBuffer)
|
|
||||||
{
|
|
||||||
DPRINT("USBSTOR_CBWCompletionRoutine: Request->DataBuffer == NULL!\n");
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
USBSTOR_IssueBulkOrInterruptRequest(Context->FDODeviceExtension,
|
USBSTOR_IssueBulkOrInterruptRequest(Context->FDODeviceExtension,
|
||||||
|
@ -477,10 +445,17 @@ USBSTOR_CBWCompletionRoutine(
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
|
|
||||||
ResetRecovery:
|
ResetRecovery:
|
||||||
Context->ErrorIndex = 2;
|
Request = Context->FDODeviceExtension->ActiveSrb;
|
||||||
Status = USBSTOR_QueueWorkItem(Context, NULL);
|
IoStack->Parameters.Scsi.Srb = Request;
|
||||||
ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
|
Irp->IoStatus.Information = 0;
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
|
||||||
|
Request->SrbStatus = SRB_STATUS_BUS_RESET;
|
||||||
|
|
||||||
|
USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
|
||||||
|
USBSTOR_QueueResetDevice(Context->FDODeviceExtension);
|
||||||
|
|
||||||
|
ExFreePoolWithTag(Context, USB_STOR_TAG);
|
||||||
|
return STATUS_CONTINUE_COMPLETION;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -40,6 +40,8 @@ USBSTOR_AddDevice(
|
||||||
DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
|
DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
|
||||||
DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
|
DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
|
||||||
|
|
||||||
|
KeInitializeSpinLock(&DeviceExtension->CommonLock);
|
||||||
|
|
||||||
IoInitializeTimer(DeviceObject, USBSTOR_TimerRoutine, (PVOID)DeviceExtension);
|
IoInitializeTimer(DeviceObject, USBSTOR_TimerRoutine, (PVOID)DeviceExtension);
|
||||||
|
|
||||||
// did attaching fail
|
// did attaching fail
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
((((unsigned long)(n) & 0xFF0000)) >> 8) | \
|
((((unsigned long)(n) & 0xFF0000)) >> 8) | \
|
||||||
((((unsigned long)(n) & 0xFF000000)) >> 24))
|
((((unsigned long)(n) & 0xFF000000)) >> 24))
|
||||||
|
|
||||||
|
#ifndef BooleanFlagOn
|
||||||
|
#define BooleanFlagOn(Flags, SingleFlag) ((BOOLEAN)((((Flags) & (SingleFlag)) != 0)))
|
||||||
|
#endif
|
||||||
|
|
||||||
#define USB_RECOVERABLE_ERRORS (USBD_STATUS_STALL_PID | USBD_STATUS_DEV_NOT_RESPONDING \
|
#define USB_RECOVERABLE_ERRORS (USBD_STATUS_STALL_PID | USBD_STATUS_DEV_NOT_RESPONDING \
|
||||||
| USBD_STATUS_ENDPOINT_HALTED | USBD_STATUS_NO_BANDWIDTH)
|
| USBD_STATUS_ENDPOINT_HALTED | USBD_STATUS_NO_BANDWIDTH)
|
||||||
|
|
||||||
|
@ -34,6 +38,9 @@ typedef struct __COMMON_DEVICE_EXTENSION__
|
||||||
|
|
||||||
}USBSTOR_COMMON_DEVICE_EXTENSION, *PUSBSTOR_COMMON_DEVICE_EXTENSION;
|
}USBSTOR_COMMON_DEVICE_EXTENSION, *PUSBSTOR_COMMON_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
#define USBSTOR_FDO_FLAGS_DEVICE_RESETTING 0x00000001 // hard reset is in progress
|
||||||
|
#define USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE 0x00000002 // the irp list is freezed
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
USBSTOR_COMMON_DEVICE_EXTENSION Common; // common device extension
|
USBSTOR_COMMON_DEVICE_EXTENSION Common; // common device extension
|
||||||
|
@ -53,8 +60,6 @@ typedef struct
|
||||||
PDEVICE_OBJECT ChildPDO[16]; // max 16 child pdo devices
|
PDEVICE_OBJECT ChildPDO[16]; // max 16 child pdo devices
|
||||||
KSPIN_LOCK IrpListLock; // irp list lock
|
KSPIN_LOCK IrpListLock; // irp list lock
|
||||||
LIST_ENTRY IrpListHead; // irp list head
|
LIST_ENTRY IrpListHead; // irp list head
|
||||||
BOOLEAN IrpListFreeze; // if true the irp list is freezed
|
|
||||||
BOOLEAN ResetInProgress; // if hard reset is in progress
|
|
||||||
ULONG IrpPendingCount; // count of irp pending
|
ULONG IrpPendingCount; // count of irp pending
|
||||||
PSCSI_REQUEST_BLOCK ActiveSrb; // stores the current active SRB
|
PSCSI_REQUEST_BLOCK ActiveSrb; // stores the current active SRB
|
||||||
KEVENT NoPendingRequests; // set if no pending or in progress requests
|
KEVENT NoPendingRequests; // set if no pending or in progress requests
|
||||||
|
@ -62,6 +67,9 @@ typedef struct
|
||||||
ULONG SrbErrorHandlingActive; // error handling of srb is activated
|
ULONG SrbErrorHandlingActive; // error handling of srb is activated
|
||||||
ULONG TimerWorkQueueEnabled; // timer work queue enabled
|
ULONG TimerWorkQueueEnabled; // timer work queue enabled
|
||||||
ULONG InstanceCount; // pdo instance count
|
ULONG InstanceCount; // pdo instance count
|
||||||
|
KSPIN_LOCK CommonLock;
|
||||||
|
PIO_WORKITEM ResetDeviceWorkItem;
|
||||||
|
ULONG Flags;
|
||||||
}FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
|
}FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -461,18 +469,6 @@ VOID
|
||||||
USBSTOR_QueueInitialize(
|
USBSTOR_QueueInitialize(
|
||||||
PFDO_DEVICE_EXTENSION FDODeviceExtension);
|
PFDO_DEVICE_EXTENSION FDODeviceExtension);
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
ErrorHandlerWorkItemRoutine(
|
|
||||||
PVOID Context);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
ResetHandlerWorkItemRoutine(
|
|
||||||
PVOID Context);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
USBSTOR_QueueNextRequest(
|
USBSTOR_QueueNextRequest(
|
||||||
IN PDEVICE_OBJECT DeviceObject);
|
IN PDEVICE_OBJECT DeviceObject);
|
||||||
|
@ -500,4 +496,15 @@ USBSTOR_TimerRoutine(
|
||||||
PDEVICE_OBJECT DeviceObject,
|
PDEVICE_OBJECT DeviceObject,
|
||||||
PVOID Context);
|
PVOID Context);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
USBSTOR_QueueResetPipe(
|
||||||
|
IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
|
||||||
|
IN PIRP_CONTEXT Context);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
USBSTOR_QueueResetDevice(
|
||||||
|
IN PFDO_DEVICE_EXTENSION FDODeviceExtension);
|
||||||
|
|
||||||
#endif /* _USBSTOR_H_ */
|
#endif /* _USBSTOR_H_ */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue