Something went wrong. Try again.
Reactos
Something went wrong. Try again.
11 kB · 410 lines
C
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411/* * 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>
NTSTATUSUSBSTOR_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;}
NTSTATUSUSBSTOR_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;}
NTSTATUSUSBSTOR_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;}
VOIDNTAPIUSBSTOR_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);}
VOIDNTAPIErrorHandlerWorkItemRoutine( 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);}
VOIDNTAPIUSBSTOR_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);}
VOIDNTAPIUSBSTOR_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); } }}