[USBSTOR]
[reactos.git] / drivers / usb / usbstor / disk.c
index b42f9af..0f426c8 100644 (file)
@@ -31,6 +31,11 @@ USBSTOR_HandleInternalDeviceControl(
     //
     Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
 
+    //
+    // sanity check
+    //
+    ASSERT(Request);
+
     //
     // get device extension
     //
@@ -39,8 +44,7 @@ USBSTOR_HandleInternalDeviceControl(
     //
     // sanity check
     //
-    ASSERT(Request);
-    ASSERT(PDODeviceExtension);
+    ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
 
     switch(Request->Function)
     {
@@ -56,7 +60,7 @@ USBSTOR_HandleInternalDeviceControl(
                 //
                 // 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)) ||
+                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)
                 {
@@ -87,7 +91,7 @@ USBSTOR_HandleInternalDeviceControl(
             //
             // add the request
             //
-            if (!USBSTOR_QueueAddIrp(DeviceObject, Irp))
+            if (!USBSTOR_QueueAddIrp(PDODeviceExtension->LowerDeviceObject, Irp))
             {
                 //
                 // irp was not added to the queue
@@ -111,7 +115,7 @@ USBSTOR_HandleInternalDeviceControl(
             //
             // release claim
             //
-            PDODeviceExtension->Claimed = TRUE;
+            PDODeviceExtension->Claimed = FALSE;
             Status = STATUS_SUCCESS;
             break;
         }
@@ -154,8 +158,7 @@ USBSTOR_HandleInternalDeviceControl(
             //
             // release queue
             //
-            USBSTOR_QueueRelease(DeviceObject);
-
+            USBSTOR_QueueRelease(PDODeviceExtension->LowerDeviceObject);
 
             //
             // set status success
@@ -173,7 +176,7 @@ USBSTOR_HandleInternalDeviceControl(
             //
             // flush all requests
             //
-            USBSTOR_QueueFlushIrps(DeviceObject);
+            USBSTOR_QueueFlushIrps(PDODeviceExtension->LowerDeviceObject);
 
             //
             // set status success
@@ -237,11 +240,15 @@ USBSTOR_HandleQueryProperty(
     PSTORAGE_PROPERTY_QUERY PropertyQuery;
     PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader;
     PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor;
-    ULONG FieldLengthVendor, FieldLengthProduct, FieldLengthRevision, TotalLength;
+    ULONG FieldLengthVendor, FieldLengthProduct, FieldLengthRevision, TotalLength, FieldLengthSerialNumber;
     PPDO_DEVICE_EXTENSION PDODeviceExtension;
     PUFI_INQUIRY_RESPONSE InquiryData;
     PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor;
     PUCHAR Buffer;
+    PFDO_DEVICE_EXTENSION FDODeviceExtension;
+    UNICODE_STRING SerialNumber;
+    ANSI_STRING AnsiString;
+    NTSTATUS Status;
 
     DPRINT1("USBSTOR_HandleQueryProperty\n");
 
@@ -304,6 +311,14 @@ USBSTOR_HandleQueryProperty(
         //
         PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
         ASSERT(PDODeviceExtension);
+        ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+        //
+        // get device extension
+        //
+        FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
+        ASSERT(FDODeviceExtension);
+        ASSERT(FDODeviceExtension->Common.IsFDO);
 
         //
         // get inquiry data
@@ -319,14 +334,28 @@ USBSTOR_HandleQueryProperty(
         FieldLengthRevision = USBSTOR_GetFieldLength(InquiryData->Revision, 4);
 
         //
-        // FIXME handle serial number
+        // is there a serial number
         //
+        if (FDODeviceExtension->SerialNumber)
+        {
+            //
+            // get length
+            //
+            FieldLengthSerialNumber = wcslen(FDODeviceExtension->SerialNumber->bString);
+        }
+        else
+        {
+            //
+            // no serial number
+            //
+            FieldLengthSerialNumber = 0;
+        }
 
         //
-        // total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 3 extra null bytes - 1
+        // total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 4 extra null bytes - 1
         // -1 due STORAGE_DEVICE_DESCRIPTOR contains one byte length of parameter data
         //
-        TotalLength = sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + 2;
+        TotalLength = sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + FieldLengthSerialNumber + 3;
 
         //
         // check if output buffer is long enough
@@ -367,8 +396,8 @@ USBSTOR_HandleQueryProperty(
         DeviceDescriptor->VendorIdOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - sizeof(UCHAR);
         DeviceDescriptor->ProductIdOffset = DeviceDescriptor->VendorIdOffset + FieldLengthVendor + 1;
         DeviceDescriptor->ProductRevisionOffset = DeviceDescriptor->ProductIdOffset + FieldLengthProduct + 1;
-        DeviceDescriptor->SerialNumberOffset = 0; //FIXME
-        DeviceDescriptor->RawPropertiesLength = FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + 3;
+        DeviceDescriptor->SerialNumberOffset = (FieldLengthSerialNumber > 0 ? DeviceDescriptor->ProductRevisionOffset + FieldLengthRevision + 1 : 0);
+        DeviceDescriptor->RawPropertiesLength = FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + FieldLengthSerialNumber + 3 + (FieldLengthSerialNumber > 0 ? + 1 : 0);
 
         //
         // copy descriptors
@@ -397,12 +426,34 @@ USBSTOR_HandleQueryProperty(
         Buffer += FieldLengthRevision + 1;
 
         //
-        // TODO: copy revision
+        // copy serial number
         //
+        if (FieldLengthSerialNumber)
+        {
+            //
+            // init unicode string
+            //
+            RtlInitUnicodeString(&SerialNumber, FDODeviceExtension->SerialNumber->bString);
+
+            //
+            // init ansi string
+            //
+            AnsiString.Buffer = (PCHAR)Buffer;
+            AnsiString.Length = 0;
+            AnsiString.MaximumLength = FieldLengthSerialNumber * sizeof(WCHAR);
+
+            //
+            // convert to ansi code
+            //
+            Status = RtlUnicodeStringToAnsiString(&AnsiString, &SerialNumber, FALSE);
+            ASSERT(Status == STATUS_SUCCESS);
+        }
+
 
         DPRINT("Vendor %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->VendorIdOffset));
         DPRINT("Product %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductIdOffset));
         DPRINT("Revision %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductRevisionOffset));
+        DPRINT("Serial %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->SerialNumberOffset));
 
         //
         // done
@@ -475,6 +526,11 @@ USBSTOR_HandleDeviceControl(
 {
     PIO_STACK_LOCATION IoStack;
     NTSTATUS Status;
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
+    PSCSI_ADAPTER_BUS_INFO BusInfo;
+    PSCSI_INQUIRY_DATA InquiryData;
+    PINQUIRYDATA ScsiInquiryData;
+    PUFI_INQUIRY_RESPONSE UFIInquiryResponse;
 
     //
     // get current stack location
@@ -488,14 +544,6 @@ USBSTOR_HandleDeviceControl(
         //
         Status = USBSTOR_HandleQueryProperty(DeviceObject, Irp);
     }
-    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_ADDRESS)
-    {
-        //
-        // query get scsi address
-        //
-        DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_GET_ADDRESS NOT implemented\n");
-        Status = STATUS_NOT_SUPPORTED;
-    }
     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH)
     {
         //
@@ -520,6 +568,108 @@ USBSTOR_HandleDeviceControl(
         DPRINT1("USBSTOR_HandleDeviceControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER NOT implemented\n");
         Status = STATUS_NOT_SUPPORTED;
     }
+    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_CAPABILITIES)
+    {
+        PIO_SCSI_CAPABILITIES Capabilities;
+
+        /* Legacy port capability query */
+        if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(PVOID))
+        {
+            Capabilities = *((PVOID *)Irp->AssociatedIrp.SystemBuffer) = ExAllocatePool(NonPagedPool, sizeof(IO_SCSI_CAPABILITIES));
+            Irp->IoStatus.Information = sizeof(PVOID);
+        }
+        else
+        {
+            Capabilities = Irp->AssociatedIrp.SystemBuffer;
+            Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
+        }
+
+        if (Capabilities)
+        {
+            Capabilities->MaximumTransferLength = MAXULONG;
+            Capabilities->MaximumPhysicalPages = 25;
+            Capabilities->SupportedAsynchronousEvents = 0;
+            Capabilities->AlignmentMask = 0;
+            Capabilities->TaggedQueuing = FALSE;
+            Capabilities->AdapterScansDown = FALSE;
+            Capabilities->AdapterUsesPio = FALSE;
+            Status = STATUS_SUCCESS;
+        }
+        else
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+        }
+    } 
+    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_INQUIRY_DATA)
+    {
+        //
+        // get device extension
+        //
+        PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+        ASSERT(PDODeviceExtension);
+        ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+        //
+        // get parameters
+        //
+        BusInfo = Irp->AssociatedIrp.SystemBuffer;
+        InquiryData = (PSCSI_INQUIRY_DATA)(BusInfo + 1);
+        ScsiInquiryData = (PINQUIRYDATA)InquiryData->InquiryData;
+        
+
+        //
+        // get inquiry data
+        //
+        UFIInquiryResponse = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
+        ASSERT(UFIInquiryResponse);
+
+
+        BusInfo->NumberOfBuses = 1;
+        BusInfo->BusData[0].NumberOfLogicalUnits = 1; //FIXME
+        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) ? 1 : 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));
+
+        Irp->IoStatus.Information = sizeof(SCSI_ADAPTER_BUS_INFO) + sizeof(SCSI_INQUIRY_DATA) + sizeof(INQUIRYDATA) - 1;
+        Status = STATUS_SUCCESS;
+    }
+    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_ADDRESS)
+    {
+        PSCSI_ADDRESS Address = Irp->AssociatedIrp.SystemBuffer;
+
+        Address->Length = sizeof(SCSI_ADDRESS);
+        Address->PortNumber = 0;
+        Address->PathId = 0;
+        Address->TargetId = 0;
+        Address->Lun = (((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LUN & MAX_LUN);
+        Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
+
+        Status = STATUS_SUCCESS;
+    }
     else
     {
         //