https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f3fd12b9be4143f27f6ce…
commit f3fd12b9be4143f27f6ce5cbb5f9943b1dedfe20
Author:     Victor Perevertkin <victor(a)perevertkin.ru>
AuthorDate: Sun Mar 31 16:52:04 2019 +0300
Commit:     Victor Perevertkin <victor(a)perevertkin.ru>
CommitDate: Tue Jun 11 04:39:43 2019 +0300
    [USBSTOR] Rework the routines for sending internal SCSI requests.
    Now for each request SenseBuffer is correctly set
    and 3 attempts are made to be sure the STALL state is cleared and
    the error is in something else.
    Remove the usage of UFI_INQUIRY_DATA structure in favor of "standard"
    INQUIRYDATA structure from scsi.h
    Based in Vadim Galyant's patches to usbstor
---
 drivers/usb/usbstor/disk.c    |  71 +++-----
 drivers/usb/usbstor/misc.c    |   2 +
 drivers/usb/usbstor/pdo.c     | 392 +++++++++++++++++++++---------------------
 drivers/usb/usbstor/usbstor.h |  38 +---
 4 files changed, 230 insertions(+), 273 deletions(-)
diff --git a/drivers/usb/usbstor/disk.c b/drivers/usb/usbstor/disk.c
index cf9c0380136..984296214cf 100644
--- a/drivers/usb/usbstor/disk.c
+++ b/drivers/usb/usbstor/disk.c
@@ -174,7 +174,7 @@ USBSTOR_HandleQueryProperty(
     PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor;
     ULONG FieldLengthVendor, FieldLengthProduct, FieldLengthRevision, TotalLength,
FieldLengthSerialNumber;
     PPDO_DEVICE_EXTENSION PDODeviceExtension;
-    PUFI_INQUIRY_RESPONSE InquiryData;
+    PINQUIRYDATA InquiryData;
     PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor;
     PUCHAR Buffer;
     PFDO_DEVICE_EXTENSION FDODeviceExtension;
@@ -224,13 +224,13 @@ USBSTOR_HandleQueryProperty(
         ASSERT(FDODeviceExtension);
         ASSERT(FDODeviceExtension->Common.IsFDO);
-        InquiryData = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
+        InquiryData = PDODeviceExtension->InquiryData;
         ASSERT(InquiryData);
         // compute extra parameters length
-        FieldLengthVendor = USBSTOR_GetFieldLength(InquiryData->Vendor, 8);
-        FieldLengthProduct = USBSTOR_GetFieldLength(InquiryData->Product, 16);
-        FieldLengthRevision = USBSTOR_GetFieldLength(InquiryData->Revision, 4);
+        FieldLengthVendor = USBSTOR_GetFieldLength(InquiryData->VendorId, 8);
+        FieldLengthProduct = USBSTOR_GetFieldLength(InquiryData->ProductId, 16);
+        FieldLengthRevision =
USBSTOR_GetFieldLength(InquiryData->ProductRevisionLevel, 4);
         if (FDODeviceExtension->SerialNumber)
         {
@@ -263,11 +263,11 @@ USBSTOR_HandleQueryProperty(
         // initialize the device descriptor
         DeviceDescriptor =
(PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
-        DeviceDescriptor->Version = TotalLength;
+        DeviceDescriptor->Version = sizeof(STORAGE_DEVICE_DESCRIPTOR);
         DeviceDescriptor->Size = TotalLength;
         DeviceDescriptor->DeviceType = InquiryData->DeviceType;
-        DeviceDescriptor->DeviceTypeModifier = (InquiryData->RMB & 0x7F);
-        DeviceDescriptor->RemovableMedia = (InquiryData->RMB & 0x80) ? TRUE :
FALSE;
+        DeviceDescriptor->DeviceTypeModifier = InquiryData->DeviceTypeModifier;
+        DeviceDescriptor->RemovableMedia = InquiryData->RemovableMedia;
         DeviceDescriptor->CommandQueueing = FALSE;
         DeviceDescriptor->BusType = BusTypeUsb;
         DeviceDescriptor->VendorIdOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) -
sizeof(UCHAR);
@@ -279,15 +279,15 @@ USBSTOR_HandleQueryProperty(
         // copy descriptors
         Buffer = (PUCHAR)((ULONG_PTR)DeviceDescriptor + sizeof(STORAGE_DEVICE_DESCRIPTOR)
- sizeof(UCHAR));
-        RtlCopyMemory(Buffer, InquiryData->Vendor, FieldLengthVendor);
+        RtlCopyMemory(Buffer, InquiryData->VendorId, FieldLengthVendor);
         Buffer[FieldLengthVendor] = '\0';
         Buffer += FieldLengthVendor + 1;
-        RtlCopyMemory(Buffer, InquiryData->Product, FieldLengthProduct);
+        RtlCopyMemory(Buffer, InquiryData->ProductId, FieldLengthProduct);
         Buffer[FieldLengthProduct] = '\0';
         Buffer += FieldLengthProduct + 1;
-        RtlCopyMemory(Buffer, InquiryData->Revision, FieldLengthRevision);
+        RtlCopyMemory(Buffer, InquiryData->ProductRevisionLevel, FieldLengthRevision);
         Buffer[FieldLengthRevision] = '\0';
         Buffer += FieldLengthRevision + 1;
@@ -364,9 +364,8 @@ USBSTOR_HandleDeviceControl(
     NTSTATUS Status;
     PPDO_DEVICE_EXTENSION PDODeviceExtension;
     PSCSI_ADAPTER_BUS_INFO BusInfo;
-    PSCSI_INQUIRY_DATA InquiryData;
-    PINQUIRYDATA ScsiInquiryData;
-    PUFI_INQUIRY_RESPONSE UFIInquiryResponse;
+    PSCSI_INQUIRY_DATA ScsiInquiryData;
+    PINQUIRYDATA InquiryData;
     IoStack = IoGetCurrentIrpStackLocation(Irp);
@@ -431,11 +430,8 @@ USBSTOR_HandleDeviceControl(
             // get parameters
             BusInfo = Irp->AssociatedIrp.SystemBuffer;
-            InquiryData = (PSCSI_INQUIRY_DATA)(BusInfo + 1);
-            ScsiInquiryData = (PINQUIRYDATA)InquiryData->InquiryData;
-
-            UFIInquiryResponse =
(PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
-            ASSERT(UFIInquiryResponse);
+            ScsiInquiryData = (PSCSI_INQUIRY_DATA)(BusInfo + 1);
+            InquiryData = (PINQUIRYDATA)ScsiInquiryData->InquiryData;
             BusInfo->NumberOfBuses = 1;
@@ -443,30 +439,19 @@ USBSTOR_HandleDeviceControl(
             BusInfo->BusData[0].InitiatorBusId = 0;
             BusInfo->BusData[0].InquiryDataOffset = sizeof(SCSI_ADAPTER_BUS_INFO);
-            InquiryData->PathId = 0;
-            InquiryData->TargetId = 0;
-            InquiryData->Lun = PDODeviceExtension->LUN & MAX_LUN;
-            InquiryData->DeviceClaimed = PDODeviceExtension->Claimed;
-            InquiryData->InquiryDataLength = sizeof(INQUIRYDATA);
-            InquiryData->NextInquiryDataOffset = 0;
-
-            RtlZeroMemory(ScsiInquiryData, sizeof(INQUIRYDATA));
-            ScsiInquiryData->DeviceType = UFIInquiryResponse->DeviceType;
-            ScsiInquiryData->DeviceTypeQualifier = (UFIInquiryResponse->RMB &
0x7F);
-
-            // Hack for IoReadPartitionTable call in disk.sys
-            ScsiInquiryData->RemovableMedia = ((ScsiInquiryData->DeviceType ==
DIRECT_ACCESS_DEVICE) ? ((UFIInquiryResponse->RMB & 0x80) ? 1 : 0) : 0);
-
-            ScsiInquiryData->Versions = 0x04;
-            ScsiInquiryData->ResponseDataFormat = 0x02;
-            ScsiInquiryData->AdditionalLength = 31;
-            ScsiInquiryData->SoftReset = 0;
-            ScsiInquiryData->CommandQueue = 0;
-            ScsiInquiryData->LinkedCommands = 0;
-            ScsiInquiryData->RelativeAddressing = 0;
-
-            RtlCopyMemory(&ScsiInquiryData->VendorId,
UFIInquiryResponse->Vendor, USBSTOR_GetFieldLength(UFIInquiryResponse->Vendor, 8));
-            RtlCopyMemory(&ScsiInquiryData->ProductId,
UFIInquiryResponse->Product, USBSTOR_GetFieldLength(UFIInquiryResponse->Product,
16));
+            ScsiInquiryData->PathId = 0;
+            ScsiInquiryData->TargetId = 0;
+            ScsiInquiryData->Lun = PDODeviceExtension->LUN & MAX_LUN;
+            ScsiInquiryData->DeviceClaimed = PDODeviceExtension->Claimed;
+            ScsiInquiryData->InquiryDataLength = sizeof(INQUIRYDATA);
+            ScsiInquiryData->NextInquiryDataOffset = 0;
+
+            // Note: INQUIRYDATA structure is larger than INQUIRYDATABUFFERSIZE
+            RtlZeroMemory(InquiryData, sizeof(INQUIRYDATA));
+            RtlCopyMemory(InquiryData, PDODeviceExtension->InquiryData,
INQUIRYDATABUFFERSIZE);
+
+            InquiryData->Versions = 0x04;
+            InquiryData->ResponseDataFormat = 0x02; // some devices set this to 1
             Irp->IoStatus.Information = sizeof(SCSI_ADAPTER_BUS_INFO) +
sizeof(SCSI_INQUIRY_DATA) + sizeof(INQUIRYDATA) - 1;
             Status = STATUS_SUCCESS;
diff --git a/drivers/usb/usbstor/misc.c b/drivers/usb/usbstor/misc.c
index 671336df88c..3dbbf160813 100644
--- a/drivers/usb/usbstor/misc.c
+++ b/drivers/usb/usbstor/misc.c
@@ -258,6 +258,7 @@ USBSTOR_ResetDevice(
     return Status;
 }
+#if 0
 BOOLEAN
 USBSTOR_IsFloppy(
     IN PUCHAR Buffer,
@@ -319,3 +320,4 @@ USBSTOR_IsFloppy(
     return FALSE;
 }
+#endif
diff --git a/drivers/usb/usbstor/pdo.c b/drivers/usb/usbstor/pdo.c
index 98c01d1cb7b..93caca4e1ef 100644
--- a/drivers/usb/usbstor/pdo.c
+++ b/drivers/usb/usbstor/pdo.c
@@ -5,6 +5,8 @@
  * COPYRIGHT:   2005-2006 James Tabor
  *              2011-2012 Michael Martin (michael.martin(a)reactos.org)
  *              2011-2013 Johannes Anderwald (johannes.anderwald(a)reactos.org)
+ *              2017 Vadim Galyant
+ *              2019 Victor Perevertkin (victor.perevertkin(a)reactos.org)
  */
 #include "usbstor.h"
@@ -15,7 +17,7 @@
 LPCSTR
 USBSTOR_GetDeviceType(
-    IN PUFI_INQUIRY_RESPONSE InquiryData,
+    IN PINQUIRYDATA InquiryData,
     IN UCHAR IsFloppy)
 {
     if (InquiryData->DeviceType == 0)
@@ -67,7 +69,7 @@ USBSTOR_GetDeviceType(
 LPCSTR
 USBSTOR_GetGenericType(
-    IN PUFI_INQUIRY_RESPONSE InquiryData,
+    IN PINQUIRYDATA InquiryData,
     IN UCHAR IsFloppy)
 {
     if (InquiryData->DeviceType == 0)
@@ -198,13 +200,13 @@ USBSTOR_PdoHandleQueryDeviceId(
     CHAR Buffer[100] = {0};
     LPCSTR DeviceType;
     ULONG Offset = 0;
-    PUFI_INQUIRY_RESPONSE InquiryData;
+    PINQUIRYDATA InquiryData;
     ANSI_STRING AnsiString;
     UNICODE_STRING DeviceId;
     DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
     ASSERT(DeviceExtension->InquiryData);
-    InquiryData = (PUFI_INQUIRY_RESPONSE)DeviceExtension->InquiryData;
+    InquiryData = DeviceExtension->InquiryData;
     DeviceType = USBSTOR_GetDeviceType(InquiryData, DeviceExtension->IsFloppy);
@@ -212,17 +214,17 @@ USBSTOR_PdoHandleQueryDeviceId(
     Offset = sprintf(&Buffer[Offset], "USBSTOR\\");
     Offset += sprintf(&Buffer[Offset], DeviceType);
     Offset += sprintf(&Buffer[Offset], "&Ven_");
-    Offset += CopyField(InquiryData->Vendor, &Buffer[Offset], 8);
+    Offset += CopyField(InquiryData->VendorId, &Buffer[Offset], 8);
     Offset += sprintf(&Buffer[Offset], "&Prod_");
-    Offset += CopyField(InquiryData->Product, &Buffer[Offset], 16);
+    Offset += CopyField(InquiryData->ProductId, &Buffer[Offset], 16);
     Offset += sprintf(&Buffer[Offset], "&Rev_");
-    Offset += CopyField(InquiryData->Revision, &Buffer[Offset], 4);
+    Offset += CopyField(InquiryData->ProductRevisionLevel, &Buffer[Offset], 4);
     RtlInitAnsiString(&AnsiString, (PCSZ)Buffer);
     // allocate DeviceId string
     DeviceId.Length = 0;
-    DeviceId.MaximumLength = (strlen((PCHAR)Buffer) + 1) * sizeof(WCHAR);
+    DeviceId.MaximumLength = (USHORT)((strlen((PCHAR)Buffer) + 1) * sizeof(WCHAR));
     DeviceId.Buffer = (LPWSTR)AllocateItem(PagedPool, DeviceId.MaximumLength);
     if (!DeviceId.Buffer)
     {
@@ -289,12 +291,12 @@ USBSTOR_PdoHandleQueryHardwareId(
     CHAR Id1[50], Id2[50], Id3[50], Id4[50], Id5[50], Id6[50];
     ULONG Id1Length, Id2Length, Id3Length, Id4Length, Id5Length,Id6Length;
     ULONG Offset, TotalLength, Length;
-    PUFI_INQUIRY_RESPONSE InquiryData;
+    PINQUIRYDATA InquiryData;
     PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
     FDODeviceExtension =
(PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
     ASSERT(FDODeviceExtension->DeviceDescriptor);
-    InquiryData = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
+    InquiryData = PDODeviceExtension->InquiryData;
     DeviceType = USBSTOR_GetDeviceType(InquiryData, PDODeviceExtension->IsFloppy);
     GenericType = USBSTOR_GetGenericType(InquiryData, PDODeviceExtension->IsFloppy);
@@ -302,47 +304,47 @@ USBSTOR_PdoHandleQueryHardwareId(
     ASSERT(GenericType);
     // generate id 1
-    // USBSTOR\SCSIType_Vendor(8)_Product(16)_Revision(4)
+    // USBSTOR\SCSIType_VendorId(8)_ProductId(16)_Revision(4)
     RtlZeroMemory(Id1, sizeof(Id1));
     Offset = 0;
     Offset = sprintf(&Id1[Offset], "USBSTOR\\");
     Offset += sprintf(&Id1[Offset], DeviceType);
-    Offset += CopyField(InquiryData->Vendor, &Id1[Offset], 8);
-    Offset += CopyField(InquiryData->Product, &Id1[Offset], 16);
-    Offset += CopyField(InquiryData->Revision, &Id1[Offset], 4);
+    Offset += CopyField(InquiryData->VendorId, &Id1[Offset], 8);
+    Offset += CopyField(InquiryData->ProductId, &Id1[Offset], 16);
+    Offset += CopyField(InquiryData->ProductRevisionLevel, &Id1[Offset], 4);
     Id1Length = strlen(Id1) + 1;
     DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId1 %s\n", Id1);
     // generate id 2
-    // USBSTOR\SCSIType_VENDOR(8)_Product(16)
+    // USBSTOR\SCSIType_VendorId(8)_ProductId(16)
     RtlZeroMemory(Id2, sizeof(Id2));
     Offset = 0;
     Offset = sprintf(&Id2[Offset], "USBSTOR\\");
     Offset += sprintf(&Id2[Offset], DeviceType);
-    Offset += CopyField(InquiryData->Vendor, &Id2[Offset], 8);
-    Offset += CopyField(InquiryData->Product, &Id2[Offset], 16);
+    Offset += CopyField(InquiryData->VendorId, &Id2[Offset], 8);
+    Offset += CopyField(InquiryData->ProductId, &Id2[Offset], 16);
     Id2Length = strlen(Id2) + 1;
     DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId2 %s\n", Id2);
     // generate id 3
-    // USBSTOR\SCSIType_VENDOR(8)
+    // USBSTOR\SCSIType_VendorId(8)
     RtlZeroMemory(Id3, sizeof(Id3));
     Offset = 0;
     Offset = sprintf(&Id3[Offset], "USBSTOR\\");
     Offset += sprintf(&Id3[Offset], DeviceType);
-    Offset += CopyField(InquiryData->Vendor, &Id3[Offset], 8);
+    Offset += CopyField(InquiryData->VendorId, &Id3[Offset], 8);
     Id3Length = strlen(Id3) + 1;
     DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId3 %s\n", Id3);
     // generate id 4
-    // USBSTOR\SCSIType_VENDOR(8)_Product(16)_Revision(1)
+    // USBSTOR\SCSIType_VendorId(8)_ProductId(16)_Revision(1)
     RtlZeroMemory(Id4, sizeof(Id4));
     Offset = 0;
     Offset = sprintf(&Id4[Offset], "USBSTOR\\");
     Offset += sprintf(&Id4[Offset], DeviceType);
-    Offset += CopyField(InquiryData->Vendor, &Id4[Offset], 8);
-    Offset += CopyField(InquiryData->Product, &Id4[Offset], 16);
-    Offset += CopyField(InquiryData->Revision, &Id4[Offset], 1);
+    Offset += CopyField(InquiryData->VendorId, &Id4[Offset], 8);
+    Offset += CopyField(InquiryData->ProductId, &Id4[Offset], 16);
+    Offset += CopyField(InquiryData->ProductRevisionLevel, &Id4[Offset], 1);
     Id4Length = strlen(Id4) + 1;
     DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId4 %s\n", Id4);
@@ -404,7 +406,7 @@ USBSTOR_PdoHandleQueryCompatibleId(
     PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
     FDODeviceExtension =
(PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
     ASSERT(FDODeviceExtension->DeviceDescriptor);
-    DeviceType =
USBSTOR_GetDeviceType((PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData,
PDODeviceExtension->IsFloppy);
+    DeviceType = USBSTOR_GetDeviceType(PDODeviceExtension->InquiryData,
PDODeviceExtension->IsFloppy);
     // format instance id
     Length = sprintf(Buffer, "USBSTOR\\%s", DeviceType) + 1;
@@ -645,201 +647,204 @@ USBSTOR_PdoHandlePnp(
 NTSTATUS
 NTAPI
-USBSTOR_CompletionRoutine(
+USBSTOR_SyncCompletionRoutine(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp,
     IN PVOID Ctx)
 {
-    PKEVENT Event = (PKEVENT)Ctx;
-
-    KeSetEvent(Event, 0, FALSE);
+    KeSetEvent((PKEVENT)Ctx, IO_NO_INCREMENT, FALSE);
     return STATUS_MORE_PROCESSING_REQUIRED;
 }
+/*
+* @name USBSTOR_SendInternalCdb
+*
+* Issues an internal SCSI request to device.
+* The request is sent in a synchronous way.
+*/
+static
 NTSTATUS
-USBSTOR_AllocateIrp(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN ULONG DataTransferLength,
-    IN UCHAR OpCode,
-    IN PKEVENT Event,
-    OUT PSCSI_REQUEST_BLOCK *OutRequest,
-    OUT PIRP *OutIrp)
+USBSTOR_SendInternalCdb(
+    IN PDEVICE_OBJECT PdoDevice,
+    IN PCDB Cdb,
+    IN UCHAR CdbLength,
+    IN ULONG TimeOutValue,
+    OUT PVOID OutDataBuffer,
+    OUT PULONG OutDataTransferLength)
 {
-    PIRP Irp;
+    PSCSI_REQUEST_BLOCK Srb;
+    PSENSE_DATA SenseBuffer;
     PIO_STACK_LOCATION IoStack;
-    PSCSI_REQUEST_BLOCK Request;
-    PCDB pCDB;
-
-    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
-    if (!Irp)
-    {
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    IoStack = IoGetNextIrpStackLocation(Irp);
-
-    Request = ExAllocatePoolWithTag(NonPagedPool,
-                                    sizeof(SCSI_REQUEST_BLOCK),
-                                    USB_STOR_TAG);
-    if (!Request)
-    {
-        IoFreeIrp(Irp);
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    RtlZeroMemory(Request, sizeof(SCSI_REQUEST_BLOCK));
-
-    // allocate data transfer block
-    Request->DataBuffer = ExAllocatePoolWithTag(NonPagedPool,
-                                                DataTransferLength,
-                                                USB_STOR_TAG);
-    if (!Request->DataBuffer)
-    {
-        IoFreeIrp(Irp);
-        ExFreePoolWithTag(Request, USB_STOR_TAG);
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    Irp->MdlAddress = IoAllocateMdl(Request->DataBuffer, DataTransferLength, FALSE,
FALSE, NULL);
-    if (!Irp->MdlAddress)
-    {
-        IoFreeIrp(Irp);
-        ExFreePoolWithTag(Request->DataBuffer, USB_STOR_TAG);
-        ExFreePoolWithTag(Request, USB_STOR_TAG);
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    MmBuildMdlForNonPagedPool(Irp->MdlAddress);
-
-    Request->DataTransferLength = DataTransferLength;
-    Request->Function = SRB_FUNCTION_EXECUTE_SCSI;
-    Request->SrbFlags = SRB_FLAGS_DATA_IN;
-
-    RtlZeroMemory(Request->DataBuffer, DataTransferLength);
-
-    // get SCSI command data block
-    pCDB = (PCDB)Request->Cdb;
-
-    // set op code
-    pCDB->AsByte[0] = OpCode;
-
-    // store result
-    IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
-    IoStack->Parameters.Others.Argument1 = Request;
-    IoStack->DeviceObject = DeviceObject;
-
-    KeInitializeEvent(Event, NotificationEvent, FALSE);
-
-    IoSetCompletionRoutine(Irp, USBSTOR_CompletionRoutine, (PVOID)Event, TRUE, TRUE,
TRUE);
-
-    *OutIrp = Irp;
-    *OutRequest = Request;
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-USBSTOR_SendIrp(
-    IN PDEVICE_OBJECT PDODeviceObject,
-    IN ULONG DataTransferLength,
-    IN UCHAR OpCode,
-    OUT PVOID *OutData)
-{
-    NTSTATUS Status;
-    PIRP Irp;
     KEVENT Event;
-    PPDO_DEVICE_EXTENSION PDODeviceExtension;
-    PSCSI_REQUEST_BLOCK Request;
+    PIRP Irp = NULL;
+    PMDL Mdl = NULL;
+    ULONG ix = 0;
+    NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
+    UCHAR SrbStatus;
-    Status = USBSTOR_AllocateIrp(PDODeviceObject, DataTransferLength, OpCode, &Event,
&Request, &Irp);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("[USBSTOR] Failed to build irp\n");
-        return Status;
-    }
-
-    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
+    DPRINT("USBSTOR_SendInternalCdb SCSIOP %x\n",
Cdb->CDB6GENERIC.OperationCode);
-    ASSERT(Irp);
-    ASSERT(PDODeviceExtension->LowerDeviceObject);
-    Status = IoCallDriver(PDODeviceExtension->Self, Irp);
+    Srb = ExAllocatePoolWithTag(NonPagedPool,
+                                sizeof(SCSI_REQUEST_BLOCK),
+                                USB_STOR_TAG);
-    if (Status == STATUS_PENDING)
+    if (Srb)
     {
-        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-        Status = Irp->IoStatus.Status;
-    }
+        SenseBuffer = ExAllocatePoolWithTag(NonPagedPool,
+                                            SENSE_BUFFER_SIZE,
+                                            USB_STOR_TAG);
-    if (NT_SUCCESS(Status))
-    {
-        *OutData = Request->DataBuffer;
-    }
-    else
-    {
-        ExFreePoolWithTag(Request->DataBuffer, USB_STOR_TAG);
-        *OutData = NULL;
+        if (SenseBuffer)
+        {
+            Mdl = IoAllocateMdl(OutDataBuffer,
+                    *OutDataTransferLength,
+                    FALSE,
+                    FALSE,
+                    NULL);
+
+            if (!Mdl)
+            {
+                ExFreePoolWithTag(SenseBuffer, USB_STOR_TAG);
+                ExFreePoolWithTag(Srb, USB_STOR_TAG);
+                return Status;
+            }
+
+            MmBuildMdlForNonPagedPool(Mdl);
+
+            // make 3 attempts - the device may be in STALL state after the first one
+            do
+            {
+                Irp = IoAllocateIrp(PdoDevice->StackSize, FALSE);
+
+                if (!Irp)
+                {
+                    break;
+                }
+
+                IoStack = IoGetNextIrpStackLocation(Irp);
+                IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+                IoStack->Parameters.Scsi.Srb = Srb;
+
+                RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
+
+                Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
+                Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+                Srb->CdbLength = CdbLength;
+                Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
+                Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE;
+                Srb->DataTransferLength = *OutDataTransferLength;
+                Srb->TimeOutValue = TimeOutValue;
+                Srb->DataBuffer = OutDataBuffer;
+                Srb->SenseInfoBuffer = SenseBuffer;
+
+                RtlCopyMemory(Srb->Cdb, Cdb, CdbLength);
+
+                Irp->MdlAddress = Mdl;
+
+                KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+
+                IoSetCompletionRoutine(Irp,
+                                       USBSTOR_SyncCompletionRoutine,
+                                       &Event,
+                                       TRUE,
+                                       TRUE,
+                                       TRUE);
+
+                if (IoCallDriver(PdoDevice, Irp) == STATUS_PENDING)
+                {
+                    KeWaitForSingleObject(&Event,
+                                          Executive,
+                                          KernelMode,
+                                          FALSE,
+                                          NULL);
+                }
+
+                SrbStatus = SRB_STATUS(Srb->SrbStatus);
+
+                IoFreeIrp(Irp);
+                Irp = NULL;
+
+                if (SrbStatus == SRB_STATUS_SUCCESS ||
+                     SrbStatus == SRB_STATUS_DATA_OVERRUN)
+                {
+                    Status = STATUS_SUCCESS;
+                    *OutDataTransferLength = Srb->DataTransferLength;
+                    break;
+                }
+
+                Status = STATUS_UNSUCCESSFUL;
+
+                ++ix;
+            } while (ix < 3);
+
+            if (Mdl)
+            {
+                IoFreeMdl(Mdl);
+            }
+
+            ExFreePoolWithTag(SenseBuffer, USB_STOR_TAG);
+        }
+
+        ExFreePoolWithTag(Srb, USB_STOR_TAG);
     }
-    ExFreePoolWithTag(Request, USB_STOR_TAG);
-    IoFreeMdl(Irp->MdlAddress);
-    IoFreeIrp(Irp);
     return Status;
 }
+/*
+* @name USBSTOR_FillInquiryData
+*
+* Sends a SCSI Inquiry request and fills in the PDODeviceExtension->InquiryData field
with a result.
+*/
+static
 NTSTATUS
-USBSTOR_SendInquiryIrp(
+USBSTOR_FillInquiryData(
     IN PDEVICE_OBJECT PDODeviceObject)
 {
-    NTSTATUS Status;
+    NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
     PPDO_DEVICE_EXTENSION PDODeviceExtension;
-    PUFI_INQUIRY_RESPONSE Response;
+    CDB Cdb;
+    ULONG DataTransferLength = INQUIRYDATABUFFERSIZE;
+    PINQUIRYDATA InquiryData;
     PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
+    InquiryData = ExAllocatePoolWithTag(NonPagedPool, INQUIRYDATABUFFERSIZE,
USB_STOR_TAG);
-    Status = USBSTOR_SendIrp(PDODeviceObject, sizeof(UFI_INQUIRY_RESPONSE),
SCSIOP_INQUIRY, (PVOID*)&Response);
-    if (!NT_SUCCESS(Status))
+    if (!InquiryData)
     {
-        DPRINT1("USBSTOR_SendInquiryIrp Failed with %x\n", Status);
+        DPRINT1("USBSTOR_FillInquiryData failed with %x\n", Status);
         return Status;
     }
-    DPRINT1("Response %p\n", Response);
-    DPRINT1("DeviceType %x\n", Response->DeviceType);
-    DPRINT1("RMB %x\n", Response->RMB);
-    DPRINT1("Version %x\n", Response->Version);
-    DPRINT1("Format %x\n", Response->Format);
-    DPRINT1("Length %x\n", Response->Length);
-    DPRINT1("Reserved %p\n", Response->Reserved);
-    DPRINT1("Vendor %c%c%c%c%c%c%c%c\n", Response->Vendor[0],
Response->Vendor[1], Response->Vendor[2], Response->Vendor[3],
Response->Vendor[4], Response->Vendor[5], Response->Vendor[6],
Response->Vendor[7]);
-    DPRINT1("Product %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
Response->Product[0], Response->Product[1], Response->Product[2],
Response->Product[3],
-                                                          Response->Product[4],
Response->Product[5], Response->Product[6], Response->Product[7],
-                                                          Response->Product[8],
Response->Product[9], Response->Product[10], Response->Product[11],
-                                                          Response->Product[12],
Response->Product[13], Response->Product[14], Response->Product[15]);
-
-    DPRINT1("Revision %c%c%c%c\n", Response->Revision[0],
Response->Revision[1], Response->Revision[2], Response->Revision[3]);
-
-    PDODeviceExtension->InquiryData = (PVOID)Response;
-    return Status;
-}
+    RtlZeroMemory(&Cdb, sizeof(Cdb));
+    Cdb.CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
+    Cdb.CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
-NTSTATUS
-USBSTOR_SendFormatCapacityIrp(
-    IN PDEVICE_OBJECT PDODeviceObject)
-{
-    NTSTATUS Status;
-    PPDO_DEVICE_EXTENSION PDODeviceExtension;
-    PUCHAR Response;
-
-    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
+    Status = USBSTOR_SendInternalCdb(PDODeviceObject, &Cdb, CDB6GENERIC_LENGTH, 20,
InquiryData, &DataTransferLength);
-    Status = USBSTOR_SendIrp(PDODeviceObject, 0xFC, SCSIOP_READ_FORMATTED_CAPACITY,
(PVOID*)&Response);
     if (!NT_SUCCESS(Status))
     {
+        DPRINT1("USBSTOR_FillInquiryData failed with %x\n", Status);
+        ExFreePoolWithTag(InquiryData, USB_STOR_TAG);
         return Status;
     }
-    PDODeviceExtension->IsFloppy = USBSTOR_IsFloppy(Response, 0xFC /*FIXME*/,
&PDODeviceExtension->MediumTypeCode);
-
-    ExFreePoolWithTag(Response, USB_STOR_TAG);
+    DPRINT("DeviceType %x\n", InquiryData->DeviceType);
+    DPRINT("DeviceTypeModifier %x\n", InquiryData->DeviceTypeModifier);
+    DPRINT("RemovableMedia %x\n", InquiryData->RemovableMedia);
+    DPRINT("Version %x\n", InquiryData->Versions);
+    DPRINT("Format %x\n", InquiryData->ResponseDataFormat);
+    DPRINT("Length %x\n", InquiryData->AdditionalLength);
+    DPRINT("Reserved %p\n", InquiryData->Reserved);
+    DPRINT("VendorId %c%c%c%c%c%c%c%c\n", InquiryData->VendorId[0],
InquiryData->VendorId[1], InquiryData->VendorId[2], InquiryData->VendorId[3],
InquiryData->VendorId[4], InquiryData->VendorId[5], InquiryData->VendorId[6],
InquiryData->VendorId[7]);
+    DPRINT("ProductId %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
InquiryData->ProductId[0], InquiryData->ProductId[1], InquiryData->ProductId[2],
InquiryData->ProductId[3],
+                                                           InquiryData->ProductId[4],
InquiryData->ProductId[5], InquiryData->ProductId[6], InquiryData->ProductId[7],
+                                                           InquiryData->ProductId[8],
InquiryData->ProductId[9], InquiryData->ProductId[10],
InquiryData->ProductId[11],
+                                                           InquiryData->ProductId[12],
InquiryData->ProductId[13], InquiryData->ProductId[14],
InquiryData->ProductId[15]);
+
+    DPRINT("Revision %c%c%c%c\n", InquiryData->ProductRevisionLevel[0],
InquiryData->ProductRevisionLevel[1], InquiryData->ProductRevisionLevel[2],
InquiryData->ProductRevisionLevel[3]);
+
+    PDODeviceExtension->InquiryData = InquiryData;
     return Status;
 }
@@ -851,7 +856,6 @@ USBSTOR_CreatePDO(
     PDEVICE_OBJECT PDO;
     NTSTATUS Status;
     PPDO_DEVICE_EXTENSION PDODeviceExtension;
-    PUFI_INQUIRY_RESPONSE Response;
     PFDO_DEVICE_EXTENSION FDODeviceExtension;
     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
@@ -860,6 +864,7 @@ USBSTOR_CreatePDO(
     Status = IoCreateDevice(DeviceObject->DriverObject, sizeof(PDO_DEVICE_EXTENSION),
NULL, FILE_DEVICE_MASS_STORAGE, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
FALSE, &PDO);
     if (!NT_SUCCESS(Status))
     {
+        DPRINT1("Failed to create PDO, status %x\n", Status);
         return Status;
     }
@@ -876,7 +881,7 @@ USBSTOR_CreatePDO(
     PDODeviceExtension->Self = PDO;
     PDODeviceExtension->LUN = LUN;
-    PDO->Flags |= DO_DIRECT_IO | DO_MAP_IO_BUFFER;
+    PDO->Flags |= DO_DIRECT_IO;
     // device is initialized
     PDO->Flags &= ~DO_DEVICE_INITIALIZING;
@@ -885,20 +890,21 @@ USBSTOR_CreatePDO(
     FDODeviceExtension->ChildPDO[LUN] = PDO;
     // send inquiry command by irp
-    Status = USBSTOR_SendInquiryIrp(PDO);
-    ASSERT(Status == STATUS_SUCCESS);
-
-    Response = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
-    ASSERT(Response);
+    Status = USBSTOR_FillInquiryData(PDO);
-    if (Response->DeviceType == 0)
+    if (!NT_SUCCESS(Status))
     {
-        // check if it is a floppy
-        Status = USBSTOR_SendFormatCapacityIrp(PDO);
-        DPRINT1("[USBSTOR] Status %x IsFloppy %x MediumTypeCode %x\n", Status,
PDODeviceExtension->IsFloppy, PDODeviceExtension->MediumTypeCode);
+        return Status;
+    }
-        // failing command is non critical
-        Status = STATUS_SUCCESS;
+    if (PDODeviceExtension->InquiryData->DeviceType == DIRECT_ACCESS_DEVICE)
+    {
+        PDODeviceExtension->IsFloppy = FALSE; // TODO: implement the actual check
+    }
+    else
+    {
+        // we work only with DIRECT_ACCESS_DEVICE for now
+        return STATUS_NOT_SUPPORTED;
     }
     return Status;
diff --git a/drivers/usb/usbstor/usbstor.h b/drivers/usb/usbstor/usbstor.h
index 40b369bd15e..1ac3e33a55e 100644
--- a/drivers/usb/usbstor/usbstor.h
+++ b/drivers/usb/usbstor/usbstor.h
@@ -68,7 +68,7 @@ typedef struct
     USBSTOR_COMMON_DEVICE_EXTENSION Common;
     PDEVICE_OBJECT LowerDeviceObject;
// points to FDO
     UCHAR LUN;
// lun id
-    PVOID InquiryData;
// USB SCSI inquiry data
+    PINQUIRYDATA InquiryData;
// USB SCSI inquiry data
     PUCHAR FormatData;
// USB SCSI Read Format Capacity Data
     UCHAR Claimed;
// indicating if it has been claimed by upper driver
     ULONG BlockLength;
// length of block
@@ -117,42 +117,6 @@ typedef struct
     UCHAR Status;                                                    // CSW status
 }CSW, *PCSW;
-//--------------------------------------------------------------------------------------------------------------------------------------------
-//
-// UFI INQUIRY command
-//
-typedef struct
-{
-    UCHAR Code;                                                      // operation code
0x12
-    UCHAR LUN;                                                       // lun address
-    UCHAR PageCode;                                                  // product data
information, always 0x00
-    UCHAR Reserved;                                                  // reserved 0x00
-    UCHAR AllocationLength;                                          // length of inquiry
data to be returned, default 36 bytes
-    UCHAR Reserved1[7];                                              //reserved bytes
0x00
-}UFI_INQUIRY_CMD, *PUFI_INQUIRY_CMD;
-
-C_ASSERT(sizeof(UFI_INQUIRY_CMD) == 12);
-
-#define UFI_INQUIRY_CMD_LEN 0x6
-
-//
-// UFI INQUIRY command response
-//
-typedef struct
-{
-    UCHAR DeviceType;                                                // device type
-    UCHAR RMB;                                                       // removable media
bit
-    UCHAR Version;                                                   // contains version
0x00
-    UCHAR Format;                                                    // response format
-    UCHAR Length;                                                    // additional length
-    UCHAR Reserved[3];                                               // reserved
-    UCHAR Vendor[8];                                                 // vendor
identification string
-    UCHAR Product[16];                                               // product
identification string
-    UCHAR Revision[4];                                               // product revision
code
-}UFI_INQUIRY_RESPONSE, *PUFI_INQUIRY_RESPONSE;
-
-C_ASSERT(sizeof(UFI_INQUIRY_RESPONSE) == 36);
-
//--------------------------------------------------------------------------------------------------------------------------------------------
 //
 // UFI read cmd