xref: /reactos/drivers/usb/usbstor_new/error.c (revision 94e09426)
1*94e09426SAmine Khaldi /*
2*94e09426SAmine Khaldi  * PROJECT:     ReactOS Universal Serial Bus Bulk Storage Driver
3*94e09426SAmine Khaldi  * LICENSE:     GPL - See COPYING in the top level directory
4*94e09426SAmine Khaldi  * FILE:        drivers/usb/usbstor/error.c
5*94e09426SAmine Khaldi  * PURPOSE:     USB block storage device driver.
6*94e09426SAmine Khaldi  * PROGRAMMERS:
7*94e09426SAmine Khaldi  *              James Tabor
8*94e09426SAmine Khaldi  *              Michael Martin (michael.martin@reactos.org)
9*94e09426SAmine Khaldi  *              Johannes Anderwald (johannes.anderwald@reactos.org)
10*94e09426SAmine Khaldi  */
11*94e09426SAmine Khaldi 
12*94e09426SAmine Khaldi #include "usbstor.h"
13*94e09426SAmine Khaldi 
14*94e09426SAmine Khaldi #define NDEBUG
15*94e09426SAmine Khaldi #include <debug.h>
16*94e09426SAmine Khaldi 
17*94e09426SAmine Khaldi NTSTATUS
USBSTOR_GetEndpointStatus(IN PDEVICE_OBJECT DeviceObject,IN UCHAR bEndpointAddress,OUT PUSHORT Value)18*94e09426SAmine Khaldi USBSTOR_GetEndpointStatus(
19*94e09426SAmine Khaldi     IN PDEVICE_OBJECT DeviceObject,
20*94e09426SAmine Khaldi     IN UCHAR bEndpointAddress,
21*94e09426SAmine Khaldi     OUT PUSHORT Value)
22*94e09426SAmine Khaldi {
23*94e09426SAmine Khaldi     PURB Urb;
24*94e09426SAmine Khaldi     NTSTATUS Status;
25*94e09426SAmine Khaldi 
26*94e09426SAmine Khaldi     //
27*94e09426SAmine Khaldi     // allocate urb
28*94e09426SAmine Khaldi     //
29*94e09426SAmine Khaldi     DPRINT("Allocating URB\n");
30*94e09426SAmine Khaldi     Urb = (PURB)AllocateItem(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
31*94e09426SAmine Khaldi     if (!Urb)
32*94e09426SAmine Khaldi     {
33*94e09426SAmine Khaldi         //
34*94e09426SAmine Khaldi         // out of memory
35*94e09426SAmine Khaldi         //
36*94e09426SAmine Khaldi         DPRINT1("OutofMemory!\n");
37*94e09426SAmine Khaldi         return STATUS_INSUFFICIENT_RESOURCES;
38*94e09426SAmine Khaldi     }
39*94e09426SAmine Khaldi 
40*94e09426SAmine Khaldi     //
41*94e09426SAmine Khaldi     // build status
42*94e09426SAmine Khaldi     //
43*94e09426SAmine Khaldi    UsbBuildGetStatusRequest(Urb, URB_FUNCTION_GET_STATUS_FROM_ENDPOINT, bEndpointAddress & 0x0F, Value, NULL, NULL);
44*94e09426SAmine Khaldi 
45*94e09426SAmine Khaldi     //
46*94e09426SAmine Khaldi     // send the request
47*94e09426SAmine Khaldi     //
48*94e09426SAmine Khaldi     DPRINT1("Sending Request DeviceObject %p, Urb %p\n", DeviceObject, Urb);
49*94e09426SAmine Khaldi     Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
50*94e09426SAmine Khaldi 
51*94e09426SAmine Khaldi     //
52*94e09426SAmine Khaldi     // free urb
53*94e09426SAmine Khaldi     //
54*94e09426SAmine Khaldi     FreeItem(Urb);
55*94e09426SAmine Khaldi 
56*94e09426SAmine Khaldi     //
57*94e09426SAmine Khaldi     // done
58*94e09426SAmine Khaldi     //
59*94e09426SAmine Khaldi     return Status;
60*94e09426SAmine Khaldi }
61*94e09426SAmine Khaldi 
62*94e09426SAmine Khaldi 
63*94e09426SAmine Khaldi 
64*94e09426SAmine Khaldi NTSTATUS
USBSTOR_ResetPipeWithHandle(IN PDEVICE_OBJECT DeviceObject,IN USBD_PIPE_HANDLE PipeHandle)65*94e09426SAmine Khaldi USBSTOR_ResetPipeWithHandle(
66*94e09426SAmine Khaldi     IN PDEVICE_OBJECT DeviceObject,
67*94e09426SAmine Khaldi     IN USBD_PIPE_HANDLE PipeHandle)
68*94e09426SAmine Khaldi {
69*94e09426SAmine Khaldi     PURB Urb;
70*94e09426SAmine Khaldi     NTSTATUS Status;
71*94e09426SAmine Khaldi 
72*94e09426SAmine Khaldi     //
73*94e09426SAmine Khaldi     // allocate urb
74*94e09426SAmine Khaldi     //
75*94e09426SAmine Khaldi     DPRINT("Allocating URB\n");
76*94e09426SAmine Khaldi     Urb = (PURB)AllocateItem(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
77*94e09426SAmine Khaldi     if (!Urb)
78*94e09426SAmine Khaldi     {
79*94e09426SAmine Khaldi         //
80*94e09426SAmine Khaldi         // out of memory
81*94e09426SAmine Khaldi         //
82*94e09426SAmine Khaldi         DPRINT1("OutofMemory!\n");
83*94e09426SAmine Khaldi         return STATUS_INSUFFICIENT_RESOURCES;
84*94e09426SAmine Khaldi     }
85*94e09426SAmine Khaldi 
86*94e09426SAmine Khaldi     //
87*94e09426SAmine Khaldi     // initialize the urb
88*94e09426SAmine Khaldi     //
89*94e09426SAmine Khaldi     Urb->UrbPipeRequest.Hdr.Length = sizeof(struct _URB_PIPE_REQUEST);
90*94e09426SAmine Khaldi     Urb->UrbPipeRequest.Hdr.Function = URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL;
91*94e09426SAmine Khaldi     Urb->UrbPipeRequest.PipeHandle = PipeHandle;
92*94e09426SAmine Khaldi 
93*94e09426SAmine Khaldi     //
94*94e09426SAmine Khaldi     // send the request
95*94e09426SAmine Khaldi     //
96*94e09426SAmine Khaldi     DPRINT1("Sending Request DeviceObject %p, Urb %p\n", DeviceObject, Urb);
97*94e09426SAmine Khaldi     Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
98*94e09426SAmine Khaldi 
99*94e09426SAmine Khaldi     //
100*94e09426SAmine Khaldi     // free urb
101*94e09426SAmine Khaldi     //
102*94e09426SAmine Khaldi     FreeItem(Urb);
103*94e09426SAmine Khaldi 
104*94e09426SAmine Khaldi     //
105*94e09426SAmine Khaldi     // done
106*94e09426SAmine Khaldi     //
107*94e09426SAmine Khaldi     return Status;
108*94e09426SAmine Khaldi }
109*94e09426SAmine Khaldi 
110*94e09426SAmine Khaldi 
111*94e09426SAmine Khaldi NTSTATUS
USBSTOR_HandleTransferError(PDEVICE_OBJECT DeviceObject,PIRP_CONTEXT Context)112*94e09426SAmine Khaldi USBSTOR_HandleTransferError(
113*94e09426SAmine Khaldi     PDEVICE_OBJECT DeviceObject,
114*94e09426SAmine Khaldi     PIRP_CONTEXT Context)
115*94e09426SAmine Khaldi {
116*94e09426SAmine Khaldi     NTSTATUS Status = STATUS_SUCCESS;
117*94e09426SAmine Khaldi     PIO_STACK_LOCATION Stack;
118*94e09426SAmine Khaldi     PSCSI_REQUEST_BLOCK Request;
119*94e09426SAmine Khaldi     PCDB pCDB;
120*94e09426SAmine Khaldi 
121*94e09426SAmine Khaldi     //
122*94e09426SAmine Khaldi     // sanity checks
123*94e09426SAmine Khaldi     //
124*94e09426SAmine Khaldi     ASSERT(Context);
125*94e09426SAmine Khaldi     ASSERT(Context->PDODeviceExtension);
126*94e09426SAmine Khaldi     ASSERT(Context->PDODeviceExtension->Self);
127*94e09426SAmine Khaldi     ASSERT(Context->Irp);
128*94e09426SAmine Khaldi 
129*94e09426SAmine Khaldi     //
130*94e09426SAmine Khaldi     // first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification
131*94e09426SAmine Khaldi     //
132*94e09426SAmine Khaldi     Status = USBSTOR_ResetDevice(Context->FDODeviceExtension->LowerDeviceObject, Context->FDODeviceExtension);
133*94e09426SAmine Khaldi     if (NT_SUCCESS(Status))
134*94e09426SAmine Khaldi     {
135*94e09426SAmine Khaldi         //
136*94e09426SAmine Khaldi         // step 2 reset bulk in pipe section 5.3.4
137*94e09426SAmine Khaldi         //
138*94e09426SAmine Khaldi         Status = USBSTOR_ResetPipeWithHandle(Context->FDODeviceExtension->LowerDeviceObject, Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle);
139*94e09426SAmine Khaldi         if (NT_SUCCESS(Status))
140*94e09426SAmine Khaldi         {
141*94e09426SAmine Khaldi             //
142*94e09426SAmine Khaldi             // finally reset bulk out pipe
143*94e09426SAmine Khaldi             //
144*94e09426SAmine Khaldi             Status = USBSTOR_ResetPipeWithHandle(Context->FDODeviceExtension->LowerDeviceObject, Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkOutPipeIndex].PipeHandle);
145*94e09426SAmine Khaldi         }
146*94e09426SAmine Khaldi     }
147*94e09426SAmine Khaldi 
148*94e09426SAmine Khaldi     //
149*94e09426SAmine Khaldi     // get next stack location
150*94e09426SAmine Khaldi     //
151*94e09426SAmine Khaldi     Stack = IoGetCurrentIrpStackLocation(Context->Irp);
152*94e09426SAmine Khaldi 
153*94e09426SAmine Khaldi     //
154*94e09426SAmine Khaldi     // get request block
155*94e09426SAmine Khaldi     //
156*94e09426SAmine Khaldi     Request = (PSCSI_REQUEST_BLOCK)Stack->Parameters.Others.Argument1;
157*94e09426SAmine Khaldi     ASSERT(Request);
158*94e09426SAmine Khaldi 
159*94e09426SAmine Khaldi     //
160*94e09426SAmine Khaldi     // obtain request type
161*94e09426SAmine Khaldi     //
162*94e09426SAmine Khaldi     pCDB = (PCDB)Request->Cdb;
163*94e09426SAmine Khaldi     ASSERT(pCDB);
164*94e09426SAmine Khaldi 
165*94e09426SAmine Khaldi     if (Status != STATUS_SUCCESS || Context->RetryCount >= 1)
166*94e09426SAmine Khaldi     {
167*94e09426SAmine Khaldi         //
168*94e09426SAmine Khaldi         // Complete the master IRP
169*94e09426SAmine Khaldi         //
170*94e09426SAmine Khaldi         Context->Irp->IoStatus.Status = Status;
171*94e09426SAmine Khaldi         Context->Irp->IoStatus.Information = 0;
172*94e09426SAmine Khaldi         USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject, Context->Irp);
173*94e09426SAmine Khaldi         IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
174*94e09426SAmine Khaldi 
175*94e09426SAmine Khaldi         //
176*94e09426SAmine Khaldi         // Start the next request
177*94e09426SAmine Khaldi         //
178*94e09426SAmine Khaldi         USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject);
179*94e09426SAmine Khaldi 
180*94e09426SAmine Khaldi         //
181*94e09426SAmine Khaldi         // srb handling finished
182*94e09426SAmine Khaldi         //
183*94e09426SAmine Khaldi         Context->FDODeviceExtension->SrbErrorHandlingActive = FALSE;
184*94e09426SAmine Khaldi 
185*94e09426SAmine Khaldi         //
186*94e09426SAmine Khaldi         // clear timer srb
187*94e09426SAmine Khaldi         //
188*94e09426SAmine Khaldi         Context->FDODeviceExtension->LastTimerActiveSrb = NULL;
189*94e09426SAmine Khaldi     }
190*94e09426SAmine Khaldi     else
191*94e09426SAmine Khaldi     {
192*94e09426SAmine Khaldi         DPRINT1("Retrying Count %lu %p\n", Context->RetryCount, Context->PDODeviceExtension->Self);
193*94e09426SAmine Khaldi 
194*94e09426SAmine Khaldi         //
195*94e09426SAmine Khaldi         // re-schedule request
196*94e09426SAmine Khaldi         //
197*94e09426SAmine Khaldi         USBSTOR_HandleExecuteSCSI(Context->PDODeviceExtension->Self, Context->Irp, Context->RetryCount + 1);
198*94e09426SAmine Khaldi 
199*94e09426SAmine Khaldi         //
200*94e09426SAmine Khaldi         // srb error handling finished
201*94e09426SAmine Khaldi         //
202*94e09426SAmine Khaldi         Context->FDODeviceExtension->SrbErrorHandlingActive = FALSE;
203*94e09426SAmine Khaldi 
204*94e09426SAmine Khaldi         //
205*94e09426SAmine Khaldi         // srb error handling finished
206*94e09426SAmine Khaldi         //
207*94e09426SAmine Khaldi         Context->FDODeviceExtension->TimerWorkQueueEnabled = TRUE;
208*94e09426SAmine Khaldi 
209*94e09426SAmine Khaldi         //
210*94e09426SAmine Khaldi         // clear timer srb
211*94e09426SAmine Khaldi         //
212*94e09426SAmine Khaldi         Context->FDODeviceExtension->LastTimerActiveSrb = NULL;
213*94e09426SAmine Khaldi     }
214*94e09426SAmine Khaldi 
215*94e09426SAmine Khaldi     //
216*94e09426SAmine Khaldi     // cleanup irp context
217*94e09426SAmine Khaldi     //
218*94e09426SAmine Khaldi     FreeItem(Context->cbw);
219*94e09426SAmine Khaldi     FreeItem(Context);
220*94e09426SAmine Khaldi 
221*94e09426SAmine Khaldi 
222*94e09426SAmine Khaldi     DPRINT1("USBSTOR_HandleTransferError returning with Status %x\n", Status);
223*94e09426SAmine Khaldi     return Status;
224*94e09426SAmine Khaldi }
225*94e09426SAmine Khaldi 
226*94e09426SAmine Khaldi VOID
227*94e09426SAmine Khaldi NTAPI
USBSTOR_ResetHandlerWorkItemRoutine(PVOID Context)228*94e09426SAmine Khaldi USBSTOR_ResetHandlerWorkItemRoutine(
229*94e09426SAmine Khaldi     PVOID Context)
230*94e09426SAmine Khaldi {
231*94e09426SAmine Khaldi     NTSTATUS Status;
232*94e09426SAmine Khaldi     PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
233*94e09426SAmine Khaldi 
234*94e09426SAmine Khaldi     //
235*94e09426SAmine Khaldi     // clear stall on BulkIn pipe
236*94e09426SAmine Khaldi     //
237*94e09426SAmine Khaldi     Status = USBSTOR_ResetPipeWithHandle(WorkItemData->Context->FDODeviceExtension->LowerDeviceObject, WorkItemData->Context->FDODeviceExtension->InterfaceInformation->Pipes[WorkItemData->Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle);
238*94e09426SAmine Khaldi     DPRINT1("USBSTOR_ResetPipeWithHandle Status %x\n", Status);
239*94e09426SAmine Khaldi 
240*94e09426SAmine Khaldi     //
241*94e09426SAmine Khaldi     // now resend the csw as the stall got cleared
242*94e09426SAmine Khaldi     //
243*94e09426SAmine Khaldi     USBSTOR_SendCSW(WorkItemData->Context, WorkItemData->Irp);
244*94e09426SAmine Khaldi }
245*94e09426SAmine Khaldi 
246*94e09426SAmine Khaldi VOID
247*94e09426SAmine Khaldi NTAPI
ErrorHandlerWorkItemRoutine(PVOID Context)248*94e09426SAmine Khaldi ErrorHandlerWorkItemRoutine(
249*94e09426SAmine Khaldi     PVOID Context)
250*94e09426SAmine Khaldi {
251*94e09426SAmine Khaldi     PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
252*94e09426SAmine Khaldi 
253*94e09426SAmine Khaldi     if (WorkItemData->Context->ErrorIndex == 2)
254*94e09426SAmine Khaldi     {
255*94e09426SAmine Khaldi         //
256*94e09426SAmine Khaldi         // reset device
257*94e09426SAmine Khaldi         //
258*94e09426SAmine Khaldi         USBSTOR_HandleTransferError(WorkItemData->DeviceObject, WorkItemData->Context);
259*94e09426SAmine Khaldi     }
260*94e09426SAmine Khaldi     else
261*94e09426SAmine Khaldi     {
262*94e09426SAmine Khaldi         //
263*94e09426SAmine Khaldi         // clear stall
264*94e09426SAmine Khaldi         //
265*94e09426SAmine Khaldi         USBSTOR_ResetHandlerWorkItemRoutine(WorkItemData);
266*94e09426SAmine Khaldi     }
267*94e09426SAmine Khaldi 
268*94e09426SAmine Khaldi     //
269*94e09426SAmine Khaldi     // Free Work Item Data
270*94e09426SAmine Khaldi     //
271*94e09426SAmine Khaldi     ExFreePoolWithTag(WorkItemData, USB_STOR_TAG);
272*94e09426SAmine Khaldi }
273*94e09426SAmine Khaldi 
274*94e09426SAmine Khaldi VOID
275*94e09426SAmine Khaldi NTAPI
USBSTOR_TimerWorkerRoutine(IN PVOID Context)276*94e09426SAmine Khaldi USBSTOR_TimerWorkerRoutine(
277*94e09426SAmine Khaldi     IN PVOID Context)
278*94e09426SAmine Khaldi {
279*94e09426SAmine Khaldi     PFDO_DEVICE_EXTENSION FDODeviceExtension;
280*94e09426SAmine Khaldi     NTSTATUS Status;
281*94e09426SAmine Khaldi     PERRORHANDLER_WORKITEM_DATA WorkItemData = (PERRORHANDLER_WORKITEM_DATA)Context;
282*94e09426SAmine Khaldi 
283*94e09426SAmine Khaldi     //
284*94e09426SAmine Khaldi     // get device extension
285*94e09426SAmine Khaldi     //
286*94e09426SAmine Khaldi     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)WorkItemData->DeviceObject->DeviceExtension;
287*94e09426SAmine Khaldi     ASSERT(FDODeviceExtension->Common.IsFDO);
288*94e09426SAmine Khaldi 
289*94e09426SAmine Khaldi     //
290*94e09426SAmine Khaldi     // first perform a mass storage reset step 1 in 5.3.4 USB Mass Storage Bulk Only Specification
291*94e09426SAmine Khaldi     //
292*94e09426SAmine Khaldi     Status = USBSTOR_ResetDevice(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension);
293*94e09426SAmine Khaldi     if (NT_SUCCESS(Status))
294*94e09426SAmine Khaldi     {
295*94e09426SAmine Khaldi         //
296*94e09426SAmine Khaldi         // step 2 reset bulk in pipe section 5.3.4
297*94e09426SAmine Khaldi         //
298*94e09426SAmine Khaldi         Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle);
299*94e09426SAmine Khaldi         if (NT_SUCCESS(Status))
300*94e09426SAmine Khaldi         {
301*94e09426SAmine Khaldi             //
302*94e09426SAmine Khaldi             // finally reset bulk out pipe
303*94e09426SAmine Khaldi             //
304*94e09426SAmine Khaldi             Status = USBSTOR_ResetPipeWithHandle(FDODeviceExtension->LowerDeviceObject, FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle);
305*94e09426SAmine Khaldi         }
306*94e09426SAmine Khaldi     }
307*94e09426SAmine Khaldi     DPRINT1("Status %x\n", Status);
308*94e09426SAmine Khaldi 
309*94e09426SAmine Khaldi     //
310*94e09426SAmine Khaldi     // clear timer srb
311*94e09426SAmine Khaldi     //
312*94e09426SAmine Khaldi     FDODeviceExtension->LastTimerActiveSrb = NULL;
313*94e09426SAmine Khaldi 
314*94e09426SAmine Khaldi     //
315*94e09426SAmine Khaldi     // re-schedule request
316*94e09426SAmine Khaldi     //
317*94e09426SAmine Khaldi     //USBSTOR_HandleExecuteSCSI(WorkItemData->Context->PDODeviceExtension->Self, WorkItemData->Context->Irp, Context->RetryCount + 1);
318*94e09426SAmine Khaldi 
319*94e09426SAmine Khaldi 
320*94e09426SAmine Khaldi 
321*94e09426SAmine Khaldi     //
322*94e09426SAmine Khaldi     // do not retry for the same packet again
323*94e09426SAmine Khaldi     //
324*94e09426SAmine Khaldi     FDODeviceExtension->TimerWorkQueueEnabled = FALSE;
325*94e09426SAmine Khaldi 
326*94e09426SAmine Khaldi     //
327*94e09426SAmine Khaldi     // Free Work Item Data
328*94e09426SAmine Khaldi     //
329*94e09426SAmine Khaldi     ExFreePoolWithTag(WorkItemData, USB_STOR_TAG);
330*94e09426SAmine Khaldi }
331*94e09426SAmine Khaldi 
332*94e09426SAmine Khaldi 
333*94e09426SAmine Khaldi VOID
334*94e09426SAmine Khaldi NTAPI
USBSTOR_TimerRoutine(PDEVICE_OBJECT DeviceObject,PVOID Context)335*94e09426SAmine Khaldi USBSTOR_TimerRoutine(
336*94e09426SAmine Khaldi     PDEVICE_OBJECT DeviceObject,
337*94e09426SAmine Khaldi      PVOID Context)
338*94e09426SAmine Khaldi {
339*94e09426SAmine Khaldi     PFDO_DEVICE_EXTENSION FDODeviceExtension;
340*94e09426SAmine Khaldi     BOOLEAN ResetDevice = FALSE;
341*94e09426SAmine Khaldi     PERRORHANDLER_WORKITEM_DATA WorkItemData;
342*94e09426SAmine Khaldi 
343*94e09426SAmine Khaldi     //
344*94e09426SAmine Khaldi     // get device extension
345*94e09426SAmine Khaldi     //
346*94e09426SAmine Khaldi     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Context;
347*94e09426SAmine Khaldi     DPRINT1("[USBSTOR] TimerRoutine entered\n");
348*94e09426SAmine Khaldi     DPRINT1("[USBSTOR] ActiveSrb %p ResetInProgress %x LastTimerActiveSrb %p\n", FDODeviceExtension->ActiveSrb, FDODeviceExtension->ResetInProgress, FDODeviceExtension->LastTimerActiveSrb);
349*94e09426SAmine Khaldi 
350*94e09426SAmine Khaldi     //
351*94e09426SAmine Khaldi     // acquire spinlock
352*94e09426SAmine Khaldi     //
353*94e09426SAmine Khaldi     KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
354*94e09426SAmine Khaldi 
355*94e09426SAmine Khaldi     //
356*94e09426SAmine Khaldi     // is there an active srb and no global reset is in progress
357*94e09426SAmine Khaldi     //
358*94e09426SAmine Khaldi     if (FDODeviceExtension->ActiveSrb && FDODeviceExtension->ResetInProgress == FALSE && FDODeviceExtension->TimerWorkQueueEnabled)
359*94e09426SAmine Khaldi     {
360*94e09426SAmine Khaldi         if (FDODeviceExtension->LastTimerActiveSrb != NULL && FDODeviceExtension->LastTimerActiveSrb == FDODeviceExtension->ActiveSrb)
361*94e09426SAmine Khaldi         {
362*94e09426SAmine Khaldi             //
363*94e09426SAmine Khaldi             // check if empty
364*94e09426SAmine Khaldi             //
365*94e09426SAmine Khaldi             DPRINT1("[USBSTOR] ActiveSrb %p hang detected\n", FDODeviceExtension->ActiveSrb);
366*94e09426SAmine Khaldi             ResetDevice = TRUE;
367*94e09426SAmine Khaldi         }
368*94e09426SAmine Khaldi         else
369*94e09426SAmine Khaldi         {
370*94e09426SAmine Khaldi             //
371*94e09426SAmine Khaldi             // update pointer
372*94e09426SAmine Khaldi             //
373*94e09426SAmine Khaldi             FDODeviceExtension->LastTimerActiveSrb = FDODeviceExtension->ActiveSrb;
374*94e09426SAmine Khaldi         }
375*94e09426SAmine Khaldi     }
376*94e09426SAmine Khaldi     else
377*94e09426SAmine Khaldi     {
378*94e09426SAmine Khaldi         //
379*94e09426SAmine Khaldi         // reset srb
380*94e09426SAmine Khaldi         //
381*94e09426SAmine Khaldi         FDODeviceExtension->LastTimerActiveSrb = NULL;
382*94e09426SAmine Khaldi     }
383*94e09426SAmine Khaldi 
384*94e09426SAmine Khaldi     //
385*94e09426SAmine Khaldi     // release lock
386*94e09426SAmine Khaldi     //
387*94e09426SAmine Khaldi     KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock);
388*94e09426SAmine Khaldi 
389*94e09426SAmine Khaldi 
390*94e09426SAmine Khaldi     if (ResetDevice && FDODeviceExtension->TimerWorkQueueEnabled && FDODeviceExtension->SrbErrorHandlingActive == FALSE)
391*94e09426SAmine Khaldi     {
392*94e09426SAmine Khaldi         WorkItemData = ExAllocatePoolWithTag(NonPagedPool,
393*94e09426SAmine Khaldi                                              sizeof(ERRORHANDLER_WORKITEM_DATA),
394*94e09426SAmine Khaldi                                              USB_STOR_TAG);
395*94e09426SAmine Khaldi         if (WorkItemData)
396*94e09426SAmine Khaldi         {
397*94e09426SAmine Khaldi            //
398*94e09426SAmine Khaldi            // Initialize and queue the work item to handle the error
399*94e09426SAmine Khaldi            //
400*94e09426SAmine Khaldi            ExInitializeWorkItem(&WorkItemData->WorkQueueItem,
401*94e09426SAmine Khaldi                                  USBSTOR_TimerWorkerRoutine,
402*94e09426SAmine Khaldi                                  WorkItemData);
403*94e09426SAmine Khaldi 
404*94e09426SAmine Khaldi            WorkItemData->DeviceObject = FDODeviceExtension->FunctionalDeviceObject;
405*94e09426SAmine Khaldi 
406*94e09426SAmine Khaldi            DPRINT1("[USBSTOR] Queing Timer WorkItem\n");
407*94e09426SAmine Khaldi            ExQueueWorkItem(&WorkItemData->WorkQueueItem, DelayedWorkQueue);
408*94e09426SAmine Khaldi         }
409*94e09426SAmine Khaldi      }
410*94e09426SAmine Khaldi }
411