[USBSTOR]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Sat, 14 May 2011 18:09:00 +0000 (18:09 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Sat, 14 May 2011 18:09:00 +0000 (18:09 +0000)
- Start implementing queued srb handling
- Implement SRB_FUNCTION_RELEASE_QUEUE, SRB_FUNCTION_FLUSH, SRB_FUNCTION_FLUSH_QUEUE
- WIP, not yet working perfectly

svn path=/branches/usb-bringup/; revision=51739

drivers/usb/usbstor/CMakeLists.txt
drivers/usb/usbstor/disk.c
drivers/usb/usbstor/fdo.c
drivers/usb/usbstor/queue.c [new file with mode: 0644]
drivers/usb/usbstor/scsi.c
drivers/usb/usbstor/usbstor.c
drivers/usb/usbstor/usbstor.h

index a6e0395..7eea2d0 100644 (file)
@@ -3,7 +3,7 @@ add_definitions(-DDEBUG_MODE)
 
 include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
 
-add_library(usbstor SHARED descriptor.c disk.c fdo.c misc.c pdo.c scsi.c usbstor.c usbstor.rc)
+add_library(usbstor SHARED descriptor.c disk.c fdo.c misc.c pdo.c queue.c scsi.c usbstor.c usbstor.rc)
 
 set_module_type(usbstor kernelmodedriver)
 add_importlibs(usbstor ntoskrnl hal usbd)
index 099c0e1..96152c3 100644 (file)
 
 #include "usbstor.h"
 
-NTSTATUS
-USBSTOR_HandleExecuteSCSI(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp,
-    IN OUT PSCSI_REQUEST_BLOCK Request,
-    IN PPDO_DEVICE_EXTENSION PDODeviceExtension)
-{
-    PCDB pCDB;
-    NTSTATUS Status;
-
-    //
-    // get SCSI command data block
-    //
-    pCDB = (PCDB)Request->Cdb;
-
-    DPRINT1("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB->AsByte[0]);
-
-
-    if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
-    {
-        //
-        // sanity checks
-        //
-        ASSERT(Request->DataBuffer);
-
-        DPRINT1("SCSIOP_READ_CAPACITY Length %\n", Request->DataTransferLength);
-        Status = USBSTOR_SendCapacityCmd(DeviceObject, Irp);
-    }
-    else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE)
-    {
-        DPRINT1("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request->DataTransferLength);
-        ASSERT(pCDB->MODE_SENSE.AllocationLength == Request->DataTransferLength);
-        ASSERT(Request->DataBuffer);
-
-        //
-        // send mode sense command
-        //
-        Status = USBSTOR_SendModeSenseCmd(DeviceObject, Irp);
-    }
-    else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_READ /*||  pCDB->MODE_SENSE.OperationCode == SCSIOP_WRITE*/)
-    {
-        DPRINT1("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request->DataTransferLength);
-
-        //
-        // send read / write command
-        //
-        Status = USBSTOR_SendReadWriteCmd(DeviceObject, Irp);
-    }
-    else if (pCDB->AsByte[0] == SCSIOP_MEDIUM_REMOVAL)
-    {
-        DPRINT1("SCSIOP_MEDIUM_REMOVAL\n");
-
-        //
-        // just complete the request
-        //
-        Request->SrbStatus = SRB_STATUS_SUCCESS;
-        Irp->IoStatus.Status = STATUS_SUCCESS;
-        Irp->IoStatus.Information = Request->DataTransferLength;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_SUCCESS;
-    }
-    else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_TEST_UNIT_READY)
-    {
-        DPRINT1("SCSIOP_TEST_UNIT_READY\n");
-
-        //
-        // send test unit command
-        //
-        Status = USBSTOR_SendTestUnitCmd(DeviceObject, Irp);
-    }
-    else
-    {
-        UNIMPLEMENTED;
-        Request->SrbStatus = SRB_STATUS_ERROR;
-        Status = STATUS_NOT_SUPPORTED;
-        DbgBreakPoint();
-    }
-
-    return Status;
-}
-
 NTSTATUS
 USBSTOR_HandleInternalDeviceControl(
     IN PDEVICE_OBJECT DeviceObject,
@@ -128,7 +47,58 @@ USBSTOR_HandleInternalDeviceControl(
         case SRB_FUNCTION_EXECUTE_SCSI:
         {
             DPRINT1("SRB_FUNCTION_EXECUTE_SCSI\n");
-            return USBSTOR_HandleExecuteSCSI(DeviceObject, Irp, Request, PDODeviceExtension);
+
+            //
+            // check if request is valid
+            //
+            if (Request->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT))
+            {
+                //
+                // data is transferred with this irp
+                //
+                if (Request->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT) == (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT) ||
+                    Request->DataTransferLength == 0 ||
+                    Irp->MdlAddress == NULL)
+                {
+                    //
+                    // invalid parameter
+                    //
+                    Status = STATUS_INVALID_PARAMETER;
+                    break;
+                }
+            }
+            else
+            {
+                //
+                // sense buffer request
+                //
+                if (Request->DataTransferLength ||
+                    Request->DataBuffer ||
+                    Irp->MdlAddress)
+                {
+                    //
+                    // invalid parameter
+                    //
+                    Status = STATUS_INVALID_PARAMETER;
+                    break;
+                }
+            }
+
+            //
+            // add the request
+            //
+            if (!USBSTOR_QueueAddIrp(DeviceObject, Irp))
+            {
+                //
+                // irp was not added to the queue
+                //
+                IoStartPacket(PDODeviceExtension->LowerDeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);
+            }
+
+            //
+            // irp pending
+            //
+            return STATUS_PENDING;
         }
         case SRB_FUNCTION_RELEASE_DEVICE:
         {
@@ -179,20 +149,37 @@ USBSTOR_HandleInternalDeviceControl(
         }
         case SRB_FUNCTION_RELEASE_QUEUE:
         {
-            DPRINT1("SRB_FUNCTION_RELEASE_QUEUE UNIMPLEMENTED\n");
-            Status = STATUS_NOT_IMPLEMENTED;
+            DPRINT1("SRB_FUNCTION_RELEASE_QUEUE\n");
+
+            //
+            // release queue
+            //
+            USBSTOR_QueueRelease(DeviceObject);
+
+
+            //
+            // set status success
+            //
+            Request->SrbStatus = SRB_STATUS_SUCCESS;
+            Status = STATUS_SUCCESS;
             break;
         }
+
         case SRB_FUNCTION_FLUSH:
+        case SRB_FUNCTION_FLUSH_QUEUE:
         {
-            DPRINT1("SRB_FUNCTION_FLUSH UNIMPLEMENTED\n");
-            Status = STATUS_NOT_IMPLEMENTED;
-            break;
-        }
-        case SRB_FUNCTION_SET_LINK_TIMEOUT:
-        {
-            DPRINT1("SRB_FUNCTION_FLUSH UNIMPLEMENTED\n");
-            Status = STATUS_NOT_IMPLEMENTED;
+            DPRINT1("SRB_FUNCTION_FLUSH / SRB_FUNCTION_FLUSH_QUEUE\n");
+
+            //
+            // flush all requests
+            //
+            USBSTOR_QueueFlushIrps(DeviceObject);
+
+            //
+            // set status success
+            //
+            Request->SrbStatus = SRB_STATUS_SUCCESS;
+            Status = STATUS_SUCCESS;
             break;
         }
         default:
index 017e1ea..8251ec5 100644 (file)
@@ -141,6 +141,11 @@ USBSTOR_FdoHandleStartDevice(
         return Status;
     }
 
+    //
+    // intialize irp queue
+    //
+    USBSTOR_QueueInitialize(DeviceExtension);
+
     //
     // first get device & configuration & string descriptor
     //
diff --git a/drivers/usb/usbstor/queue.c b/drivers/usb/usbstor/queue.c
new file mode 100644 (file)
index 0000000..c726c70
--- /dev/null
@@ -0,0 +1,561 @@
+/*
+ * 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"
+
+VOID
+USBSTOR_QueueInitialize(
+    PFDO_DEVICE_EXTENSION FDODeviceExtension)
+{
+
+    //
+    // initialize queue lock
+    //
+    KeInitializeSpinLock(&FDODeviceExtension->IrpListLock);
+
+    //
+    // initialize irp list head
+    //
+    InitializeListHead(&FDODeviceExtension->IrpListHead);
+}
+
+
+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);
+
+    //
+    // acquire irp list lock
+    //
+    KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock);
+
+    //
+    // now release the cancel lock
+    //
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+    //
+    // remove the irp from the list
+    //
+    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+
+    //
+    // release irp list lock
+    //
+    KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock);
+
+    //
+    // set cancel status
+    //
+    Irp->IoStatus.Status = STATUS_CANCELLED;
+
+    //
+    // now cancel the irp
+    //
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+}
+
+
+BOOLEAN
+USBSTOR_QueueAddIrp(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PDRIVER_CANCEL OldDriverCancel;
+    KIRQL OldLevel;
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
+    PFDO_DEVICE_EXTENSION FDODeviceExtension;
+    BOOLEAN IrpListFreeze;
+
+    //
+    // get pdo device extension
+    //
+    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    //
+    // get FDO device extension
+    //
+    FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
+
+    //
+    // mark irp pending
+    //
+    IoMarkIrpPending(Irp);
+
+    //
+    // acquire lock
+    //
+    KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
+
+    //
+    // add irp to queue
+    //
+    InsertTailList(&FDODeviceExtension->IrpListHead, &Irp->Tail.Overlay.ListEntry);
+
+    //
+    // now set the driver cancel routine
+    //
+    OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_CancelIo);
+
+    //
+    // check if the irp has already been cancelled
+    //
+    if (Irp->Cancel && OldDriverCancel == NULL)
+    {
+        //
+        // the irp has already been cancelled
+        //
+        KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
+
+        //
+        // cancel routine requires that cancel spinlock is held
+        //
+        IoAcquireCancelSpinLock(&Irp->CancelIrql);
+
+        //
+        // cancel irp
+        //
+        USBSTOR_CancelIo(DeviceObject, Irp);
+
+        //
+        // irp was cancelled
+        //
+        return FALSE;
+    }
+
+    //
+    // check if queue is freezed
+    //
+    IrpListFreeze = FDODeviceExtension->IrpListFreeze;
+
+    //
+    // release list lock
+    //
+    KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
+
+    //
+    // if list is freezed, dont start this packet
+    //
+    return IrpListFreeze;
+}
+
+PIRP
+USBSTOR_RemoveIrp(
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    KIRQL OldLevel;
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
+    PFDO_DEVICE_EXTENSION FDODeviceExtension;
+    PLIST_ENTRY Entry;
+    PIRP Irp = NULL;
+
+    //
+    // get pdo device extension
+    //
+    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    //
+    // sanity check
+    //
+    ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+    //
+    // get FDO device extension
+    //
+    FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
+
+    //
+    // 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_QueueFlushIrps(
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    KIRQL OldLevel;
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
+    PFDO_DEVICE_EXTENSION FDODeviceExtension;
+    PLIST_ENTRY Entry;
+    PIRP Irp;
+    PIO_STACK_LOCATION IoStack;
+    PSCSI_REQUEST_BLOCK Request;
+
+    //
+    // get pdo device extension
+    //
+    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    //
+    // sanity check
+    //
+    ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+    //
+    // get FDO device extension
+    //
+    FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
+
+    //
+    // acquire lock
+    //
+    KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
+
+    //
+    // complete all irps with status cancelled
+    // 
+    while(!IsListEmpty(&FDODeviceExtension->IrpListHead))
+    {
+        //
+        // remove irp
+        //
+        Entry = RemoveHeadList(&FDODeviceExtension->IrpListHead);
+
+        //
+        // get start of irp structure
+        //
+        Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
+
+        //
+        // get current stack location
+        //
+        IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+        //
+        // get request block
+        //
+        Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+        //
+        // sanity check
+        //
+        ASSERT(Request);
+
+        //
+        // set srb status to flushed
+        //
+        Request->SrbStatus = SRB_STATUS_REQUEST_FLUSHED;
+
+        //
+        // set unsuccessful status
+        //
+        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+
+        //
+        // complete request
+        //
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
+
+    //
+    // release lock
+    //
+    KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel);
+}
+
+VOID
+USBSTOR_QueueNextRequest(
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
+    PIRP Irp;
+    PIO_STACK_LOCATION IoStack;
+    PSCSI_REQUEST_BLOCK Request;
+
+    //
+    // get pdo device extension
+    //
+    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    //
+    // sanity check
+    //
+    ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+    //
+    // remove first irp from list
+    //
+    Irp = USBSTOR_RemoveIrp(DeviceObject);
+
+    //
+    // is there an irp pending
+    //
+    if (!Irp)
+    {
+        //
+        // no work to do
+        //
+        return;
+    }
+
+    //
+    // get current stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    //
+    // get srb
+    //
+    Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+    //
+    // start next packet
+    //
+    IoStartPacket(PDODeviceExtension->LowerDeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);
+}
+
+VOID
+USBSTOR_QueueRelease(
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
+    PFDO_DEVICE_EXTENSION FDODeviceExtension;
+    PIRP Irp;
+    KIRQL OldLevel;
+    PIO_STACK_LOCATION IoStack;
+    PSCSI_REQUEST_BLOCK Request;
+
+    //
+    // get pdo device extension
+    //
+    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    //
+    // sanity check
+    //
+    ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+    //
+    // get FDO device extension
+    //
+    FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
+
+    //
+    // 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(PDODeviceExtension->LowerDeviceObject, // FDO
+                  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;
+    NTSTATUS Status;
+
+    DPRINT1("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;
+
+        //
+        // complete request
+        //
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        //
+        // check if the queue has been frozen
+        //
+        if (FDODeviceExtension->IrpListFreeze == FALSE)
+        {
+            //
+            // queue next request
+            //
+            USBSTOR_QueueNextRequest(DeviceObject);
+
+            //
+            // start next request
+            //
+            IoStartNextPacket(DeviceObject, TRUE);
+        }
+
+        //
+        // done
+        //
+        return;
+    }
+
+    //
+    // release cancel spinlock
+    //
+    IoReleaseCancelSpinLock(OldLevel);
+
+    //
+    // acquire lock
+    //
+    KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel);
+
+    //
+    // remove irp from list
+    //
+    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+
+    //
+    // 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);
+
+    //
+    // execute scsi
+    //
+    Status = USBSTOR_HandleExecuteSCSI(IoStack->DeviceObject, Irp);
+
+    //
+    // FIXME: synchronize action with error handling
+    //
+    USBSTOR_QueueNextRequest(IoStack->DeviceObject);
+
+    //
+    // start next request
+    //
+    IoStartNextPacket(DeviceObject, TRUE);
+
+}
index cb39572..0e2b926 100644 (file)
@@ -1002,3 +1002,94 @@ USBSTOR_SendTestUnitCmd(
     //
     return USBSTOR_SendRequest(DeviceObject, Irp, NULL, UFI_TEST_UNIT_CMD_LEN, (PUCHAR)&Cmd, 0, NULL);
 }
+
+
+NTSTATUS
+USBSTOR_HandleExecuteSCSI(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PCDB pCDB;
+    NTSTATUS Status;
+    PIO_STACK_LOCATION IoStack;
+    PSCSI_REQUEST_BLOCK Request;
+
+    //
+    // get current stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    //
+    // get request block
+    //
+    Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
+
+    //
+    // get SCSI command data block
+    //
+    pCDB = (PCDB)Request->Cdb;
+
+    DPRINT1("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB->AsByte[0]);
+
+    if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
+    {
+        //
+        // sanity checks
+        //
+        ASSERT(Request->DataBuffer);
+
+        DPRINT1("SCSIOP_READ_CAPACITY Length %\n", Request->DataTransferLength);
+        Status = USBSTOR_SendCapacityCmd(DeviceObject, Irp);
+    }
+    else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE)
+    {
+        DPRINT1("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request->DataTransferLength);
+        ASSERT(pCDB->MODE_SENSE.AllocationLength == Request->DataTransferLength);
+        ASSERT(Request->DataBuffer);
+
+        //
+        // send mode sense command
+        //
+        Status = USBSTOR_SendModeSenseCmd(DeviceObject, Irp);
+    }
+    else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_READ /*||  pCDB->MODE_SENSE.OperationCode == SCSIOP_WRITE*/)
+    {
+        DPRINT1("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request->DataTransferLength);
+
+        //
+        // send read / write command
+        //
+        Status = USBSTOR_SendReadWriteCmd(DeviceObject, Irp);
+    }
+    else if (pCDB->AsByte[0] == SCSIOP_MEDIUM_REMOVAL)
+    {
+        DPRINT1("SCSIOP_MEDIUM_REMOVAL\n");
+
+        //
+        // just complete the request
+        //
+        Request->SrbStatus = SRB_STATUS_SUCCESS;
+        Irp->IoStatus.Status = STATUS_SUCCESS;
+        Irp->IoStatus.Information = Request->DataTransferLength;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return STATUS_SUCCESS;
+    }
+    else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_TEST_UNIT_READY)
+    {
+        DPRINT1("SCSIOP_TEST_UNIT_READY\n");
+
+        //
+        // send test unit command
+        //
+        Status = USBSTOR_SendTestUnitCmd(DeviceObject, Irp);
+    }
+    else
+    {
+        UNIMPLEMENTED;
+        Request->SrbStatus = SRB_STATUS_ERROR;
+        Status = STATUS_NOT_SUPPORTED;
+        DbgBreakPoint();
+    }
+
+    return Status;
+}
index 12b2c0a..dc2d6e7 100644 (file)
@@ -99,18 +99,6 @@ USBSTOR_Unload(
     //
 }
 
