ReactOS 0.4.16-dev-338-g34e76ad
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
73VOID
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
91VOID
94 IN PDEVICE_OBJECT FdoDevice,
96{
97 PFDO_DEVICE_EXTENSION FDODeviceExtension;
98 UINT32 ix;
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
133VOID
134NTAPI
136 IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
137{
138 DPRINT("USBSTOR_QueueResetPipe\n");
139
140 IoQueueWorkItem(FDODeviceExtension->ResetDeviceWorkItem,
143 FDODeviceExtension);
144}
145
146VOID
147NTAPI
149 IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
150{
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
165VOID
166NTAPI
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
203VOID
204NTAPI
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);
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,
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}
unsigned char BOOLEAN
unsigned int UINT32
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
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:33
struct _FDO_DEVICE_EXTENSION * PFDO_DEVICE_EXTENSION
VOID NTAPI USBSTOR_ResetDeviceWorkItemRoutine(IN PDEVICE_OBJECT FdoDevice, IN PVOID Context)
Definition: error.c:93
VOID NTAPI USBSTOR_QueueResetDevice(IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
Definition: error.c:148
NTSTATUS USBSTOR_ResetPipeWithHandle(IN PDEVICE_OBJECT DeviceObject, IN USBD_PIPE_HANDLE PipeHandle)
Definition: error.c:46
VOID NTAPI USBSTOR_QueueResetPipe(IN PFDO_DEVICE_EXTENSION FDODeviceExtension)
Definition: error.c:135
VOID NTAPI USBSTOR_ResetPipeWorkItemRoutine(IN PDEVICE_OBJECT FdoDevice, IN PVOID Ctx)
Definition: error.c:75
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:83
NTSTATUS USBSTOR_ResetDevice(IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension)
Definition: misc.c:219
VOID USBSTOR_QueueNextRequest(IN PDEVICE_OBJECT DeviceObject)
Definition: queue.c:220
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define NonPagedPool
Definition: env_spec_w32.h:307
Status
Definition: gdiplustypes.h:25
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
PVOID AllocateItem(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes)
Definition: misc.c:29
VOID FreeItem(IN PVOID Item)
Definition: misc.c:37
DWORD ResetDevice(DWORD private_handle)
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
#define DPRINT
Definition: sndvol32.h:73
PVOID DeviceExtension
Definition: env_spec_w32.h:418
PDEVICE_OBJECT DeviceObject
Definition: usbstor.h:167
WORK_QUEUE_ITEM WorkQueueItem
Definition: usbstor.h:169
COMMON_DEVICE_EXTENSION Common
Definition: pci.h:84
Definition: usb.h:529
struct _URB_PIPE_REQUEST UrbPipeRequest
Definition: usb.h:534
#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
NTSTATUS USBSTOR_SendCSWRequest(PFDO_DEVICE_EXTENSION FDODeviceExtension, PIRP Irp)
Definition: scsi.c:242
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 USBSTOR_FDO_FLAGS_DEVICE_RESETTING
Definition: usbstor.h:117
#define USB_STOR_TAG
Definition: usbstor.h:11
struct _ERRORHANDLER_WORKITEM_DATA * PERRORHANDLER_WORKITEM_DATA
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
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
@ CriticalWorkQueue
Definition: extypes.h:189
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
unsigned char UCHAR
Definition: xmlstorage.h:181