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)
18 USBSTOR_QueueInitialize(
19 PFDO_DEVICE_EXTENSION FDODeviceExtension
)
24 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
27 // initialize queue lock
29 KeInitializeSpinLock(&FDODeviceExtension
->IrpListLock
);
32 // initialize irp list head
34 InitializeListHead(&FDODeviceExtension
->IrpListHead
);
39 KeInitializeEvent(&FDODeviceExtension
->NoPendingRequests
, NotificationEvent
, TRUE
);
45 IN PDEVICE_OBJECT DeviceObject
,
48 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
51 // get FDO device extension
53 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
58 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
59 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
62 // this IRP isn't in our list here
66 // now release the cancel lock
68 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
73 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
78 USBSTOR_QueueTerminateRequest(DeviceObject
, Irp
);
79 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
84 USBSTOR_QueueNextRequest(DeviceObject
);
90 IN PDEVICE_OBJECT DeviceObject
,
93 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
96 // get FDO device extension
98 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
103 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
104 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
107 // acquire irp list lock
109 KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension
->IrpListLock
);
112 // remove the irp from the list
114 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
117 // release irp list lock
119 KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension
->IrpListLock
);
122 // now release the cancel lock
124 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
129 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
132 // now cancel the irp
134 USBSTOR_QueueTerminateRequest(DeviceObject
, Irp
);
135 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
138 // start the next one
140 USBSTOR_QueueNextRequest(DeviceObject
);
145 IN PDEVICE_OBJECT DeviceObject
,
148 PDRIVER_CANCEL OldDriverCancel
;
150 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
151 BOOLEAN IrpListFreeze
;
152 BOOLEAN SrbProcessing
;
153 PIO_STACK_LOCATION IoStack
= IoGetCurrentIrpStackLocation(Irp
);
154 PSCSI_REQUEST_BLOCK Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
157 // get FDO device extension
159 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
164 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
169 IoMarkIrpPending(Irp
);
174 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
177 // check if there are irp pending
179 SrbProcessing
= FDODeviceExtension
->IrpPendingCount
!= 0;
186 InsertTailList(&FDODeviceExtension
->IrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
190 // increment pending count
192 FDODeviceExtension
->IrpPendingCount
++;
196 // clear the no requests pending event
198 KeClearEvent(&FDODeviceExtension
->NoPendingRequests
);
201 // check if queue is freezed
203 IrpListFreeze
= FDODeviceExtension
->IrpListFreeze
;
208 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
211 // synchronize with cancellations by holding the cancel lock
213 IoAcquireCancelSpinLock(&Irp
->CancelIrql
);
216 // now set the driver cancel routine
220 ASSERT(FDODeviceExtension
->ActiveSrb
!= NULL
);
222 OldDriverCancel
= IoSetCancelRoutine(Irp
, USBSTOR_Cancel
);
226 ASSERT(FDODeviceExtension
->ActiveSrb
== NULL
);
228 FDODeviceExtension
->ActiveSrb
= Request
;
229 OldDriverCancel
= IoSetCancelRoutine(Irp
, USBSTOR_CancelIo
);
233 // check if the irp has already been cancelled
235 if (Irp
->Cancel
&& OldDriverCancel
== NULL
)
240 Irp
->CancelRoutine(DeviceObject
, Irp
);
249 // release the cancel lock
251 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
254 // if list is freezed, dont start this packet
256 DPRINT("IrpListFreeze: %lu IrpPendingCount %lu\n", IrpListFreeze
, FDODeviceExtension
->IrpPendingCount
);
258 return (IrpListFreeze
|| SrbProcessing
);
263 IN PDEVICE_OBJECT DeviceObject
)
266 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
271 // get FDO device extension
273 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
278 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
283 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
286 // check if list is empty
288 if (!IsListEmpty(&FDODeviceExtension
->IrpListHead
))
293 Entry
= RemoveHeadList(&FDODeviceExtension
->IrpListHead
);
296 // get offset to start of irp
298 Irp
= (PIRP
)CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
304 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
313 USBSTOR_QueueWaitForPendingRequests(
314 IN PDEVICE_OBJECT DeviceObject
)
316 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
319 // get FDO device extension
321 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
326 KeWaitForSingleObject(&FDODeviceExtension
->NoPendingRequests
,
334 USBSTOR_QueueTerminateRequest(
335 IN PDEVICE_OBJECT FDODeviceObject
,
339 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
340 PIO_STACK_LOCATION IoStack
= IoGetCurrentIrpStackLocation(Irp
);
341 PSCSI_REQUEST_BLOCK Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
344 // get FDO device extension
346 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)FDODeviceObject
->DeviceExtension
;
351 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
356 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
359 // decrement pending irp count
361 FDODeviceExtension
->IrpPendingCount
--;
364 // check if this was our current active SRB
366 if (FDODeviceExtension
->ActiveSrb
== Request
)
369 // indicate processing is completed
371 FDODeviceExtension
->ActiveSrb
= NULL
;
375 // Set the event if nothing else is pending
377 if (FDODeviceExtension
->IrpPendingCount
== 0 &&
378 FDODeviceExtension
->ActiveSrb
== NULL
)
380 KeSetEvent(&FDODeviceExtension
->NoPendingRequests
, IO_NO_INCREMENT
, FALSE
);
386 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
391 USBSTOR_QueueNextRequest(
392 IN PDEVICE_OBJECT DeviceObject
)
394 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
396 PIO_STACK_LOCATION IoStack
;
397 PSCSI_REQUEST_BLOCK Request
;
400 // get pdo device extension
402 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
407 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
410 // check first if there's already a request pending or the queue is frozen
412 if (FDODeviceExtension
->ActiveSrb
!= NULL
||
413 FDODeviceExtension
->IrpListFreeze
)
422 // remove first irp from list
424 Irp
= USBSTOR_RemoveIrp(DeviceObject
);
427 // is there an irp pending
434 IoStartNextPacket(DeviceObject
, TRUE
);
439 // get current stack location
441 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
446 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
454 // set the active SRB
456 FDODeviceExtension
->ActiveSrb
= Request
;
461 IoStartPacket(DeviceObject
, Irp
, &Request
->QueueSortKey
, USBSTOR_CancelIo
);
464 // start next request
466 IoStartNextPacket(DeviceObject
, TRUE
);
470 USBSTOR_QueueRelease(
471 IN PDEVICE_OBJECT DeviceObject
)
473 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
476 PIO_STACK_LOCATION IoStack
;
477 PSCSI_REQUEST_BLOCK Request
;
480 // get FDO device extension
482 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
487 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
492 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
495 // clear freezed status
497 FDODeviceExtension
->IrpListFreeze
= FALSE
;
500 // release irp list lock
502 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
507 Irp
= USBSTOR_RemoveIrp(DeviceObject
);
521 // get current irp stack location
523 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
528 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
533 IoStartPacket(DeviceObject
,
535 &Request
->QueueSortKey
,
543 PDEVICE_OBJECT DeviceObject
,
546 PIO_STACK_LOCATION IoStack
;
547 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
548 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
550 BOOLEAN ResetInProgress
;
552 DPRINT("USBSTOR_StartIo\n");
555 // get FDO device extension
557 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
562 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
565 // acquire cancel spinlock
567 IoAcquireCancelSpinLock(&OldLevel
);
570 // set cancel routine to zero
572 IoSetCancelRoutine(Irp
, NULL
);
575 // check if the irp has been cancelled
580 // irp has been cancelled, release cancel spinlock
582 IoReleaseCancelSpinLock(OldLevel
);
587 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
588 Irp
->IoStatus
.Information
= 0;
593 USBSTOR_QueueTerminateRequest(DeviceObject
, Irp
);
598 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
601 // queue next request
603 USBSTOR_QueueNextRequest(DeviceObject
);
612 // release cancel spinlock
614 IoReleaseCancelSpinLock(OldLevel
);
619 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
622 // check reset is in progress
624 ResetInProgress
= FDODeviceExtension
->ResetInProgress
;
625 ASSERT(ResetInProgress
== FALSE
);
630 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
633 // get current irp stack location
635 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
638 // get pdo device extension
640 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
645 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
648 // is a reset in progress
653 // hard reset is in progress
655 Irp
->IoStatus
.Information
= 0;
656 Irp
->IoStatus
.Status
= STATUS_DEVICE_DOES_NOT_EXIST
;
657 USBSTOR_QueueTerminateRequest(DeviceObject
, Irp
);
658 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
665 USBSTOR_HandleExecuteSCSI(IoStack
->DeviceObject
, Irp
, 0);
668 // FIXME: handle error