2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbstor/queue.c
5 * PURPOSE: USB block storage device driver.
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
15 USBSTOR_QueueInitialize(
16 PFDO_DEVICE_EXTENSION FDODeviceExtension
)
21 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
24 // initialize queue lock
26 KeInitializeSpinLock(&FDODeviceExtension
->IrpListLock
);
29 // initialize irp list head
31 InitializeListHead(&FDODeviceExtension
->IrpListHead
);
36 KeInitializeEvent(&FDODeviceExtension
->NoPendingRequests
, NotificationEvent
, TRUE
);
42 IN PDEVICE_OBJECT DeviceObject
,
45 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
48 // get FDO device extension
50 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
55 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
56 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
59 // this IRP isn't in our list here
63 // now release the cancel lock
65 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
70 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
75 USBSTOR_QueueTerminateRequest(DeviceObject
, Irp
);
76 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
81 USBSTOR_QueueNextRequest(DeviceObject
);
87 IN PDEVICE_OBJECT DeviceObject
,
90 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
93 // get FDO device extension
95 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
100 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
101 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
104 // acquire irp list lock
106 KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension
->IrpListLock
);
109 // remove the irp from the list
111 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
114 // release irp list lock
116 KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension
->IrpListLock
);
119 // now release the cancel lock
121 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
126 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
129 // now cancel the irp
131 USBSTOR_QueueTerminateRequest(DeviceObject
, Irp
);
132 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
135 // start the next one
137 USBSTOR_QueueNextRequest(DeviceObject
);
142 IN PDEVICE_OBJECT DeviceObject
,
145 PDRIVER_CANCEL OldDriverCancel
;
147 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
148 BOOLEAN IrpListFreeze
;
149 BOOLEAN SrbProcessing
;
150 PIO_STACK_LOCATION IoStack
= IoGetCurrentIrpStackLocation(Irp
);
151 PSCSI_REQUEST_BLOCK Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
154 // get FDO device extension
156 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
161 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
166 IoMarkIrpPending(Irp
);
171 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
174 // check if there are irp pending
176 SrbProcessing
= FDODeviceExtension
->IrpPendingCount
!= 0;
183 InsertTailList(&FDODeviceExtension
->IrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
187 // increment pending count
189 FDODeviceExtension
->IrpPendingCount
++;
193 // clear the no requests pending event
195 KeClearEvent(&FDODeviceExtension
->NoPendingRequests
);
198 // check if queue is freezed
200 IrpListFreeze
= FDODeviceExtension
->IrpListFreeze
;
205 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
208 // synchronize with cancellations by holding the cancel lock
210 IoAcquireCancelSpinLock(&Irp
->CancelIrql
);
213 // now set the driver cancel routine
217 ASSERT(FDODeviceExtension
->ActiveSrb
!= NULL
);
219 OldDriverCancel
= IoSetCancelRoutine(Irp
, USBSTOR_Cancel
);
223 ASSERT(FDODeviceExtension
->ActiveSrb
== NULL
);
225 FDODeviceExtension
->ActiveSrb
= Request
;
226 OldDriverCancel
= IoSetCancelRoutine(Irp
, USBSTOR_CancelIo
);
230 // check if the irp has already been cancelled
232 if (Irp
->Cancel
&& OldDriverCancel
== NULL
)
237 Irp
->CancelRoutine(DeviceObject
, Irp
);
246 // release the cancel lock
248 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
251 // if list is freezed, dont start this packet
253 DPRINT("IrpListFreeze: %lu IrpPendingCount %lu\n", IrpListFreeze
, FDODeviceExtension
->IrpPendingCount
);
255 return (IrpListFreeze
|| SrbProcessing
);
260 IN PDEVICE_OBJECT DeviceObject
)
263 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
268 // get FDO device extension
270 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
275 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
280 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
283 // check if list is empty
285 if (!IsListEmpty(&FDODeviceExtension
->IrpListHead
))
290 Entry
= RemoveHeadList(&FDODeviceExtension
->IrpListHead
);
293 // get offset to start of irp
295 Irp
= (PIRP
)CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
301 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
310 USBSTOR_QueueWaitForPendingRequests(
311 IN PDEVICE_OBJECT DeviceObject
)
313 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
316 // get FDO device extension
318 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
323 KeWaitForSingleObject(&FDODeviceExtension
->NoPendingRequests
,
331 USBSTOR_QueueTerminateRequest(
332 IN PDEVICE_OBJECT FDODeviceObject
,
336 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
337 PIO_STACK_LOCATION IoStack
= IoGetCurrentIrpStackLocation(Irp
);
338 PSCSI_REQUEST_BLOCK Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
341 // get FDO device extension
343 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)FDODeviceObject
->DeviceExtension
;
348 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
353 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
356 // decrement pending irp count
358 FDODeviceExtension
->IrpPendingCount
--;
361 // check if this was our current active SRB
363 if (FDODeviceExtension
->ActiveSrb
== Request
)
366 // indicate processing is completed
368 FDODeviceExtension
->ActiveSrb
= NULL
;
372 // Set the event if nothing else is pending
374 if (FDODeviceExtension
->IrpPendingCount
== 0 &&
375 FDODeviceExtension
->ActiveSrb
== NULL
)
377 KeSetEvent(&FDODeviceExtension
->NoPendingRequests
, IO_NO_INCREMENT
, FALSE
);
383 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
388 USBSTOR_QueueNextRequest(
389 IN PDEVICE_OBJECT DeviceObject
)
391 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
393 PIO_STACK_LOCATION IoStack
;
394 PSCSI_REQUEST_BLOCK Request
;
397 // get pdo device extension
399 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
404 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
407 // check first if there's already a request pending or the queue is frozen
409 if (FDODeviceExtension
->ActiveSrb
!= NULL
||
410 FDODeviceExtension
->IrpListFreeze
)
419 // remove first irp from list
421 Irp
= USBSTOR_RemoveIrp(DeviceObject
);
424 // is there an irp pending
431 IoStartNextPacket(DeviceObject
, TRUE
);
436 // get current stack location
438 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
443 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
451 // set the active SRB
453 FDODeviceExtension
->ActiveSrb
= Request
;
458 IoStartPacket(DeviceObject
, Irp
, &Request
->QueueSortKey
, USBSTOR_CancelIo
);
461 // start next request
463 IoStartNextPacket(DeviceObject
, TRUE
);
467 USBSTOR_QueueRelease(
468 IN PDEVICE_OBJECT DeviceObject
)
470 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
473 PIO_STACK_LOCATION IoStack
;
474 PSCSI_REQUEST_BLOCK Request
;
477 // get FDO device extension
479 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
484 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
489 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
492 // clear freezed status
494 FDODeviceExtension
->IrpListFreeze
= FALSE
;
497 // release irp list lock
499 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
504 Irp
= USBSTOR_RemoveIrp(DeviceObject
);
518 // get current irp stack location
520 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
525 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
530 IoStartPacket(DeviceObject
,
532 &Request
->QueueSortKey
,
540 PDEVICE_OBJECT DeviceObject
,
543 PIO_STACK_LOCATION IoStack
;
544 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
545 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
548 BOOLEAN ResetInProgress
;
550 DPRINT("USBSTOR_StartIo\n");
553 // get FDO device extension
555 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
560 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
563 // acquire cancel spinlock
565 IoAcquireCancelSpinLock(&OldLevel
);
568 // set cancel routine to zero
570 IoSetCancelRoutine(Irp
, NULL
);
573 // check if the irp has been cancelled
578 // irp has been cancelled, release cancel spinlock
580 IoReleaseCancelSpinLock(OldLevel
);
585 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
586 Irp
->IoStatus
.Information
= 0;
591 USBSTOR_QueueTerminateRequest(DeviceObject
, Irp
);
596 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
599 // queue next request
601 USBSTOR_QueueNextRequest(DeviceObject
);
610 // release cancel spinlock
612 IoReleaseCancelSpinLock(OldLevel
);
617 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
620 // check reset is in progress
622 ResetInProgress
= FDODeviceExtension
->ResetInProgress
;
623 ASSERT(ResetInProgress
== FALSE
);
628 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
631 // get current irp stack location
633 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
636 // get pdo device extension
638 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
643 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
646 // is a reset in progress
651 // hard reset is in progress
653 Irp
->IoStatus
.Information
= 0;
654 Irp
->IoStatus
.Status
= STATUS_DEVICE_DOES_NOT_EXIST
;
655 USBSTOR_QueueTerminateRequest(DeviceObject
, Irp
);
656 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
663 Status
= USBSTOR_HandleExecuteSCSI(IoStack
->DeviceObject
, Irp
, 0);
666 // FIXME: handle error