-VOID
-NTAPI
-USBSTOR_StartIo(
-    PDEVICE_OBJECT DeviceObject,
-    PIRP Irp)
-{
-    //
-    // implement me
-    //
-    UNIMPLEMENTED
-}
-
 NTSTATUS
 NTAPI
 USBSTOR_DispatchClose(
@@ -251,10 +239,9 @@ DriverEntry(
     DriverObject->DriverExtension->AddDevice = USBSTOR_AddDevice;
 
     //
-    // FIXME: driver start i/o routine
+    // driver start i/o routine
     //
-    //DriverObject->DriverStartIo = USBSTOR_StartIo;
-
+    DriverObject->DriverStartIo = USBSTOR_StartIo;
 
     //
     // create / close
index e837469..a193862 100644 (file)
@@ -63,6 +63,9 @@ typedef struct
     UCHAR BulkOutPipeIndex;                                                              // bulk out pipe index
     UCHAR MaxLUN;                                                                        // max lun for device
     PDEVICE_OBJECT ChildPDO[16];                                                         // max 16 child pdo devices
+    KSPIN_LOCK IrpListLock;                                                              // irp list lock
+    LIST_ENTRY IrpListHead;                                                              // irp list head
+    BOOLEAN IrpListFreeze;                                                               // if true the irp list is freezed
 }FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
 
 typedef struct
@@ -76,6 +79,9 @@ typedef struct
     ULONG LastLogicBlockAddress;                                                         // last block address
 }PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
 
