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
);
37 IN PDEVICE_OBJECT DeviceObject
,
40 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
43 // get FDO device extension
45 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
50 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
51 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
54 // acquire irp list lock
56 KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension
->IrpListLock
);
59 // now release the cancel lock
61 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
64 // remove the irp from the list
66 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
69 // release irp list lock
71 KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension
->IrpListLock
);
76 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
81 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
87 IN PDEVICE_OBJECT DeviceObject
,
90 PDRIVER_CANCEL OldDriverCancel
;
92 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
93 BOOLEAN IrpListFreeze
;
94 BOOLEAN SrbProcessing
;
97 // get FDO device extension
99 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
104 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
109 IoMarkIrpPending(Irp
);
114 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
117 // check if there are irp pending
119 SrbProcessing
= FDODeviceExtension
->IrpPendingCount
!= 0;
126 InsertTailList(&FDODeviceExtension
->IrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
130 // increment pending count
132 FDODeviceExtension
->IrpPendingCount
++;
135 // now set the driver cancel routine
137 OldDriverCancel
= IoSetCancelRoutine(Irp
, USBSTOR_CancelIo
);
140 // check if the irp has already been cancelled
142 if (Irp
->Cancel
&& OldDriverCancel
== NULL
)
145 // the irp has already been cancelled
147 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
150 // cancel routine requires that cancel spinlock is held
152 IoAcquireCancelSpinLock(&Irp
->CancelIrql
);
157 USBSTOR_CancelIo(DeviceObject
, Irp
);
166 // check if queue is freezed
168 IrpListFreeze
= FDODeviceExtension
->IrpListFreeze
;
173 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
176 // if list is freezed, dont start this packet
178 DPRINT1("IrpListFreeze: %lu IrpPendingCount %lu\n", IrpListFreeze
, FDODeviceExtension
->IrpPendingCount
);
180 return (IrpListFreeze
|| SrbProcessing
);
185 IN PDEVICE_OBJECT DeviceObject
)
188 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
193 // get FDO device extension
195 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
200 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
205 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
208 // check if list is empty
210 if (!IsListEmpty(&FDODeviceExtension
->IrpListHead
))
215 Entry
= RemoveHeadList(&FDODeviceExtension
->IrpListHead
);
218 // get offset to start of irp
220 Irp
= (PIRP
)CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
226 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
235 USBSTOR_QueueFlushIrps(
236 IN PDEVICE_OBJECT DeviceObject
)
239 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
242 PIO_STACK_LOCATION IoStack
;
243 PSCSI_REQUEST_BLOCK Request
;
246 // get FDO device extension
248 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
253 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
258 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
261 // complete all irps with status cancelled
263 while(!IsListEmpty(&FDODeviceExtension
->IrpListHead
))
268 Entry
= RemoveHeadList(&FDODeviceExtension
->IrpListHead
);
271 // get start of irp structure
273 Irp
= (PIRP
)CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
276 // get current stack location
278 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
283 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
291 // set srb status to flushed
293 Request
->SrbStatus
= SRB_STATUS_REQUEST_FLUSHED
;
296 // set unsuccessful status
298 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
303 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
309 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
313 USBSTOR_QueueTerminateRequest(
314 IN PDEVICE_OBJECT FDODeviceObject
,
315 IN BOOLEAN ModifySrbState
)
318 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
321 // get FDO device extension
323 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)FDODeviceObject
->DeviceExtension
;
328 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
333 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
336 // decrement pending irp count
338 FDODeviceExtension
->IrpPendingCount
--;
345 ASSERT(FDODeviceExtension
->SrbActive
== TRUE
);
348 // indicate processing is completed
350 FDODeviceExtension
->SrbActive
= FALSE
;
356 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
361 USBSTOR_QueueNextRequest(
362 IN PDEVICE_OBJECT DeviceObject
)
364 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
366 PIO_STACK_LOCATION IoStack
;
367 PSCSI_REQUEST_BLOCK Request
;
370 // get pdo device extension
372 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
377 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
380 // remove first irp from list
382 Irp
= USBSTOR_RemoveIrp(DeviceObject
);
385 // is there an irp pending
392 IoStartNextPacket(DeviceObject
, TRUE
);
397 // get current stack location
399 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
404 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
414 IoStartPacket(DeviceObject
, Irp
, &Request
->QueueSortKey
, USBSTOR_CancelIo
);
417 // start next request
419 IoStartNextPacket(DeviceObject
, TRUE
);
423 USBSTOR_QueueRelease(
424 IN PDEVICE_OBJECT DeviceObject
)
426 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
429 PIO_STACK_LOCATION IoStack
;
430 PSCSI_REQUEST_BLOCK Request
;
433 // get FDO device extension
435 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
440 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
445 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
448 // clear freezed status
450 FDODeviceExtension
->IrpListFreeze
= FALSE
;
453 // release irp list lock
455 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
460 Irp
= USBSTOR_RemoveIrp(DeviceObject
);
474 // get current irp stack location
476 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
481 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
486 IoStartPacket(DeviceObject
,
488 &Request
->QueueSortKey
,
496 PDEVICE_OBJECT DeviceObject
,
499 PIO_STACK_LOCATION IoStack
;
500 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
501 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
504 BOOLEAN ResetInProgress
;
506 DPRINT1("USBSTOR_StartIo\n");
509 // get FDO device extension
511 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
516 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
519 // acquire cancel spinlock
521 IoAcquireCancelSpinLock(&OldLevel
);
524 // set cancel routine to zero
526 IoSetCancelRoutine(Irp
, NULL
);
529 // check if the irp has been cancelled
534 // irp has been cancelled, release cancel spinlock
536 IoReleaseCancelSpinLock(OldLevel
);
541 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
542 Irp
->IoStatus
.Information
= 0;
547 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
550 // check if the queue has been frozen
552 if (FDODeviceExtension
->IrpListFreeze
== FALSE
)
555 // queue next request
557 USBSTOR_QueueTerminateRequest(DeviceObject
, FALSE
);
558 USBSTOR_QueueNextRequest(DeviceObject
);
568 // release cancel spinlock
570 IoReleaseCancelSpinLock(OldLevel
);
575 KeAcquireSpinLock(&FDODeviceExtension
->IrpListLock
, &OldLevel
);
578 // check reset is in progress
580 ResetInProgress
= FDODeviceExtension
->ResetInProgress
;
581 ASSERT(ResetInProgress
== FALSE
);
586 ASSERT(FDODeviceExtension
->SrbActive
== FALSE
);
587 FDODeviceExtension
->SrbActive
= TRUE
;
592 KeReleaseSpinLock(&FDODeviceExtension
->IrpListLock
, OldLevel
);
595 // get current irp stack location
597 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
600 // get pdo device extension
602 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
607 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
610 // is a reset in progress
615 // hard reset is in progress
617 Irp
->IoStatus
.Information
= 0;
618 Irp
->IoStatus
.Status
= STATUS_DEVICE_DOES_NOT_EXIST
;
619 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
620 USBSTOR_QueueTerminateRequest(DeviceObject
, TRUE
);
627 Status
= USBSTOR_HandleExecuteSCSI(IoStack
->DeviceObject
, Irp
);
630 // FIXME: handle error