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