+
+
+
 //
 // max lun command identifier
 //
@@ -361,41 +367,53 @@ USBSTOR_GetPipeHandles(
 // scsi.c routines
 //
 NTSTATUS
-USBSTOR_SendInquiryCmd(
-    IN PDEVICE_OBJECT DeviceObject);
-
-NTSTATUS
-USBSTOR_SendCapacityCmd(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp);
-
-NTSTATUS
-USBSTOR_SendModeSenseCmd(
+USBSTOR_HandleExecuteSCSI(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp);
 
+//---------------------------------------------------------------------
+//
+// disk.c routines
+//
 NTSTATUS
-USBSTOR_SendReadWriteCmd(
+USBSTOR_HandleInternalDeviceControl(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp);
 
 NTSTATUS
-USBSTOR_SendTestUnitCmd(
+USBSTOR_HandleDeviceControl(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp);
 
 //---------------------------------------------------------------------
 //
-// disk.c routines
+// queue.c routines
 //
-NTSTATUS
-USBSTOR_HandleInternalDeviceControl(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp);
+VOID
+NTAPI
+USBSTOR_StartIo(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp);
 
-NTSTATUS
-USBSTOR_HandleDeviceControl(
+VOID
+USBSTOR_QueueFlushIrps(
+    IN PDEVICE_OBJECT DeviceObject);
+
+VOID
+USBSTOR_QueueRelease(
+    IN PDEVICE_OBJECT DeviceObject);
+
+BOOLEAN
+USBSTOR_QueueAddIrp(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp);
 
+VOID
+NTAPI
+USBSTOR_CancelIo(
+    IN  PDEVICE_OBJECT DeviceObject,
+    IN  PIRP Irp);
 
+VOID
+USBSTOR_QueueInitialize(
+    PFDO_DEVICE_EXTENSION FDODeviceExtension);