ReactOS  0.4.14-dev-599-g2d4d3f5
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 {
81  PFDO_DEVICE_EXTENSION FDODeviceExtension = (PFDO_DEVICE_EXTENSION)FdoDevice->DeviceExtension;
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
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,
138 {
139  DPRINT("USBSTOR_QueueResetPipe\n");
140 
141  IoQueueWorkItem(FDODeviceExtension->ResetDeviceWorkItem,
144  Context);
145 }
146 
147 VOID
148 NTAPI
150  IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
151 {
152  KIRQL OldIrql;
153 
154  DPRINT("USBSTOR_QueueResetDevice\n");
155 
156  KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldIrql);
157  FDODeviceExtension->Flags |= USBSTOR_FDO_FLAGS_DEVICE_RESETTING;
158  KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldIrql);
159 
160  IoQueueWorkItem(FDODeviceExtension->ResetDeviceWorkItem,
163  NULL);
164 }
165 
166 VOID
167 NTAPI
169  IN PVOID Context)
170 {
171  PFDO_DEVICE_EXTENSION FDODeviceExtension;
174 
175  FDODeviceExtension = (PFDO_DEVICE_EXTENSION)WorkItemData->DeviceObject->DeviceExtension;
176  ASSERT(FDODeviceExtension->Common.IsFDO);
177 
178  // first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification
179  Status = USBSTOR_ResetDevice(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension);
180  if (NT_SUCCESS(Status))
181  {
182  // step 2 reset bulk in pipe section 5.3.4
183  Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle);
184  if (NT_SUCCESS(Status))
185  {
186  // finally reset bulk out pipe
187  Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle);
188  }
189  }
190  DPRINT1("Status %x\n", Status);
191 
192  // clear timer srb
193  FDODeviceExtension->LastTimerActiveSrb = NULL;
194 
195  // re-schedule request
196  //USBSTOR_HandleExecuteSCSI(WorkItemData->Context->PDODeviceExtension->Self, WorkItemData->Context->Irp, Context->RetryCount + 1);
197 
198  // do not retry for the same packet again
199  FDODeviceExtension->TimerWorkQueueEnabled = FALSE;
200 
201  ExFreePoolWithTag(WorkItemData, USB_STOR_TAG);
202 }
203 
204 VOID
205 NTAPI
208  PVOID Context)
209 {
210  PFDO_DEVICE_EXTENSION FDODeviceExtension;
212  PERRORHANDLER_WORKITEM_DATA WorkItemData;
213 
214  FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Context;
215  DPRINT1("[USBSTOR] TimerRoutine entered\n");
216  // DPRINT1("[USBSTOR] ActiveSrb %p ResetInProgress %x LastTimerActiveSrb %p\n", FDODeviceExtension->ActiveSrb, FDODeviceExtension->ResetInProgress, FDODeviceExtension->LastTimerActiveSrb);
217 
218  KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
219 
220  // is there an active srb and no global reset is in progress
221  if (FDODeviceExtension->ActiveSrb && /* FDODeviceExtension->ResetInProgress == FALSE && */ FDODeviceExtension->TimerWorkQueueEnabled)
222  {
223  if (FDODeviceExtension->LastTimerActiveSrb != NULL && FDODeviceExtension->LastTimerActiveSrb == FDODeviceExtension->ActiveSrb)
224  {
225  // check if empty
226  DPRINT1("[USBSTOR] ActiveSrb %p hang detected\n", FDODeviceExtension->ActiveSrb);
227  ResetDevice = TRUE;
228  }
229  else
230  {
231  // update pointer
232  FDODeviceExtension->LastTimerActiveSrb = FDODeviceExtension->ActiveSrb;
233  }
234  }
235  else
236  {
237  // reset srb
238  FDODeviceExtension->LastTimerActiveSrb = NULL;
239  }
240 
241  KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock);
242 
243 
244  if (ResetDevice && FDODeviceExtension->TimerWorkQueueEnabled && FDODeviceExtension->SrbErrorHandlingActive == FALSE)
245  {
246  WorkItemData = ExAllocatePoolWithTag(NonPagedPool,
248  USB_STOR_TAG);
249  if (WorkItemData)
250  {
251  // Initialize and queue the work item to handle the error
252  ExInitializeWorkItem(&WorkItemData->WorkQueueItem,
254  WorkItemData);
255 
256  WorkItemData->DeviceObject = FDODeviceExtension->FunctionalDeviceObject;
257 
258  DPRINT1("[USBSTOR] Queing Timer WorkItem\n");
260  }
261  }
262 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
#define IN
Definition: typedefs.h:38
VOID NTAPI USBSTOR_QueueResetPipe(IN PFDO_DEVICE_EXTENSION FDODeviceExtension, IN PIRP_CONTEXT Context)
Definition: error.c:135
VOID NTAPI USBSTOR_ResetPipeWorkItemRoutine(IN PDEVICE_OBJECT FdoDevice, IN PVOID Ctx)
Definition: error.c:75
#define TRUE
Definition: types.h:120
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
IRP_CONTEXT * PIRP_CONTEXT
Definition: cdstruc.h:1217
struct _ERRORHANDLER_WORKITEM_DATA * PERRORHANDLER_WORKITEM_DATA
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:315
struct _FDO_DEVICE_EXTENSION * PFDO_DEVICE_EXTENSION
PDEVICE_OBJECT DeviceObject
Definition: usbstor.h:313
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
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:251
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
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define USB_STOR_TAG
Definition: usbstor.h:10
#define USBSTOR_FDO_FLAGS_DEVICE_RESETTING
Definition: usbstor.h:45
COMMON_DEVICE_EXTENSION Common
Definition: pci.h:80
struct _URB * PURB
VOID NTAPI USBSTOR_TimerRoutine(PDEVICE_OBJECT DeviceObject, PVOID Context)
Definition: error.c:206
Status
Definition: gdiplustypes.h:24
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
Definition: usb.h:529
NTSTATUS USBSTOR_GetEndpointStatus(IN PDEVICE_OBJECT DeviceObject, IN UCHAR bEndpointAddress, OUT PUSHORT Value)
Definition: error.c:18
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_TimerWorkerRoutine(IN PVOID Context)
Definition: error.c:168
#define OUT
Definition: typedefs.h:39
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
VOID NTAPI USBSTOR_QueueResetDevice(IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
Definition: error.c:149
NTSTATUS USBSTOR_SendCSWRequest(PIRP_CONTEXT Context, PIRP Irp)
Definition: scsi.c:258
unsigned short * PUSHORT
Definition: retypes.h:2