ReactOS 0.4.16-dev-197-g92996da
queue.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 */
9
10#include "usbstor.h"
11
12#define NDEBUG
13#include <debug.h>
14
15
16VOID
18 PFDO_DEVICE_EXTENSION FDODeviceExtension)
19{
20 ASSERT(FDODeviceExtension->Common.IsFDO);
21 KeInitializeSpinLock(&FDODeviceExtension->IrpListLock);
22 InitializeListHead(&FDODeviceExtension->IrpListHead);
23 KeInitializeEvent(&FDODeviceExtension->NoPendingRequests, NotificationEvent, TRUE);
24}
25
26VOID
30 IN PIRP Irp)
31{
32 PFDO_DEVICE_EXTENSION FDODeviceExtension;
33
34 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
36 ASSERT(FDODeviceExtension->Common.IsFDO);
37
38 // this IRP isn't in our list here
39 // now release the cancel lock
40 IoReleaseCancelSpinLock(Irp->CancelIrql);
41 Irp->IoStatus.Status = STATUS_CANCELLED;
42
45
47}
48
49VOID
53 IN PIRP Irp)
54{
55 PFDO_DEVICE_EXTENSION FDODeviceExtension;
56
57 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
59 ASSERT(FDODeviceExtension->Common.IsFDO);
60
61 KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
62 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
63 KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock);
64
65 IoReleaseCancelSpinLock(Irp->CancelIrql);
66 Irp->IoStatus.Status = STATUS_CANCELLED;
67
70
72}
73
77 IN PIRP Irp)
78{
79 PDRIVER_CANCEL OldDriverCancel;
80 KIRQL OldLevel;
81 PFDO_DEVICE_EXTENSION FDODeviceExtension;
82 BOOLEAN IrpListFreeze;
83 BOOLEAN SrbProcessing;
86
87 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
88 ASSERT(FDODeviceExtension->Common.IsFDO);
89
91
92 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
93
94 SrbProcessing = FDODeviceExtension->IrpPendingCount != 0;
95
96 if (SrbProcessing)
97 {
98 // add irp to queue
99 InsertTailList(&FDODeviceExtension->IrpListHead, &Irp->Tail.Overlay.ListEntry);
100 }
101
102 FDODeviceExtension->IrpPendingCount++;
103 KeClearEvent(&FDODeviceExtension->NoPendingRequests);
104
105 // check if queue is freezed
106 IrpListFreeze = BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE);
107
108 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
109
110 // synchronize with cancellations by holding the cancel lock
111 IoAcquireCancelSpinLock(&Irp->CancelIrql);
112
113 if (SrbProcessing)
114 {
115 ASSERT(FDODeviceExtension->ActiveSrb != NULL);
116
117 OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_Cancel);
118 }
119 else
120 {
121 ASSERT(FDODeviceExtension->ActiveSrb == NULL);
122
123 FDODeviceExtension->ActiveSrb = Request;
124 OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_CancelIo);
125 }
126
127 // check if the irp has already been cancelled
128 if (Irp->Cancel && OldDriverCancel == NULL)
129 {
130 // cancel irp
131 Irp->CancelRoutine(DeviceObject, Irp);
132 return FALSE;
133 }
134
135 IoReleaseCancelSpinLock(Irp->CancelIrql);
136
137 // if list is freezed, dont start this packet
138 DPRINT("IrpListFreeze: %lu IrpPendingCount %lu\n", IrpListFreeze, FDODeviceExtension->IrpPendingCount);
139
140 return (IrpListFreeze || SrbProcessing);
141}
142
143PIRP
146{
147 KIRQL OldLevel;
148 PFDO_DEVICE_EXTENSION FDODeviceExtension;
150 PIRP Irp = NULL;
151
152 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
153 ASSERT(FDODeviceExtension->Common.IsFDO);
154
155 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
156
157 if (!IsListEmpty(&FDODeviceExtension->IrpListHead))
158 {
159 Entry = RemoveHeadList(&FDODeviceExtension->IrpListHead);
160
161 // get offset to start of irp
162 Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
163 }
164
165 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
166
167 return Irp;
168}
169
170VOID
173{
174 PFDO_DEVICE_EXTENSION FDODeviceExtension;
175
176 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
177
178 KeWaitForSingleObject(&FDODeviceExtension->NoPendingRequests,
179 Executive,
181 FALSE,
182 NULL);
183}
184
185VOID
187 IN PDEVICE_OBJECT FDODeviceObject,
188 IN PIRP Irp)
189{
190 KIRQL OldLevel;
191 PFDO_DEVICE_EXTENSION FDODeviceExtension;
194
195 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)FDODeviceObject->DeviceExtension;
196 ASSERT(FDODeviceExtension->Common.IsFDO);
197
198 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
199
200 FDODeviceExtension->IrpPendingCount--;
201
202 // check if this was our current active SRB
203 if (FDODeviceExtension->ActiveSrb == Request)
204 {
205 // indicate processing is completed
206 FDODeviceExtension->ActiveSrb = NULL;
207 }
208
209 // Set the event if nothing else is pending
210 if (FDODeviceExtension->IrpPendingCount == 0 &&
211 FDODeviceExtension->ActiveSrb == NULL)
212 {
213 KeSetEvent(&FDODeviceExtension->NoPendingRequests, IO_NO_INCREMENT, FALSE);
214 }
215
216 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
217}
218
219VOID
222{
223 PFDO_DEVICE_EXTENSION FDODeviceExtension;
224 PIRP Irp;
225 PIO_STACK_LOCATION IoStack;
227
228 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
229 ASSERT(FDODeviceExtension->Common.IsFDO);
230
231 // check first if there's already a request pending or the queue is frozen
232 if (FDODeviceExtension->ActiveSrb != NULL ||
234 {
235 // no work to do yet
236 return;
237 }
238
239 // remove first irp from list
241
242 // is there an irp pending
243 if (!Irp)
244 {
245 // no work to do
247 return;
248 }
249
251 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
253
254 FDODeviceExtension->ActiveSrb = Request;
255
256 // start next packet
259}
260
261VOID
264{
265 PFDO_DEVICE_EXTENSION FDODeviceExtension;
266 PIRP Irp;
267 KIRQL OldLevel;
268 PIO_STACK_LOCATION IoStack;
270
271 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
272 ASSERT(FDODeviceExtension->Common.IsFDO);
273
274 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
275
276 // clear freezed status
277 FDODeviceExtension->Flags &= ~USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE;
278
279 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
280
281 // grab newest irp
283
284 if (!Irp)
285 {
286 return;
287 }
288
290 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
291
293 Irp,
294 &Request->QueueSortKey,
296}
297
298VOID
299NTAPI
302 PIRP Irp)
303{
304 PIO_STACK_LOCATION IoStack;
306 PFDO_DEVICE_EXTENSION FDODeviceExtension;
307 PPDO_DEVICE_EXTENSION PDODeviceExtension;
308 KIRQL OldLevel;
309 BOOLEAN ResetInProgress;
310
311 DPRINT("USBSTOR_StartIo\n");
312
313 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
314 ASSERT(FDODeviceExtension->Common.IsFDO);
315
316 IoAcquireCancelSpinLock(&OldLevel);
317
319
320 // check if the irp has been cancelled
321 if (Irp->Cancel)
322 {
323 IoReleaseCancelSpinLock(OldLevel);
324
325 Irp->IoStatus.Status = STATUS_CANCELLED;
326 Irp->IoStatus.Information = 0;
327
331 return;
332 }
333
334 IoReleaseCancelSpinLock(OldLevel);
335
336 KeAcquireSpinLock(&FDODeviceExtension->CommonLock, &OldLevel);
337 ResetInProgress = BooleanFlagOn(FDODeviceExtension->Flags, USBSTOR_FDO_FLAGS_DEVICE_RESETTING);
338 KeReleaseSpinLock(&FDODeviceExtension->CommonLock, OldLevel);
339
341
342 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
343 Request = IoStack->Parameters.Scsi.Srb;
344 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
345
346 if (ResetInProgress)
347 {
348 // hard reset is in progress
349 Request->SrbStatus = SRB_STATUS_NO_DEVICE;
350 Request->DataTransferLength = 0;
351 Irp->IoStatus.Information = 0;
352 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
356 return;
357 }
358
360
361 // FIXME: handle error
362}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
struct _IRP * PIRP
unsigned char BOOLEAN
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
struct _FDO_DEVICE_EXTENSION * PFDO_DEVICE_EXTENSION
struct _PDO_DEVICE_EXTENSION * PPDO_DEVICE_EXTENSION
#define ASSERT_IRQL_EQUAL(x)
Definition: debug.h:43
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define SRB_STATUS_NO_DEVICE
Definition: srb.h:348
VOID NTAPI USBSTOR_Cancel(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: queue.c:51
BOOLEAN USBSTOR_QueueAddIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: queue.c:75
VOID USBSTOR_QueueRelease(IN PDEVICE_OBJECT DeviceObject)
Definition: queue.c:262
PIRP USBSTOR_RemoveIrp(IN PDEVICE_OBJECT DeviceObject)
Definition: queue.c:144
VOID USBSTOR_QueueInitialize(PFDO_DEVICE_EXTENSION FDODeviceExtension)
Definition: queue.c:17
VOID USBSTOR_QueueTerminateRequest(IN PDEVICE_OBJECT FDODeviceObject, IN PIRP Irp)
Definition: queue.c:186
VOID USBSTOR_QueueWaitForPendingRequests(IN PDEVICE_OBJECT DeviceObject)
Definition: queue.c:171
VOID USBSTOR_QueueNextRequest(IN PDEVICE_OBJECT DeviceObject)
Definition: queue.c:220
VOID NTAPI USBSTOR_CancelIo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: queue.c:28
VOID NTAPI USBSTOR_StartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: queue.c:300
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IoMarkIrpPending(Irp)
IoSetCancelRoutine(Irp, CancelRoutine)
#define ASSERT(a)
Definition: mode.c:44
#define KernelMode
Definition: asm.h:34
@ NotificationEvent
VOID NTAPI IoStartPacket(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PULONG Key, IN PDRIVER_CANCEL CancelFunction)
Definition: device.c:1876
VOID NTAPI IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Cancelable)
Definition: device.c:1847
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:428
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
#define DPRINT
Definition: sndvol32.h:73
base of all file and directory entries
Definition: entries.h:83
PVOID DeviceExtension
Definition: env_spec_w32.h:418
LIST_ENTRY ListEntry
Definition: pci.h:86
COMMON_DEVICE_EXTENSION Common
Definition: pci.h:84
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
struct _IO_STACK_LOCATION::@3974::@3996 Scsi
union _IO_STACK_LOCATION::@1575 Parameters
struct _IO_STACK_LOCATION::@3974::@4013 Others
Definition: typedefs.h:120
COMMON_DEVICE_EXTENSION Common
Definition: pci.h:59
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
NTSTATUS USBSTOR_HandleExecuteSCSI(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: scsi.c:540
#define USBSTOR_FDO_FLAGS_DEVICE_RESETTING
Definition: usbstor.h:117
#define USBSTOR_FDO_FLAGS_IRP_LIST_FREEZE
Definition: usbstor.h:118
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
#define IO_NO_INCREMENT
Definition: iotypes.h:598
DRIVER_CANCEL * PDRIVER_CANCEL
Definition: iotypes.h:2759
@ Executive
Definition: ketypes.h:415