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