ReactOS  0.4.15-dev-1177-g6cb3b62
error.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3  * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE: USB block storage device driver.
5  * COPYRIGHT: 2005-2006 James Tabor
6  * 2011-2012 Michael Martin (michael.martin@reactos.org)
7  * 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
8  * 2019 Victor Perevertkin (victor.perevertkin@reactos.org)
9  */
10 
11 #include "usbstor.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 
20  IN UCHAR bEndpointAddress,
22 {
23  PURB Urb;
25 
26  DPRINT("Allocating URB\n");
28  if (!Urb)
29  {
30  DPRINT1("OutofMemory!\n");
32  }
33 
34  // build status
36 
37  // send the request
38  DPRINT1("Sending Request DeviceObject %p, Urb %p\n", DeviceObject, Urb);
40 
41  FreeItem(Urb);
42  return Status;
43 }
44 
49 {
50  PURB Urb;
52 
53  DPRINT("Allocating URB\n");
54  Urb = (PURB)AllocateItem(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
55  if (!Urb)
56  {
57  DPRINT1("OutofMemory!\n");
59  }
60 
61  Urb->UrbPipeRequest.Hdr.Length = sizeof(struct _URB_PIPE_REQUEST);
63  Urb->UrbPipeRequest.PipeHandle = PipeHandle;
64 
65  // send the request
66  DPRINT1("Sending Request DeviceObject %p, Urb %p\n", DeviceObject, Urb);
68 
69  FreeItem(Urb);
70  return Status;
71 }
72 
73 VOID
74 NTAPI
76  IN PDEVICE_OBJECT FdoDevice,
77  IN PVOID Ctx)
78 {
80  PFDO_DEVICE_EXTENSION FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Ctx;
81  PIRP_CONTEXT Context = &FDODeviceExtension->CurrentIrpContext;
82 
83  // clear stall on the corresponding pipe
84  Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, Context->Urb.UrbBulkOrInterruptTransfer.PipeHandle);
85  DPRINT1("USBSTOR_ResetPipeWithHandle Status %x\n", Status);
86 
87  // now resend the csw as the stall got cleared
88  USBSTOR_SendCSWRequest(FDODeviceExtension, Context->Irp);
89 }
90 
91 VOID
92 NTAPI
94  IN PDEVICE_OBJECT FdoDevice,
96 {
97  PFDO_DEVICE_EXTENSION FDODeviceExtension;
98  UINT32 ix;
100  KIRQL OldIrql;
101 
102  DPRINT("USBSTOR_ResetDeviceWorkItemRoutine\n");
103 
104  FDODeviceExtension = FdoDevice->DeviceExtension;
105 
106  for (ix = 0; ix < 3; ++ix)
107  {
108  // first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification
109  Status = USBSTOR_ResetDevice(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension);
110  if (NT_SUCCESS(Status))
111  {
112  // step 2 reset bulk in pipe section 5.3.4
113  Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle);
114  if (NT_SUCCESS(Status))
115  {
116  // finally reset bulk out pipe
117  Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle);
118  if (NT_SUCCESS(Status))
119  {
120  break;
121  }
122  }
123  }
124  }
125 
126  KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldIrql);
127  FDODeviceExtension->Flags &= ~USBSTOR_FDO_FLAGS_DEVICE_RESETTING;
128  KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldIrql);
129 
130  USBSTOR_QueueNextRequest(FdoDevice);
131 }
132 
133 VOID
134 NTAPI
136  IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
137 {
138  DPRINT("USBSTOR_QueueResetPipe\n");
139 
140  IoQueueWorkItem(FDODeviceExtension->ResetDeviceWorkItem,
143  FDODeviceExtension);
144 }
145 
146 VOID
147 NTAPI
149  IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
150 {
151  KIRQL OldIrql;
152 
153  DPRINT("USBSTOR_QueueResetDevice\n");
154 
155  KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldIrql);
156  FDODeviceExtension->Flags |= USBSTOR_FDO_FLAGS_DEVICE_RESETTING;
157  KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldIrql);
158 
159  IoQueueWorkItem(FDODeviceExtension->ResetDeviceWorkItem,
162  NULL);
163 }
164 
165 VOID
166 NTAPI
168  IN PVOID Context)
169 {
170  PFDO_DEVICE_EXTENSION FDODeviceExtension;
173 
174  FDODeviceExtension = (PFDO_DEVICE_EXTENSION)WorkItemData->DeviceObject->DeviceExtension;
175  ASSERT(FDODeviceExtension->Common.IsFDO);
176 
177  // first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification
178  Status = USBSTOR_ResetDevice(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension);
179  if (NT_SUCCESS(Status))
180  {
181  // step 2 reset bulk in pipe section 5.3.4
182  Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle);
183  if (NT_SUCCESS(Status))
184  {
185  // finally reset bulk out pipe
186  Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle);
187  }
188  }
189  DPRINT1("Status %x\n", Status);
190 
191  // clear timer srb
192  FDODeviceExtension->LastTimerActiveSrb = NULL;
193 
194  // re-schedule request
195  //USBSTOR_HandleExecuteSCSI(WorkItemData->Context->PDODeviceExtension->Self, WorkItemData->Context->Irp, Context->RetryCount + 1);
196 
197  // do not retry for the same packet again
198  FDODeviceExtension->TimerWorkQueueEnabled = FALSE;
199 
200  ExFreePoolWithTag(WorkItemData, USB_STOR_TAG);
201 }
202 
203 VOID
204 NTAPI
207  PVOID Context)
208 {
209  PFDO_DEVICE_EXTENSION FDODeviceExtension;
211  PERRORHANDLER_WORKITEM_DATA WorkItemData;
212 
213  FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Context;
214  DPRINT1("[USBSTOR] TimerRoutine entered\n");
215  // DPRINT1("[USBSTOR] ActiveSrb %p ResetInProgress %x LastTimerActiveSrb %p\n", FDODeviceExtension->ActiveSrb, FDODeviceExtension->ResetInProgress, FDODeviceExtension->LastTimerActiveSrb);
216 
217  KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
218 
219  // is there an active srb and no global reset is in progress
220  if (FDODeviceExtension->ActiveSrb && /* FDODeviceExtension->ResetInProgress == FALSE && */ FDODeviceExtension->TimerWorkQueueEnabled)
221  {
222  if (FDODeviceExtension->LastTimerActiveSrb != NULL && FDODeviceExtension->LastTimerActiveSrb == FDODeviceExtension->ActiveSrb)
223  {
224  // check if empty
225  DPRINT1("[USBSTOR] ActiveSrb %p hang detected\n", FDODeviceExtension->ActiveSrb);
226  ResetDevice = TRUE;
227  }
228  else
229  {
230  // update pointer
231  FDODeviceExtension->LastTimerActiveSrb = FDODeviceExtension->ActiveSrb;
232  }
233  }
234  else
235  {
236  // reset srb
237  FDODeviceExtension->LastTimerActiveSrb = NULL;
238  }
239 
240  KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock);
241 
242 
243  if (ResetDevice && FDODeviceExtension->TimerWorkQueueEnabled && FDODeviceExtension->SrbErrorHandlingActive == FALSE)
244  {
245  WorkItemData = ExAllocatePoolWithTag(NonPagedPool,
247  USB_STOR_TAG);
248  if (WorkItemData)
249  {
250  // Initialize and queue the work item to handle the error
251  ExInitializeWorkItem(&WorkItemData->WorkQueueItem,
253  WorkItemData);
254 
255  WorkItemData->DeviceObject = FDODeviceExtension->FunctionalDeviceObject;
256 
257  DPRINT1("[USBSTOR] Queing Timer WorkItem\n");
259  }
260  }
261 }
#define IN
Definition: typedefs.h:39
VOID NTAPI USBSTOR_ResetPipeWorkItemRoutine(IN PDEVICE_OBJECT FdoDevice, IN PVOID Ctx)
Definition: error.c:75
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:717
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define UsbBuildGetStatusRequest(urb, op, index, transferBuffer, transferBufferMDL, link)
Definition: usbdlib.h:35
struct _ERRORHANDLER_WORKITEM_DATA * PERRORHANDLER_WORKITEM_DATA
#define TRUE
Definition: types.h:120
DWORD ResetDevice(DWORD private_handle)
PVOID AllocateItem(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes)
Definition: misc.c:30
VOID NTAPI KeAcquireSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:192
LONG NTSTATUS
Definition: precomp.h:26
WORK_QUEUE_ITEM WorkQueueItem
Definition: usbstor.h:168
struct _FDO_DEVICE_EXTENSION * PFDO_DEVICE_EXTENSION
PDEVICE_OBJECT DeviceObject
Definition: usbstor.h:166
IN UCHAR Value
Definition: halp.h:394
NTSTATUS USBSTOR_SendCSWRequest(PFDO_DEVICE_EXTENSION FDODeviceExtension, PIRP Irp)
Definition: scsi.c:242
UCHAR KIRQL
Definition: env_spec_w32.h:591
VOID FreeItem(IN PVOID Item)
Definition: misc.c:43
VOID USBSTOR_QueueNextRequest(IN PDEVICE_OBJECT DeviceObject)
Definition: queue.c:220
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
unsigned int UINT32
NTSTATUS USBSTOR_ResetPipeWithHandle(IN PDEVICE_OBJECT DeviceObject, IN USBD_PIPE_HANDLE PipeHandle)
Definition: error.c:46
NTSTATUS USBSTOR_ResetDevice(IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension)
Definition: misc.c:250
PVOID DeviceExtension
Definition: env_spec_w32.h:418
VOID NTAPI USBSTOR_ResetDeviceWorkItemRoutine(IN PDEVICE_OBJECT FdoDevice, IN PVOID Context)
Definition: error.c:93
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
#define URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
Definition: usb.h:116
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
Definition: usb.h:107
VOID NTAPI KeReleaseSpinLockFromDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:215
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
struct _URB_PIPE_REQUEST UrbPipeRequest
Definition: usb.h:534
unsigned char UCHAR
Definition: xmlstorage.h:181
Status
Definition: gdiplustypes.h:24
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define USB_STOR_TAG
Definition: usbstor.h:10
#define USBSTOR_FDO_FLAGS_DEVICE_RESETTING
Definition: usbstor.h:116
COMMON_DEVICE_EXTENSION Common
Definition: pci.h:81
struct _URB * PURB
VOID NTAPI USBSTOR_TimerRoutine(PDEVICE_OBJECT DeviceObject, PVOID Context)
Definition: error.c:205
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
Definition: usb.h:529
NTSTATUS USBSTOR_GetEndpointStatus(IN PDEVICE_OBJECT DeviceObject, IN UCHAR bEndpointAddress, OUT PUSHORT Value)
Definition: error.c:18
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
static HANDLE PipeHandle
Definition: dhcpcsvc.c:21
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
NTSTATUS USBSTOR_SyncUrbRequest(IN PDEVICE_OBJECT DeviceObject, OUT PURB UrbRequest)
Definition: misc.c:107
#define DPRINT1
Definition: precomp.h:8
VOID NTAPI USBSTOR_QueueResetPipe(IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
Definition: error.c:135
VOID NTAPI USBSTOR_TimerWorkerRoutine(IN PVOID Context)
Definition: error.c:167
#define OUT
Definition: typedefs.h:40
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
VOID NTAPI USBSTOR_QueueResetDevice(IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
Definition: error.c:148
unsigned short * PUSHORT
Definition: retypes.h:2