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)
17 USBSTOR_QueueInitialize(
18 PFDO_DEVICE_EXTENSION FDODeviceExtension
)
20 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
21 KeInitializeSpinLock(&FDODeviceExtension
->IrpListLock
);
22 InitializeListHead(&FDODeviceExtension
->IrpListHead
);
23 KeInitializeEvent(&FDODeviceExtension
->NoPendingRequests
, NotificationEvent
, TRUE
);
29 IN PDEVICE_OBJECT DeviceObject
,
32 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
34 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
35 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL
);
36 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
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
;
43 USBSTOR_QueueTerminateRequest(DeviceObject
, Irp
);
44 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
46 USBSTOR_QueueNextRequest(DeviceObject
);
52 IN PDEVICE_OBJECT DeviceObject
,
55 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
57 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
58 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL
);
59 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
61 KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension
->IrpListLock
);
62 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
63 KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension
->IrpListLock
);
65 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
66 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
68 USBSTOR_QueueTerminateRequest(DeviceObject
, Irp
);
69 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
71 USBSTOR_QueueNextRequest(DeviceObject
);
76 IN PDEVICE_OBJECT DeviceObject
,
79 PDRIVER_CANCEL OldDriverCancel
;
81 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
82 BOOLEAN IrpListFreeze
;
83 BOOLEAN SrbProcessing
;
84 PIO_STACK_LOCATION IoStack
= IoGetCurrentIrpStackLocation(Irp
);
85 PSCSI_REQUEST_BLOCK Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
87 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
88 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
90 IoMarkIrpPending(Irp
);
92 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
94 SrbProcessing
= FDODeviceExtension
->IrpPendingCount
!= 0;
99 InsertTailList(&FDODeviceExtension
->IrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
102 FDODeviceExtension
->IrpPendingCount
++;
103 KeClearEvent(&FDODeviceExtension
->NoPendingRequests
);
105 // check if queue is freezed
106 IrpListFreeze
= FDODeviceExtension
->IrpListFreeze
;
108 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
110 // synchronize with cancellations by holding the cancel lock
111 IoAcquireCancelSpinLock(&Irp
->CancelIrql
);
115 ASSERT(FDODeviceExtension
->ActiveSrb
!= NULL
);
117 OldDriverCancel
= IoSetCancelRoutine(Irp
, USBSTOR_Cancel
);
121 ASSERT(FDODeviceExtension
->ActiveSrb
== NULL
);
123 FDODeviceExtension
->ActiveSrb
= Request
;
124 OldDriverCancel
= IoSetCancelRoutine(Irp
, USBSTOR_CancelIo
);
127 // check if the irp has already been cancelled
128 if (Irp
->Cancel
&& OldDriverCancel
== NULL
)
131 Irp
->CancelRoutine(DeviceObject
, Irp
);
135 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
137 // if list is freezed, dont start this packet
138 DPRINT("IrpListFreeze: %lu IrpPendingCount %lu\n", IrpListFreeze
, FDODeviceExtension
->IrpPendingCount
);
140 return (IrpListFreeze
|| SrbProcessing
);
145 IN PDEVICE_OBJECT DeviceObject
)
148 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
152 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
153 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
155 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
157 if (!IsListEmpty(&FDODeviceExtension
->IrpListHead
))
159 Entry
= RemoveHeadList(&FDODeviceExtension
->IrpListHead
);
161 // get offset to start of irp
162 Irp
= (PIRP
)CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
165 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
171 USBSTOR_QueueWaitForPendingRequests(
172 IN PDEVICE_OBJECT DeviceObject
)
174 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
176 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
178 KeWaitForSingleObject(&FDODeviceExtension
->NoPendingRequests
,
186 USBSTOR_QueueTerminateRequest(
187 IN PDEVICE_OBJECT FDODeviceObject
,
191 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
192 PIO_STACK_LOCATION IoStack
= IoGetCurrentIrpStackLocation(Irp
);
193 PSCSI_REQUEST_BLOCK Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
195 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)FDODeviceObject
->DeviceExtension
;
196 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
198 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
200 FDODeviceExtension
->IrpPendingCount
--;
202 // check if this was our current active SRB
203 if (FDODeviceExtension
->ActiveSrb
== Request
)
205 // indicate processing is completed
206 FDODeviceExtension
->ActiveSrb
= NULL
;
209 // Set the event if nothing else is pending
210 if (FDODeviceExtension
->IrpPendingCount
== 0 &&
211 FDODeviceExtension
->ActiveSrb
== NULL
)
213 KeSetEvent(&FDODeviceExtension
->NoPendingRequests
, IO_NO_INCREMENT
, FALSE
);
216 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
220 USBSTOR_QueueNextRequest(
221 IN PDEVICE_OBJECT DeviceObject
)
223 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
225 PIO_STACK_LOCATION IoStack
;
226 PSCSI_REQUEST_BLOCK Request
;
228 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
229 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
231 // check first if there's already a request pending or the queue is frozen
232 if (FDODeviceExtension
->ActiveSrb
!= NULL
||
233 FDODeviceExtension
->IrpListFreeze
)
239 // remove first irp from list
240 Irp
= USBSTOR_RemoveIrp(DeviceObject
);
242 // is there an irp pending
246 IoStartNextPacket(DeviceObject
, TRUE
);
250 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
251 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
254 FDODeviceExtension
->ActiveSrb
= Request
;
257 IoStartPacket(DeviceObject
, Irp
, &Request
->QueueSortKey
, USBSTOR_CancelIo
);
258 IoStartNextPacket(DeviceObject
, TRUE
);
262 USBSTOR_QueueRelease(
263 IN PDEVICE_OBJECT DeviceObject
)
265 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
268 PIO_STACK_LOCATION IoStack
;
269 PSCSI_REQUEST_BLOCK Request
;
271 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
272 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
274 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
276 // clear freezed status
277 FDODeviceExtension
->IrpListFreeze
= FALSE
;
279 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
282 Irp
= USBSTOR_RemoveIrp(DeviceObject
);
289 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
290 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
292 IoStartPacket(DeviceObject
,
294 &Request
->QueueSortKey
,
301 PDEVICE_OBJECT DeviceObject
,
304 PIO_STACK_LOCATION IoStack
;
305 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
306 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
308 BOOLEAN ResetInProgress
;
310 DPRINT("USBSTOR_StartIo\n");
312 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
313 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
315 IoAcquireCancelSpinLock(&OldLevel
);
317 IoSetCancelRoutine(Irp
, NULL
);
319 // check if the irp has been cancelled
322 IoReleaseCancelSpinLock(OldLevel
);
324 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
325 Irp
->IoStatus
.Information
= 0;
327 USBSTOR_QueueTerminateRequest(DeviceObject
, Irp
);
328 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
329 USBSTOR_QueueNextRequest(DeviceObject
);
333 IoReleaseCancelSpinLock(OldLevel
);
335 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
337 ResetInProgress
= FDODeviceExtension
->ResetInProgress
;
338 ASSERT(ResetInProgress
== FALSE
);
340 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
342 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
344 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
345 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
347 // TODO: this condition is always false
350 // hard reset is in progress
351 Irp
->IoStatus
.Information
= 0;
352 Irp
->IoStatus
.Status
= STATUS_DEVICE_DOES_NOT_EXIST
;
353 USBSTOR_QueueTerminateRequest(DeviceObject
, Irp
);
354 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
358 USBSTOR_HandleExecuteSCSI(IoStack
->DeviceObject
, Irp
, 0);
360 // FIXME: handle error