+++ /dev/null
-/*
- * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: drivers/usb/usbstor/queue.c
- * PURPOSE: USB block storage device driver.
- * PROGRAMMERS:
- * James Tabor
- * Michael Martin (michael.martin@reactos.org)
- * Johannes Anderwald (johannes.anderwald@reactos.org)
- */
-
-#include "usbstor.h"
-
-#define NDEBUG
-#include <debug.h>
-
-VOID
-USBSTOR_QueueInitialize(
- PFDO_DEVICE_EXTENSION FDODeviceExtension)
-{
- //
- // sanity check
- //
- ASSERT(FDODeviceExtension->Common.IsFDO);
-
- //
- // initialize queue lock
- //
- KeInitializeSpinLock(&FDODeviceExtension->IrpListLock);
-
- //
- // initialize irp list head
- //
- InitializeListHead(&FDODeviceExtension->IrpListHead);
-
- //
- // initialize event
- //
- KeInitializeEvent(&FDODeviceExtension->NoPendingRequests, NotificationEvent, TRUE);
-}
-
-VOID
-NTAPI
-USBSTOR_CancelIo(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- PFDO_DEVICE_EXTENSION FDODeviceExtension;
-
- //
- // get FDO device extension
- //
- FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- //
- // sanity check
- //
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
- ASSERT(FDODeviceExtension->Common.IsFDO);
-
- //
- // this IRP isn't in our list here
- //
-
- //
- // now release the cancel lock
- //
- IoReleaseCancelSpinLock(Irp->CancelIrql);
-
- //
- // set cancel status
- //
- Irp->IoStatus.Status = STATUS_CANCELLED;
-
- //
- // now cancel the irp
- //
- USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- //
- // start the next one
- //
- USBSTOR_QueueNextRequest(DeviceObject);
-}
-
-VOID
-NTAPI
-USBSTOR_Cancel(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- PFDO_DEVICE_EXTENSION FDODeviceExtension;
-
- //
- // get FDO device extension
- //
- FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- //
- // sanity check
- //
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
- ASSERT(FDODeviceExtension->Common.IsFDO);
-
- //
- // acquire irp list lock
- //
- KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
-
- //
- // remove the irp from the list
- //
- RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
-
- //
- // release irp list lock
- //
- KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock);
-
- //
- // now release the cancel lock
- //
- IoReleaseCancelSpinLock(Irp->CancelIrql);
-
- //
- // set cancel status
- //
- Irp->IoStatus.Status = STATUS_CANCELLED;
-
- //
- // now cancel the irp
- //
- USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- //
- // start the next one
- //
- USBSTOR_QueueNextRequest(DeviceObject);
-}
-
-BOOLEAN
-USBSTOR_QueueAddIrp(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- PDRIVER_CANCEL OldDriverCancel;
- KIRQL OldLevel;
- PFDO_DEVICE_EXTENSION FDODeviceExtension;
- BOOLEAN IrpListFreeze;
- BOOLEAN SrbProcessing;
- PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
- PSCSI_REQUEST_BLOCK Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
-
- //
- // get FDO device extension
- //
- FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- //
- // sanity check
- //
- ASSERT(FDODeviceExtension->Common.IsFDO);
-
- //
- // mark irp pending
- //
- IoMarkIrpPending(Irp);
-
- //
- // acquire lock
- //
- KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
-
- //
- // check if there are irp pending
- //
- SrbProcessing = FDODeviceExtension->IrpPendingCount != 0;
-
- if (SrbProcessing)
- {
- //
- // add irp to queue
- //
- InsertTailList(&FDODeviceExtension->IrpListHead, &Irp->Tail.Overlay.ListEntry);
- }
-
- //
- // increment pending count
- //
- FDODeviceExtension->IrpPendingCount++;
-
-
- //
- // clear the no requests pending event
- //
- KeClearEvent(&FDODeviceExtension->NoPendingRequests);
-
- //
- // check if queue is freezed
- //
- IrpListFreeze = FDODeviceExtension->IrpListFreeze;
-
- //
- // release list lock
- //
- KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
-
- //
- // synchronize with cancellations by holding the cancel lock
- //
- IoAcquireCancelSpinLock(&Irp->CancelIrql);
-
- //
- // now set the driver cancel routine
- //
- if (SrbProcessing)
- {
- ASSERT(FDODeviceExtension->ActiveSrb != NULL);
-
- OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_Cancel);
- }
- else
- {
- ASSERT(FDODeviceExtension->ActiveSrb == NULL);
-
- FDODeviceExtension->ActiveSrb = Request;
- OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_CancelIo);
- }
-
- //
- // check if the irp has already been cancelled
- //
- if (Irp->Cancel && OldDriverCancel == NULL)
- {
- //
- // cancel irp
- //
- Irp->CancelRoutine(DeviceObject, Irp);
-
- //
- // irp was cancelled
- //
- return FALSE;
- }
-
- //
- // release the cancel lock
- //
- IoReleaseCancelSpinLock(Irp->CancelIrql);
-
- //
- // if list is freezed, dont start this packet
- //
- DPRINT("IrpListFreeze: %lu IrpPendingCount %lu\n", IrpListFreeze, FDODeviceExtension->IrpPendingCount);
-
- return (IrpListFreeze || SrbProcessing);
-}
-
-PIRP
-USBSTOR_RemoveIrp(
- IN PDEVICE_OBJECT DeviceObject)
-{
- KIRQL OldLevel;
- PFDO_DEVICE_EXTENSION FDODeviceExtension;
- PLIST_ENTRY Entry;
- PIRP Irp = NULL;
-
- //
- // get FDO device extension
- //
- FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- //
- // sanity check
- //
- ASSERT(FDODeviceExtension->Common.IsFDO);
-
- //
- // acquire lock
- //
- KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
-
- //
- // check if list is empty
- //
- if (!IsListEmpty(&FDODeviceExtension->IrpListHead))
- {
- //
- // remove entry
- //
- Entry = RemoveHeadList(&FDODeviceExtension->IrpListHead);
-
- //
- // get offset to start of irp
- //
- Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
- }
-
- //
- // release list lock
- //
- KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
-
- //
- // return result
- //
- return Irp;
-}
-
-VOID
-USBSTOR_QueueWaitForPendingRequests(
- IN PDEVICE_OBJECT DeviceObject)
-{
- PFDO_DEVICE_EXTENSION FDODeviceExtension;
-
- //
- // get FDO device extension
- //
- FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- //
- // perform the wait
- //
- KeWaitForSingleObject(&FDODeviceExtension->NoPendingRequests,
- Executive,
- KernelMode,
- FALSE,
- NULL);
-}
-
-VOID
-USBSTOR_QueueTerminateRequest(
- IN PDEVICE_OBJECT FDODeviceObject,
- IN PIRP Irp)
-{
- KIRQL OldLevel;
- PFDO_DEVICE_EXTENSION FDODeviceExtension;
- PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
- PSCSI_REQUEST_BLOCK Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
-
- //
- // get FDO device extension
- //
- FDODeviceExtension = (PFDO_DEVICE_EXTENSION)FDODeviceObject->DeviceExtension;
-
- //
- // sanity check
- //
- ASSERT(FDODeviceExtension->Common.IsFDO);
-
- //
- // acquire lock
- //
- KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
-
- //
- // decrement pending irp count
- //
- FDODeviceExtension->IrpPendingCount--;
-
- //
- // check if this was our current active SRB
- //
- if (FDODeviceExtension->ActiveSrb == Request)
- {
- //
- // indicate processing is completed
- //
- FDODeviceExtension->ActiveSrb = NULL;
- }
-
- //
- // Set the event if nothing else is pending
- //
- if (FDODeviceExtension->IrpPendingCount == 0 &&
- FDODeviceExtension->ActiveSrb == NULL)
- {
- KeSetEvent(&FDODeviceExtension->NoPendingRequests, IO_NO_INCREMENT, FALSE);
- }
-
- //
- // release lock
- //
- KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
-
-}
-
-VOID
-USBSTOR_QueueNextRequest(
- IN PDEVICE_OBJECT DeviceObject)
-{
- PFDO_DEVICE_EXTENSION FDODeviceExtension;
- PIRP Irp;
- PIO_STACK_LOCATION IoStack;
- PSCSI_REQUEST_BLOCK Request;
-
- //
- // get pdo device extension
- //
- FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- //
- // sanity check
- //
- ASSERT(FDODeviceExtension->Common.IsFDO);
-
- //
- // check first if there's already a request pending or the queue is frozen
- //
- if (FDODeviceExtension->ActiveSrb != NULL ||
- FDODeviceExtension->IrpListFreeze)
- {
- //
- // no work to do yet
- //
- return;
- }
-
- //
- // remove first irp from list
- //
- Irp = USBSTOR_RemoveIrp(DeviceObject);
-
- //
- // is there an irp pending
- //
- if (!Irp)
- {
- //
- // no work to do
- //
- IoStartNextPacket(DeviceObject, TRUE);
- return;
- }
-
- //
- // get current stack location
- //
- IoStack = IoGetCurrentIrpStackLocation(Irp);
-
- //
- // get srb
- //
- Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
-
- //
- // sanity check
- //
- ASSERT(Request);
-
- //
- // set the active SRB
- //
- FDODeviceExtension->ActiveSrb = Request;
-
- //
- // start next packet
- //
- IoStartPacket(DeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);
-
- //
- // start next request
- //
- IoStartNextPacket(DeviceObject, TRUE);
-}
-
-VOID
-USBSTOR_QueueRelease(
- IN PDEVICE_OBJECT DeviceObject)
-{
- PFDO_DEVICE_EXTENSION FDODeviceExtension;
- PIRP Irp;
- KIRQL OldLevel;
- PIO_STACK_LOCATION IoStack;
- PSCSI_REQUEST_BLOCK Request;
-
- //
- // get FDO device extension
- //
- FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- //
- // sanity check
- //
- ASSERT(FDODeviceExtension->Common.IsFDO);
-
- //
- // acquire lock
- //
- KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
-
- //
- // clear freezed status
- //
- FDODeviceExtension->IrpListFreeze = FALSE;
-
- //
- // release irp list lock
- //
- KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
-
- //
- // grab newest irp
- //
- Irp = USBSTOR_RemoveIrp(DeviceObject);
-
- //
- // is there an irp
- //
- if (!Irp)
- {
- //
- // no irp
- //
- return;
- }
-
- //
- // get current irp stack location
- //
- IoStack = IoGetCurrentIrpStackLocation(Irp);
-
- //
- // get srb
- //
- Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
-
- //
- // start new packet
- //
- IoStartPacket(DeviceObject,
- Irp,
- &Request->QueueSortKey,
- USBSTOR_CancelIo);
-}
-
-
-VOID
-NTAPI
-USBSTOR_StartIo(
- PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
-{
- PIO_STACK_LOCATION IoStack;
- PFDO_DEVICE_EXTENSION FDODeviceExtension;
- PPDO_DEVICE_EXTENSION PDODeviceExtension;
- KIRQL OldLevel;
- BOOLEAN ResetInProgress;
-
- DPRINT("USBSTOR_StartIo\n");
-
- //
- // get FDO device extension
- //
- FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- //
- // sanity check
- //
- ASSERT(FDODeviceExtension->Common.IsFDO);
-
- //
- // acquire cancel spinlock
- //
- IoAcquireCancelSpinLock(&OldLevel);
-
- //
- // set cancel routine to zero
- //
- IoSetCancelRoutine(Irp, NULL);
-
- //
- // check if the irp has been cancelled
- //
- if (Irp->Cancel)
- {
- //
- // irp has been cancelled, release cancel spinlock
- //
- IoReleaseCancelSpinLock(OldLevel);
-
- //
- // irp is cancelled
- //
- Irp->IoStatus.Status = STATUS_CANCELLED;
- Irp->IoStatus.Information = 0;
-
- //
- // terminate request
- //
- USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
-
- //
- // complete request
- //
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- //
- // queue next request
- //
- USBSTOR_QueueNextRequest(DeviceObject);
-
- //
- // done
- //
- return;
- }
-
- //
- // release cancel spinlock
- //
- IoReleaseCancelSpinLock(OldLevel);
-
- //
- // acquire lock
- //
- KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
-
- //
- // check reset is in progress
- //
- ResetInProgress = FDODeviceExtension->ResetInProgress;
- ASSERT(ResetInProgress == FALSE);
-
- //
- // release lock
- //
- KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
-
- //
- // get current irp stack location
- //
- IoStack = IoGetCurrentIrpStackLocation(Irp);
-
- //
- // get pdo device extension
- //
- PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
-
- //
- // sanity check
- //
- ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
-
- //
- // is a reset in progress
- //
- if (ResetInProgress)
- {
- //
- // hard reset is in progress
- //
- Irp->IoStatus.Information = 0;
- Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
- USBSTOR_QueueTerminateRequest(DeviceObject, Irp);
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return;
- }
-
- //
- // execute scsi
- //
- USBSTOR_HandleExecuteSCSI(IoStack->DeviceObject, Irp, 0);
-
- //
- // FIXME: handle error
- //
-}