[STORPORT] Enumerate attached devices
authorEric Kohl <eric.kohl@reactos.org>
Thu, 24 May 2018 09:39:01 +0000 (11:39 +0200)
committerEric Kohl <eric.kohl@reactos.org>
Thu, 24 May 2018 09:39:47 +0000 (11:39 +0200)
- Implement AcquireSpinlock, ReleaseSpinlock and GetExtendedFunctionTable notifications.
- Implement a bus scan routine, borrowed from scsiport.

Storport and storahci are now able to detect a disk device attached to a Virtual Box AHCI controller.

drivers/storage/port/storport/fdo.c
drivers/storage/port/storport/miniport.c
drivers/storage/port/storport/misc.c
drivers/storage/port/storport/pdo.c
drivers/storage/port/storport/precomp.h
drivers/storage/port/storport/storport.c
drivers/storage/port/storport/storport.spec
sdk/include/ddk/storport.h

index 92a5a7f..e20fd68 100644 (file)
@@ -243,6 +243,289 @@ PortFdoStartDevice(
 }
 
 
+static NTSTATUS
+SpiSendInquiry(IN PDEVICE_OBJECT DeviceObject,
+               ULONG Bus, ULONG Target, ULONG Lun)
+{
+//    IO_STATUS_BLOCK IoStatusBlock;
+//    PIO_STACK_LOCATION IrpStack;
+//    KEVENT Event;
+//    KIRQL Irql;
+//    PIRP Irp;
+    NTSTATUS Status;
+    PINQUIRYDATA InquiryBuffer;
+    PUCHAR /*PSENSE_DATA*/ SenseBuffer;
+//    BOOLEAN KeepTrying = TRUE;
+//    ULONG RetryCount = 0;
+    SCSI_REQUEST_BLOCK Srb;
+    PCDB Cdb;
+//    PSCSI_PORT_LUN_EXTENSION LunExtension;
+//    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+
+PFDO_DEVICE_EXTENSION DeviceExtension;
+    PVOID SrbExtension = NULL;
+    BOOLEAN ret;
+
+    DPRINT1("SpiSendInquiry() called\n");
+
+    DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    InquiryBuffer = ExAllocatePoolWithTag(NonPagedPool, INQUIRYDATABUFFERSIZE, TAG_INQUIRY_DATA);
+    if (InquiryBuffer == NULL)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    SenseBuffer = ExAllocatePoolWithTag(NonPagedPool, SENSE_BUFFER_SIZE, TAG_SENSE_DATA);
+    if (SenseBuffer == NULL)
+    {
+        ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    if (DeviceExtension->Miniport.PortConfig.SrbExtensionSize != 0)
+    {
+        SrbExtension = ExAllocatePoolWithTag(NonPagedPool, DeviceExtension->Miniport.PortConfig.SrbExtensionSize, TAG_SENSE_DATA);
+        if (SrbExtension == NULL)
+        {
+            ExFreePoolWithTag(SenseBuffer, TAG_SENSE_DATA);
+            ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA);
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+    }
+
+//    while (KeepTrying)
+    {
+        /* Initialize event for waiting */
+//        KeInitializeEvent(&Event,
+//                          NotificationEvent,
+//                          FALSE);
+
+        /* Create an IRP */
+//        Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_IN,
+//                                            DeviceObject,
+//                                            NULL,
+//                                            0,
+//                                            InquiryBuffer,
+//                                            INQUIRYDATABUFFERSIZE,
+//                                            TRUE,
+//                                            &Event,
+//                                            &IoStatusBlock);
+//        if (Irp == NULL)
+//        {
+//            DPRINT1("IoBuildDeviceIoControlRequest() failed\n");
+
+            /* Quit the loop */
+//            Status = STATUS_INSUFFICIENT_RESOURCES;
+//            KeepTrying = FALSE;
+//            continue;
+//        }
+
+        /* Prepare SRB */
+        RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
+
+        Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
+//        Srb.OriginalRequest = Irp;
+        Srb.PathId = Bus;
+        Srb.TargetId = Target;
+        Srb.Lun = Lun;
+        Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
+        Srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
+        Srb.TimeOutValue = 4;
+        Srb.CdbLength = 6;
+
+        Srb.SenseInfoBuffer = SenseBuffer;
+        Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE;
+
+        Srb.DataBuffer = InquiryBuffer;
+        Srb.DataTransferLength = INQUIRYDATABUFFERSIZE;
+
+        Srb.SrbExtension = SrbExtension;
+
+        /* Attach Srb to the Irp */
+//        IrpStack = IoGetNextIrpStackLocation(Irp);
+//        IrpStack->Parameters.Scsi.Srb = &Srb;
+
+        /* Fill in CDB */
+        Cdb = (PCDB)Srb.Cdb;
+        Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
+        Cdb->CDB6INQUIRY.LogicalUnitNumber = Lun;
+        Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
+
+        /* Call the driver */
+
+
+        ret = MiniportStartIo(&DeviceExtension->Miniport,
+                              &Srb);
+DPRINT1("MiniportStartIo returned %u\n", ret);
+
+//        Status = IoCallDriver(DeviceObject, Irp);
+
+        /* Wait for it to complete */
+//        if (Status == STATUS_PENDING)
+//        {
+//            DPRINT1("SpiSendInquiry(): Waiting for the driver to process request...\n");
+//            KeWaitForSingleObject(&Event,
+//                                  Executive,
+//                                  KernelMode,
+//                                  FALSE,
+//                                  NULL);
+//            Status = IoStatusBlock.Status;
+//        }
+
+//        DPRINT1("SpiSendInquiry(): Request processed by driver, status = 0x%08X\n", Status);
+
+        if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_SUCCESS)
+        {
+            /* All fine, copy data over */
+//            RtlCopyMemory(LunInfo->InquiryData,
+//                          InquiryBuffer,
+//                          INQUIRYDATABUFFERSIZE);
+
+            /* Quit the loop */
+            Status = STATUS_SUCCESS;
+//            KeepTrying = FALSE;
+//            continue;
+        }
+
+        DPRINT("Inquiry SRB failed with SrbStatus 0x%08X\n", Srb.SrbStatus);
+#if 0
+        /* Check if the queue is frozen */
+        if (Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN)
+        {
+            /* Something weird happened, deal with it (unfreeze the queue) */
+            KeepTrying = FALSE;
+
+            DPRINT("SpiSendInquiry(): the queue is frozen at TargetId %d\n", Srb.TargetId);
+
+            LunExtension = SpiGetLunExtension(DeviceExtension,
+                                              LunInfo->PathId,
+                                              LunInfo->TargetId,
+                                              LunInfo->Lun);
+
+            /* Clear frozen flag */
+            LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
+
+            /* Acquire the spinlock */
+            KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
+
+            /* Process the request */
+            SpiGetNextRequestFromLun(DeviceObject->DeviceExtension, LunExtension);
+
+            /* SpiGetNextRequestFromLun() releases the spinlock,
+                so we just lower irql back to what it was before */
+            KeLowerIrql(Irql);
+        }
+
+        /* Check if data overrun happened */
+        if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN)
+        {
+            DPRINT("Data overrun at TargetId %d\n", LunInfo->TargetId);
+
+            /* Nothing dramatic, just copy data, but limiting the size */
+            RtlCopyMemory(LunInfo->InquiryData,
+                            InquiryBuffer,
+                            (Srb.DataTransferLength > INQUIRYDATABUFFERSIZE) ?
+                            INQUIRYDATABUFFERSIZE : Srb.DataTransferLength);
+
+            /* Quit the loop */
+            Status = STATUS_SUCCESS;
+            KeepTrying = FALSE;
+        }
+        else if ((Srb.SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
+                 SenseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST)
+        {
+            /* LUN is not valid, but some device responds there.
+                Mark it as invalid anyway */
+
+            /* Quit the loop */
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            KeepTrying = FALSE;
+        }
+        else
+        {
+            /* Retry a couple of times if no timeout happened */
+            if ((RetryCount < 2) &&
+                (SRB_STATUS(Srb.SrbStatus) != SRB_STATUS_NO_DEVICE) &&
+                (SRB_STATUS(Srb.SrbStatus) != SRB_STATUS_SELECTION_TIMEOUT))
+            {
+                RetryCount++;
+                KeepTrying = TRUE;
+            }
+            else
+            {
+                /* That's all, quit the loop */
+                KeepTrying = FALSE;
+
+                /* Set status according to SRB status */
+                if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_BAD_FUNCTION ||
+                    SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_BAD_SRB_BLOCK_LENGTH)
+                {
+                    Status = STATUS_INVALID_DEVICE_REQUEST;
+                }
+                else
+                {
+                    Status = STATUS_IO_DEVICE_ERROR;
+                }
+            }
+        }
+#endif
+    }
+
+    /* Free buffers */
+    if (SrbExtension != NULL)
+        ExFreePoolWithTag(SrbExtension, TAG_SENSE_DATA);
+
+    ExFreePoolWithTag(SenseBuffer, TAG_SENSE_DATA);
+    ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA);
+
+    DPRINT("SpiSendInquiry() done with Status 0x%08X\n", Status);
+
+    return Status;
+}
+
+
+static
+NTSTATUS
+PortFdoScanBus(
+    _In_ PFDO_DEVICE_EXTENSION DeviceExtension)
+{
+    ULONG Bus, Target, Lun;
+    NTSTATUS Status;
+
+
+    DPRINT1("PortFdoScanBus(%p)\n",
+            DeviceExtension);
+
+    DPRINT1("NumberOfBuses: %lu\n", DeviceExtension->Miniport.PortConfig.NumberOfBuses);
+    DPRINT1("MaximumNumberOfTargets: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets);
+    DPRINT1("MaximumNumberOfLogicalUnits: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits);
+
+    /* Scan all buses */
+    for (Bus = 0; Bus < DeviceExtension->Miniport.PortConfig.NumberOfBuses; Bus++)
+    {
+        DPRINT1("Scanning bus %ld\n", Bus);
+
+        /* Scan all targets */
+        for (Target = 0; Target < DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets; Target++)
+        {
+            DPRINT1("  Scanning target %ld:%ld\n", Bus, Target);
+
+            /* Scan all logical units */
+            for (Lun = 0; Lun < DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits; Lun++)
+            {
+                DPRINT1("    Scanning logical unit %ld:%ld:%ld\n", Bus, Target, Lun);
+
+                Status = SpiSendInquiry(DeviceExtension->Device, Bus, Target, Lun);
+                DPRINT1("SpiSendInquiry returned 0x%08lx\n", Status);
+            }
+        }
+    }
+
+    DPRINT1("Done!\n");
+
+    return STATUS_SUCCESS;
+}
+
+
 static
 NTSTATUS
 PortFdoQueryBusRelations(
@@ -254,6 +537,8 @@ PortFdoQueryBusRelations(
     DPRINT1("PortFdoQueryBusRelations(%p %p)\n",
             DeviceExtension, Information);
 
+    Status = PortFdoScanBus(DeviceExtension);
+
     *Information = 0;
 
     return Status;
@@ -282,6 +567,35 @@ PortFdoFilterRequirements(
 }
 
 
+NTSTATUS
+NTAPI
+PortFdoScsi(
+    _In_ PDEVICE_OBJECT DeviceObject,
+    _In_ PIRP Irp)
+{
+    PFDO_DEVICE_EXTENSION DeviceExtension;
+//    PIO_STACK_LOCATION Stack;
+    ULONG_PTR Information = 0;
+    NTSTATUS Status = STATUS_NOT_SUPPORTED;
+
+    DPRINT1("PortFdoScsi(%p %p)\n",
+            DeviceObject, Irp);
+
+    DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    ASSERT(DeviceExtension);
+    ASSERT(DeviceExtension->ExtensionType == FdoExtension);
+
+//    Stack = IoGetCurrentIrpStackLocation(Irp);
+
+
+    Irp->IoStatus.Information = Information;
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+
 NTSTATUS
 NTAPI
 PortFdoPnp(
index 815e609..e1aedcb 100644 (file)
@@ -362,4 +362,21 @@ MiniportHwInterrupt(
     return Result;
 }
 
+
+BOOLEAN
+MiniportStartIo(
+    _In_ PMINIPORT Miniport,
+    _In_ PSCSI_REQUEST_BLOCK Srb)
+{
+    BOOLEAN Result;
+
+    DPRINT1("MiniportHwStartIo(%p %p)\n",
+            Miniport, Srb);
+
+    Result = Miniport->InitData->HwStartIo(&Miniport->MiniportExtension->HwDeviceExtension, Srb);
+    DPRINT1("HwStartIo() returned %u\n", Result);
+
+    return Result;
+}
+
 /* EOF */
index f74fd35..1c9c73a 100644 (file)
@@ -370,17 +370,4 @@ AllocateAddressMapping(
     return STATUS_SUCCESS;
 }
 
-#if defined(_M_AMD64)
-/* KeQuerySystemTime is an inline function, 
-   so we cannot forward the export to ntoskrnl */
-STORPORT_API
-VOID
-NTAPI
-StorPortQuerySystemTime(
-    _Out_ PLARGE_INTEGER CurrentTime)
-{
-    KeQuerySystemTime(CurrentTime);
-}
-#endif /* defined(_M_AMD64) */
-
 /* EOF */
index fb7280c..8df3151 100644 (file)
 
 /* FUNCTIONS ******************************************************************/
 
+NTSTATUS
+NTAPI
+PortPdoScsi(
+    _In_ PDEVICE_OBJECT DeviceObject,
+    _In_ PIRP Irp)
+{
+    DPRINT1("PortPdoScsi()\n");
+
+    Irp->IoStatus.Information = 0;
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return STATUS_SUCCESS;
+}
+
+
 NTSTATUS
 NTAPI
 PortPdoPnp(
index 5bd16f3..84925ef 100644 (file)
@@ -29,6 +29,8 @@
 #define TAG_ACCRESS_RANGE   'RAtS'
 #define TAG_RESOURCE_LIST   'LRtS'
 #define TAG_ADDRESS_MAPPING 'MAtS'
+#define TAG_INQUIRY_DATA    'QItS'
+#define TAG_SENSE_DATA      'NStS'
 
 typedef enum
 {
@@ -119,6 +121,12 @@ typedef struct _PDO_DEVICE_EXTENSION
 
 /* fdo.c */
 
+NTSTATUS
+NTAPI
+PortFdoScsi(
+    _In_ PDEVICE_OBJECT DeviceObject,
+    _In_ PIRP Irp);
+
 NTSTATUS
 NTAPI
 PortFdoPnp(
@@ -146,6 +154,11 @@ BOOLEAN
 MiniportHwInterrupt(
     _In_ PMINIPORT Miniport);
 
+BOOLEAN
+MiniportStartIo(
+    _In_ PMINIPORT Miniport,
+    _In_ PSCSI_REQUEST_BLOCK Srb);
+
 /* misc.c */
 
 NTSTATUS
@@ -206,6 +219,12 @@ AllocateAddressMapping(
 
 /* pdo.c */
 
+NTSTATUS
+NTAPI
+PortPdoScsi(
+    _In_ PDEVICE_OBJECT DeviceObject,
+    _In_ PIRP Irp);
+
 NTSTATUS
 NTAPI
 PortPdoPnp(
index a9fd3d0..03ec563 100644 (file)
@@ -100,6 +100,69 @@ PortGetDriverInitData(
 }
 
 
+static
+VOID
+PortAcquireSpinLock(
+    PFDO_DEVICE_EXTENSION DeviceExtension,
+    STOR_SPINLOCK SpinLock,
+    PVOID LockContext,
+    PSTOR_LOCK_HANDLE LockHandle)
+{
+    DPRINT1("PortAcquireSpinLock(%p %lu %p %p)\n",
+            DeviceExtension, SpinLock, LockContext, LockHandle);
+
+    LockHandle->Lock = SpinLock;
+
+    switch (SpinLock)
+    {
+        case DpcLock: /* 1, */
+            DPRINT1("DpcLock\n");
+            break;
+
+        case StartIoLock: /* 2 */
+            DPRINT1("StartIoLock\n");
+            break;
+
+        case InterruptLock: /* 3 */
+            DPRINT1("InterruptLock\n");
+            if (DeviceExtension->Interrupt == NULL)
+                LockHandle->Context.OldIrql = 0;
+            else
+                LockHandle->Context.OldIrql = KeAcquireInterruptSpinLock(DeviceExtension->Interrupt);
+            break;
+    }
+}
+
+
+static
+VOID
+PortReleaseSpinLock(
+    PFDO_DEVICE_EXTENSION DeviceExtension,
+    PSTOR_LOCK_HANDLE LockHandle)
+{
+    DPRINT1("PortReleaseSpinLock(%p %p)\n",
+            DeviceExtension, LockHandle);
+
+    switch (LockHandle->Lock)
+    {
+        case DpcLock: /* 1, */
+            DPRINT1("DpcLock\n");
+            break;
+
+        case StartIoLock: /* 2 */
+            DPRINT1("StartIoLock\n");
+            break;
+
+        case InterruptLock: /* 3 */
+            DPRINT1("InterruptLock\n");
+            if (DeviceExtension->Interrupt != NULL)
+                KeReleaseInterruptSpinLock(DeviceExtension->Interrupt,
+                                           LockHandle->Context.OldIrql);
+            break;
+    }
+}
+
+
 static
 NTSTATUS
 NTAPI
@@ -280,13 +343,30 @@ PortDispatchScsi(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp)
 {
+    PFDO_DEVICE_EXTENSION DeviceExtension;
+
     DPRINT1("PortDispatchScsi(%p %p)\n",
             DeviceObject, Irp);
 
-    Irp->IoStatus.Status = STATUS_SUCCESS;
-    Irp->IoStatus.Information = 0;
+    DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    DPRINT1("ExtensionType: %u\n", DeviceExtension->ExtensionType);
 
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    switch (DeviceExtension->ExtensionType)
+    {
+        case FdoExtension:
+            return PortFdoScsi(DeviceObject,
+                               Irp);
+
+        case PdoExtension:
+            return PortPdoScsi(DeviceObject,
+                               Irp);
+
+        default:
+            Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+            Irp->IoStatus.Information = 0;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return STATUS_UNSUCCESSFUL;
+    }
 
     return STATUS_SUCCESS;
 }
@@ -742,10 +822,13 @@ StorPortGetPhysicalAddress(
 
     // FIXME
 
-    UNIMPLEMENTED;
 
-    *Length = 0;
-    PhysicalAddress.QuadPart = (LONGLONG)0;
+    PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
+    *Length = 1;
+//    UNIMPLEMENTED;
+
+//    *Length = 0;
+//    PhysicalAddress.QuadPart = (LONGLONG)0;
 
     return PhysicalAddress;
 }
@@ -1012,11 +1095,16 @@ StorPortNotification(
     PMINIPORT_DEVICE_EXTENSION MiniportExtension = NULL;
     PFDO_DEVICE_EXTENSION DeviceExtension = NULL;
     PHW_PASSIVE_INITIALIZE_ROUTINE HwPassiveInitRoutine;
+    PSTORPORT_EXTENDED_FUNCTIONS *ppExtendedFunctions;
     PBOOLEAN Result;
     PSTOR_DPC Dpc;
     PHW_DPC_ROUTINE HwDpcRoutine;
     va_list ap;
 
+    STOR_SPINLOCK SpinLock;
+    PVOID LockContext;
+    PSTOR_LOCK_HANDLE LockHandle;
+
     DPRINT1("StorPortNotification(%x %p)\n",
             NotificationType, HwDeviceExtension);
 
@@ -1036,6 +1124,13 @@ StorPortNotification(
 
     switch (NotificationType)
     {
+        case GetExtendedFunctionTable:
+            DPRINT1("GetExtendedFunctionTable\n");
+            ppExtendedFunctions = (PSTORPORT_EXTENDED_FUNCTIONS*)va_arg(ap, PSTORPORT_EXTENDED_FUNCTIONS*);
+            if (ppExtendedFunctions != NULL)
+                *ppExtendedFunctions = NULL; /* FIXME */
+            break;
+
         case EnablePassiveInitialization:
             DPRINT1("EnablePassiveInitialization\n");
             HwPassiveInitRoutine = (PHW_PASSIVE_INITIALIZE_ROUTINE)va_arg(ap, PHW_PASSIVE_INITIALIZE_ROUTINE);
@@ -1065,6 +1160,28 @@ StorPortNotification(
             KeInitializeSpinLock(&Dpc->Lock);
             break;
 
+        case AcquireSpinLock:
+            DPRINT1("AcquireSpinLock\n");
+            SpinLock = (STOR_SPINLOCK)va_arg(ap, STOR_SPINLOCK);
+            DPRINT1("SpinLock %lu\n", SpinLock);
+            LockContext = (PVOID)va_arg(ap, PVOID);
+            DPRINT1("LockContext %p\n", LockContext);
+            LockHandle = (PSTOR_LOCK_HANDLE)va_arg(ap, PSTOR_LOCK_HANDLE);
+            DPRINT1("LockHandle %p\n", LockHandle);
+            PortAcquireSpinLock(DeviceExtension,
+                                SpinLock,
+                                LockContext,
+                                LockHandle);
+            break;
+
+        case ReleaseSpinLock:
+            DPRINT1("ReleaseSpinLock\n");
+            LockHandle = (PSTOR_LOCK_HANDLE)va_arg(ap, PSTOR_LOCK_HANDLE);
+            DPRINT1("LockHandle %p\n", LockHandle);
+            PortReleaseSpinLock(DeviceExtension,
+                                LockHandle);
+            break;
+
         default:
             DPRINT1("Unsupported Notification %lx\n", NotificationType);
             break;
@@ -1109,6 +1226,25 @@ StorPortPauseDevice(
 }
 
 
+#if defined(_M_AMD64)
+/*
+ * @implemented
+ */
+/* KeQuerySystemTime is an inline function, 
+   so we cannot forward the export to ntoskrnl */
+STORPORT_API
+VOID
+NTAPI
+StorPortQuerySystemTime(
+    _Out_ PLARGE_INTEGER CurrentTime)
+{
+    DPRINT1("StorPortQuerySystemTime(%p)\n", CurrentTime);
+
+    KeQuerySystemTime(CurrentTime);
+}
+#endif /* defined(_M_AMD64) */
+
+
 /*
  * @unimplemented
  */
index 310e201..a36e5ed 100644 (file)
 @ stdcall StorPortLogError(ptr ptr long long long long long)
 @ stdcall StorPortMoveMemory(ptr ptr long)
 @ cdecl StorPortNotification()
-@ stdcall -arch=i386 StorPortQuerySystemTime(ptr) NTOSKRNL.KeQuerySystemTime
-@ stdcall -arch=amd64 StorPortQuerySystemTime(ptr)
 @ stdcall StorPortPause(ptr long)
 @ stdcall StorPortPauseDevice(ptr long long long long)
+@ stdcall -arch=i386 StorPortQuerySystemTime(ptr) NTOSKRNL.KeQuerySystemTime
+@ stdcall -arch=amd64 StorPortQuerySystemTime(ptr)
 @ stdcall StorPortReadPortBufferUchar(ptr ptr ptr long)
 @ stdcall StorPortReadPortBufferUlong(ptr ptr ptr long)
 @ stdcall StorPortReadPortBufferUshort(ptr ptr ptr long)
index 64a6e10..44d5d96 100644 (file)
@@ -57,7 +57,14 @@ extern "C" {
 #define CDB10GENERIC_LENGTH                 10
 #define CDB12GENERIC_LENGTH                 12
 
-#define INQUIRYDATABUFFERSIZE               36
+#define INQUIRYDATABUFFERSIZE                36
+#define SENSE_BUFFER_SIZE                    18
+#define MAX_SENSE_BUFFER_SIZE               255
+
+#define FILE_DEVICE_SCSI 0x0000001b
+#define IOCTL_SCSI_EXECUTE_IN   ((FILE_DEVICE_SCSI << 16) + 0x0011)
+#define IOCTL_SCSI_EXECUTE_OUT  ((FILE_DEVICE_SCSI << 16) + 0x0012)
+#define IOCTL_SCSI_EXECUTE_NONE ((FILE_DEVICE_SCSI << 16) + 0x0013)
 
 #define MODE_PAGE_VENDOR_SPECIFIC           0x00
 #define MODE_PAGE_ERROR_RECOVERY            0x01
@@ -563,6 +570,12 @@ typedef enum _STOR_EVENT_ASSOCIATION_ENUM
     StorEventInvalidAssociation
 } STOR_EVENT_ASSOCIATION_ENUM;
 
+typedef enum _GETSGSTATUS
+{
+    SG_ALLOCATED = 0,
+    SG_BUFFER_TOO_SMALL
+} GETSGSTATUS, *PGETSGSTATUS;
+
 typedef struct _SCSI_REQUEST_BLOCK
 {
     USHORT Length;
@@ -2182,6 +2195,64 @@ VOID
     _In_ PSTOR_SCATTER_GATHER_LIST ScatterGather,
     _In_ PVOID Context);
 
+typedef
+BOOLEAN
+(NTAPI *PStorPortGetMessageInterruptInformation)(
+    _In_ PVOID HwDeviceExtension,
+    _In_ ULONG MessageId,
+    _Out_ PMESSAGE_INTERRUPT_INFORMATION InterruptInfo);
+
+typedef
+VOID
+(NTAPI *PStorPortPutScatterGatherList)(
+    _In_ PVOID HwDeviceExtension,
+    _In_ PSTOR_SCATTER_GATHER_LIST ScatterGatherList,
+    _In_ BOOLEAN WriteToDevice);
+
+typedef
+GETSGSTATUS
+(NTAPI *PStorPortBuildScatterGatherList)(
+    _In_ PVOID HwDeviceExtension,
+    _In_ PVOID Mdl,
+    _In_ PVOID CurrentVa,
+    _In_ ULONG Length,
+    _In_ PpostScaterGatherExecute ExecutionRoutine,
+    _In_ PVOID Context,
+    _In_ BOOLEAN WriteToDevice,
+    _Inout_ PVOID ScatterGatherBuffer,
+    _In_ ULONG ScatterGatherBufferLength);
+
+typedef
+VOID
+(NTAPI *PStorPortFreePool)(
+    _In_ PVOID PMemory,
+    _In_ PVOID HwDeviceExtension,
+    _In_opt_ PVOID PMdl);
+
+typedef
+PVOID
+(NTAPI *PStorPortAllocatePool)(
+    _In_ ULONG NumberOfBytes,
+    _In_ ULONG Tag,
+    _In_ PVOID HwDeviceExtension,
+    _Out_ PVOID *PMdl);
+
+typedef
+PVOID
+(NTAPI *PStorPortGetSystemAddress)(
+    _In_ PSCSI_REQUEST_BLOCK Srb);
+
+typedef struct _STORPORT_EXTENDED_FUNCTIONS
+{
+    ULONG Version;
+    PStorPortGetMessageInterruptInformation GetMessageInterruptInformation;
+    PStorPortPutScatterGatherList PutScatterGatherList;
+    PStorPortBuildScatterGatherList BuildScatterGatherList;
+    PStorPortFreePool FreePool;
+    PStorPortAllocatePool AllocatePool;
+    PStorPortGetSystemAddress GetSystemAddress;
+} STORPORT_EXTENDED_FUNCTIONS, *PSTORPORT_EXTENDED_FUNCTIONS;
+
 typedef struct _HW_INITIALIZATION_DATA
 {
     ULONG HwInitializationDataSize;