mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 04:35:53 +00:00
[USBSTOR_NEW] Create usbstor_new based on usbstor in order to contain Vadim Galyant's work.
This commit is contained in:
parent
d7c47feb25
commit
94e0942644
14 changed files with 6991 additions and 0 deletions
410
drivers/usb/usbstor_new/error.c
Normal file
410
drivers/usb/usbstor_new/error.c
Normal file
|
@ -0,0 +1,410 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/usb/usbstor/error.c
|
||||
* PURPOSE: USB block storage device driver.
|
||||
* PROGRAMMERS:
|
||||
* James Tabor
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||
*/
|
||||
|
||||
#include "usbstor.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
NTSTATUS
|
||||
USBSTOR_GetEndpointStatus(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN UCHAR bEndpointAddress,
|
||||
OUT PUSHORT Value)
|
||||
{
|
||||
PURB Urb;
|
||||
NTSTATUS Status;
|
||||
|
||||
//
|
||||
// allocate urb
|
||||
//
|
||||
DPRINT("Allocating URB\n");
|
||||
Urb = (PURB)AllocateItem(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
|
||||
if (!Urb)
|
||||
{
|
||||
//
|
||||
// out of memory
|
||||
//
|
||||
DPRINT1("OutofMemory!\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// build status
|
||||
//
|
||||
UsbBuildGetStatusRequest(Urb, URB_FUNCTION_GET_STATUS_FROM_ENDPOINT, bEndpointAddress & 0x0F, Value, NULL, NULL);
|
||||
|
||||
//
|
||||
// send the request
|
||||
//
|
||||
DPRINT1("Sending Request DeviceObject %p, Urb %p\n", DeviceObject, Urb);
|
||||
Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
|
||||
|
||||
//
|
||||
// free urb
|
||||
//
|
||||
FreeItem(Urb);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NTSTATUS
|
||||
USBSTOR_ResetPipeWithHandle(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN USBD_PIPE_HANDLE PipeHandle)
|
||||
{
|
||||
PURB Urb;
|
||||
NTSTATUS Status;
|
||||
|
||||
//
|
||||
// allocate urb
|
||||
//
|
||||
DPRINT("Allocating URB\n");
|
||||
Urb = (PURB)AllocateItem(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
|
||||
if (!Urb)
|
||||
{
|
||||
//
|
||||
// out of memory
|
||||
//
|
||||
DPRINT1("OutofMemory!\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// initialize the urb
|
||||
//
|
||||
Urb->UrbPipeRequest.Hdr.Length = sizeof(struct _URB_PIPE_REQUEST);
|
||||
Urb->UrbPipeRequest.Hdr.Function = URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL;
|
||||
Urb->UrbPipeRequest.PipeHandle = PipeHandle;
|
||||
|
||||
//
|
||||
// send the request
|
||||
//
|
||||
DPRINT1("Sending Request DeviceObject %p, Urb %p\n", DeviceObject, Urb);
|
||||
Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
|
||||
|
||||
//
|
||||
// free urb
|
||||
//
|
||||
FreeItem(Urb);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
USBSTOR_HandleTransferError(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP_CONTEXT Context)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PSCSI_REQUEST_BLOCK Request;
|
||||
PCDB pCDB;
|
||||
|
||||
//
|
||||
// sanity checks
|
||||
//
|
||||
ASSERT(Context);
|
||||
ASSERT(Context->PDODeviceExtension);
|
||||
ASSERT(Context->PDODeviceExtension->Self);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 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);
|
||||
|
||||
if (Status != STATUS_SUCCESS || Context->RetryCount >= 1)
|
||||
{
|
||||
//
|
||||
// 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);
|
||||
|
||||
//
|
||||
// srb handling finished
|
||||
//
|
||||
Context->FDODeviceExtension->SrbErrorHandlingActive = FALSE;
|
||||
|
||||
//
|
||||
// clear timer srb
|
||||
//
|
||||
Context->FDODeviceExtension->LastTimerActiveSrb = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Retrying Count %lu %p\n", Context->RetryCount, Context->PDODeviceExtension->Self);
|
||||
|
||||
//
|
||||
// re-schedule request
|
||||
//
|
||||
USBSTOR_HandleExecuteSCSI(Context->PDODeviceExtension->Self, Context->Irp, Context->RetryCount + 1);
|
||||
|
||||
//
|
||||
// srb error handling finished
|
||||
//
|
||||
Context->FDODeviceExtension->SrbErrorHandlingActive = FALSE;
|
||||
|
||||
//
|
||||
// srb error handling finished
|
||||
//
|
||||
Context->FDODeviceExtension->TimerWorkQueueEnabled = TRUE;
|
||||
|
||||
//
|
||||
// clear timer srb
|
||||
//
|
||||
Context->FDODeviceExtension->LastTimerActiveSrb = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
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);
|
||||
|
||||
//
|
||||
// now resend the csw as the stall got cleared
|
||||
//
|
||||
USBSTOR_SendCSW(WorkItemData->Context, WorkItemData->Irp);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ErrorHandlerWorkItemRoutine(
|
||||
PVOID Context)
|
||||
{
|
||||
PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
|
||||
|
||||
if (WorkItemData->Context->ErrorIndex == 2)
|
||||
{
|
||||
//
|
||||
// reset device
|
||||
//
|
||||
USBSTOR_HandleTransferError(WorkItemData->DeviceObject, WorkItemData->Context);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// clear stall
|
||||
//
|
||||
USBSTOR_ResetHandlerWorkItemRoutine(WorkItemData);
|
||||
}
|
||||
|
||||
//
|
||||
// Free Work Item Data
|
||||
//
|
||||
ExFreePoolWithTag(WorkItemData, USB_STOR_TAG);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
USBSTOR_TimerWorkerRoutine(
|
||||
IN PVOID Context)
|
||||
{
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
NTSTATUS Status;
|
||||
PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)WorkItemData->DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification
|
||||
//
|
||||
Status = USBSTOR_ResetDevice(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// step 2 reset bulk in pipe section 5.3.4
|
||||
//
|
||||
Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// finally reset bulk out pipe
|
||||
//
|
||||
Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle);
|
||||
}
|
||||
}
|
||||
DPRINT1("Status %x\n", Status);
|
||||
|
||||
//
|
||||
// clear timer srb
|
||||
//
|
||||
FDODeviceExtension->LastTimerActiveSrb = NULL;
|
||||
|
||||
//
|
||||
// re-schedule request
|
||||
//
|
||||
//USBSTOR_HandleExecuteSCSI(WorkItemData->Context->PDODeviceExtension->Self, WorkItemData->Context->Irp, Context->RetryCount + 1);
|
||||
|
||||
|
||||
|
||||
//
|
||||
// do not retry for the same packet again
|
||||
//
|
||||
FDODeviceExtension->TimerWorkQueueEnabled = FALSE;
|
||||
|
||||
//
|
||||
// Free Work Item Data
|
||||
//
|
||||
ExFreePoolWithTag(WorkItemData, USB_STOR_TAG);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
USBSTOR_TimerRoutine(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PVOID Context)
|
||||
{
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
BOOLEAN ResetDevice = FALSE;
|
||||
PERRORHANDLER_WORKITEM_DATA WorkItemData;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Context;
|
||||
DPRINT1("[USBSTOR] TimerRoutine entered\n");
|
||||
DPRINT1("[USBSTOR] ActiveSrb %p ResetInProgress %x LastTimerActiveSrb %p\n", FDODeviceExtension->ActiveSrb, FDODeviceExtension->ResetInProgress, FDODeviceExtension->LastTimerActiveSrb);
|
||||
|
||||
//
|
||||
// acquire spinlock
|
||||
//
|
||||
KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
|
||||
|
||||
//
|
||||
// is there an active srb and no global reset is in progress
|
||||
//
|
||||
if (FDODeviceExtension->ActiveSrb && FDODeviceExtension->ResetInProgress == FALSE && FDODeviceExtension->TimerWorkQueueEnabled)
|
||||
{
|
||||
if (FDODeviceExtension->LastTimerActiveSrb != NULL && FDODeviceExtension->LastTimerActiveSrb == FDODeviceExtension->ActiveSrb)
|
||||
{
|
||||
//
|
||||
// check if empty
|
||||
//
|
||||
DPRINT1("[USBSTOR] ActiveSrb %p hang detected\n", FDODeviceExtension->ActiveSrb);
|
||||
ResetDevice = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// update pointer
|
||||
//
|
||||
FDODeviceExtension->LastTimerActiveSrb = FDODeviceExtension->ActiveSrb;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// reset srb
|
||||
//
|
||||
FDODeviceExtension->LastTimerActiveSrb = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// release lock
|
||||
//
|
||||
KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock);
|
||||
|
||||
|
||||
if (ResetDevice && FDODeviceExtension->TimerWorkQueueEnabled && FDODeviceExtension->SrbErrorHandlingActive == FALSE)
|
||||
{
|
||||
WorkItemData = ExAllocatePoolWithTag(NonPagedPool,
|
||||
sizeof(ERRORHANDLER_WORKITEM_DATA),
|
||||
USB_STOR_TAG);
|
||||
if (WorkItemData)
|
||||
{
|
||||
//
|
||||
// Initialize and queue the work item to handle the error
|
||||
//
|
||||
ExInitializeWorkItem(&WorkItemData->WorkQueueItem,
|
||||
USBSTOR_TimerWorkerRoutine,
|
||||
WorkItemData);
|
||||
|
||||
WorkItemData->DeviceObject = FDODeviceExtension->FunctionalDeviceObject;
|
||||
|
||||
DPRINT1("[USBSTOR] Queing Timer WorkItem\n");
|
||||
ExQueueWorkItem(&WorkItemData->WorkQueueItem, DelayedWorkQueue);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue