https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c0c57e2324a7326de3e060c6296af177a75ff54f

commit c0c57e2324a7326de3e060c6296af177a75ff54f
Author:     Dmitry Borisov <[email protected]>
AuthorDate: Sun Jan 8 18:07:14 2023 +0600
Commit:     Stanislav Motylkov <[email protected]>
CommitDate: Sun Jul 16 13:20:30 2023 +0300

    [PCIIDEX] Improve and fix the driver
    
    - Fix IRP handling, add missing IRP handlers
    - Specify the device name for DO
    - The legacy IRQ descriptor is edge-triggered
    - Improve pool tagging
    - Place the PNP code in a pageable section
    
    CORE-17256
---
 drivers/storage/ide/pciidex/CMakeLists.txt |    4 +-
 drivers/storage/ide/pciidex/fdo.c          |  934 ++++++++++----------
 drivers/storage/ide/pciidex/miniport.c     |  307 +++----
 drivers/storage/ide/pciidex/misc.c         |   73 --
 drivers/storage/ide/pciidex/pciidex.c      |  337 ++++++-
 drivers/storage/ide/pciidex/pciidex.h      |  158 +++-
 drivers/storage/ide/pciidex/pdo.c          | 1325 +++++++++++++++++-----------
 drivers/storage/ide/pciidex/power.c        |   66 ++
 sdk/include/ddk/ide.h                      |    1 +
 9 files changed, 1926 insertions(+), 1279 deletions(-)

diff --git a/drivers/storage/ide/pciidex/CMakeLists.txt 
b/drivers/storage/ide/pciidex/CMakeLists.txt
index d8d1daa4f5f..492ea66bd11 100644
--- a/drivers/storage/ide/pciidex/CMakeLists.txt
+++ b/drivers/storage/ide/pciidex/CMakeLists.txt
@@ -4,9 +4,9 @@ spec2def(pciidex.sys pciidex.spec ADD_IMPORTLIB)
 list(APPEND SOURCE
     fdo.c
     miniport.c
-    misc.c
     pciidex.c
     pdo.c
+    power.c
     pciidex.h)
 
 add_library(pciidex MODULE
@@ -16,5 +16,5 @@ add_library(pciidex MODULE
 
 add_pch(pciidex pciidex.h SOURCE)
 set_module_type(pciidex kernelmodedriver)
-add_importlibs(pciidex ntoskrnl)
+add_importlibs(pciidex ntoskrnl hal)
 add_cd_file(TARGET pciidex DESTINATION reactos/system32/drivers NO_CAB FOR all)
diff --git a/drivers/storage/ide/pciidex/fdo.c 
b/drivers/storage/ide/pciidex/fdo.c
index b4b7a244d3d..b85cbfae748 100644
--- a/drivers/storage/ide/pciidex/fdo.c
+++ b/drivers/storage/ide/pciidex/fdo.c
@@ -1,9 +1,9 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         PCI IDE bus driver extension
- * FILE:            drivers/storage/pciidex/fdo.c
- * PURPOSE:         IRP_MJ_PNP operations for FDOs
- * PROGRAMMERS:     Herv� Poussineau ([email protected])
+ * PROJECT:     PCI IDE bus driver extension
+ * LICENSE:     See COPYING in the top level directory
+ * PURPOSE:     IRP_MJ_PNP operations for FDOs
+ * COPYRIGHT:   Copyright 2005 Hervé Poussineau <[email protected]>
+ *              Copyright 2023 Dmitry Borisov <[email protected]>
  */
 
 #include "pciidex.h"
@@ -11,481 +11,497 @@
 #define NDEBUG
 #include <debug.h>
 
-#include <initguid.h>
-#include <wdmguid.h>
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXFdoParseResources(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ PCM_RESOURCE_LIST ResourcesTranslated)
+{
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR BusMasterDescriptor = NULL;
+    PVOID IoBase;
+    ULONG i;
+
+    PAGED_CODE();
+
+    if (!ResourcesTranslated)
+        return STATUS_INVALID_PARAMETER;
+
+    for (i = 0; i < ResourcesTranslated->List[0].PartialResourceList.Count; 
++i)
+    {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+
+        Descriptor = 
&ResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[i];
+        switch (Descriptor->Type)
+        {
+            case CmResourceTypePort:
+            case CmResourceTypeMemory:
+            {
+                switch (Descriptor->u.Port.Length)
+                {
+                    /* Bus master port base */
+                    case 16:
+                    {
+                        if (!BusMasterDescriptor)
+                            BusMasterDescriptor = Descriptor;
+                        break;
+                    }
+
+                    default:
+                        break;
+                }
+            }
+
+            default:
+                break;
+        }
+    }
+
+    if (!BusMasterDescriptor)
+        return STATUS_DEVICE_CONFIGURATION_ERROR;
+
+    if ((BusMasterDescriptor->Type == CmResourceTypePort) &&
+        (BusMasterDescriptor->Flags & CM_RESOURCE_PORT_IO))
+    {
+        IoBase = (PVOID)(ULONG_PTR)BusMasterDescriptor->u.Port.Start.QuadPart;
+    }
+    else
+    {
+        IoBase = MmMapIoSpace(BusMasterDescriptor->u.Memory.Start, 16, 
MmNonCached);
+        if (!IoBase)
+            return STATUS_INSUFFICIENT_RESOURCES;
+
+        FdoExtension->IoBaseMapped = TRUE;
+    }
+    FdoExtension->BusMasterPortBase = IoBase;
+
+    return STATUS_SUCCESS;
+}
 
-static NTSTATUS
-GetBusInterface(
-       IN PFDO_DEVICE_EXTENSION DeviceExtension)
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXFdoStartDevice(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ PIRP Irp)
 {
-       PBUS_INTERFACE_STANDARD BusInterface = NULL;
-       KEVENT Event;
-       IO_STATUS_BLOCK IoStatus;
-       PIRP Irp;
-       PIO_STACK_LOCATION Stack;
-       NTSTATUS Status = STATUS_UNSUCCESSFUL;
-
-       if (DeviceExtension->BusInterface)
-       {
-               DPRINT("We already have the bus interface\n");
-               goto cleanup;
-       }
-
-       BusInterface = ExAllocatePool(PagedPool, 
sizeof(BUS_INTERFACE_STANDARD));
-       if (!BusInterface)
-       {
-               DPRINT("ExAllocatePool() failed\n");
-               Status = STATUS_INSUFFICIENT_RESOURCES;
-               goto cleanup;
-       }
-
-       KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
-       Irp = IoBuildSynchronousFsdRequest(
-               IRP_MJ_PNP,
-               DeviceExtension->LowerDevice,
-               NULL,
-               0,
-               NULL,
-               &Event,
-               &IoStatus);
-       if (!Irp)
-       {
-               DPRINT("IoBuildSynchronousFsdRequest() failed\n");
-               Status = STATUS_INSUFFICIENT_RESOURCES;
-               goto cleanup;
-       }
-
-       Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
-       Irp->IoStatus.Information = 0;
-
-       Stack = IoGetNextIrpStackLocation(Irp);
-       Stack->MajorFunction = IRP_MJ_PNP;
-       Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
-       Stack->Parameters.QueryInterface.InterfaceType = 
(LPGUID)&GUID_BUS_INTERFACE_STANDARD;
-       Stack->Parameters.QueryInterface.Version = 1;
-       Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
-       Stack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface;
-       Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
-
-       Status = IoCallDriver(DeviceExtension->LowerDevice, Irp);
-       if (Status == STATUS_PENDING)
-       {
-               KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, 
NULL);
-               Status = IoStatus.Status;
-       }
-       if (!NT_SUCCESS(Status))
-               goto cleanup;
-
-       DeviceExtension->BusInterface = BusInterface;
-       BusInterface = NULL;
-       Status = STATUS_SUCCESS;
-
-cleanup:
-       if (BusInterface) ExFreePool(BusInterface);
-       return Status;
+    NTSTATUS Status;
+    PIO_STACK_LOCATION IoStack;
+
+    PAGED_CODE();
+
+    if (!NT_VERIFY(IoForwardIrpSynchronously(FdoExtension->Ldo, Irp)))
+    {
+        return STATUS_UNSUCCESSFUL;
+    }
+    Status = Irp->IoStatus.Status;
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    Status = PciIdeXFdoParseResources(FdoExtension,
+                                      
IoStack->Parameters.StartDevice.AllocatedResourcesTranslated);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to parse resources 0x%lx\n", Status);
+        return Status;
+    }
+
+    Status = PciIdeXStartMiniport(FdoExtension);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Miniport initialization failed 0x%lx\n", Status);
+        return Status;
+    }
+
+    return STATUS_SUCCESS;
 }
 
-static NTSTATUS
-ReleaseBusInterface(
-       IN PFDO_DEVICE_EXTENSION DeviceExtension)
+static
+CODE_SEG("PAGE")
+VOID
+PciIdeXFdoFreeResources(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension)
 {
-       NTSTATUS Status = STATUS_UNSUCCESSFUL;
+    PAGED_CODE();
 
-       if (DeviceExtension->BusInterface)
-       {
-               (*DeviceExtension->BusInterface->InterfaceDereference)(
-                       DeviceExtension->BusInterface->Context);
-               DeviceExtension->BusInterface = NULL;
-               Status = STATUS_SUCCESS;
-       }
+    if (FdoExtension->IoBaseMapped)
+    {
+        MmUnmapIoSpace(FdoExtension->BusMasterPortBase, 16);
+        FdoExtension->IoBaseMapped = FALSE;
+    }
+}
 
-       return Status;
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXFdoStopDevice(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension)
+{
+    PAGED_CODE();
+
+    PciIdeXFdoFreeResources(FdoExtension);
+
+    return STATUS_SUCCESS;
 }
 
-NTSTATUS NTAPI
-PciIdeXAddDevice(
-       IN PDRIVER_OBJECT DriverObject,
-       IN PDEVICE_OBJECT Pdo)
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXFdoRemoveDevice(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ PIRP Irp)
 {
-       PPCIIDEX_DRIVER_EXTENSION DriverExtension;
-       PFDO_DEVICE_EXTENSION DeviceExtension;
-       PDEVICE_OBJECT Fdo;
-       ULONG BytesRead;
-       PCI_COMMON_CONFIG PciConfig;
-       NTSTATUS Status;
-
-       DPRINT("PciIdeXAddDevice(%p %p)\n", DriverObject, Pdo);
-
-       DriverExtension = IoGetDriverObjectExtension(DriverObject, 
DriverObject);
-       ASSERT(DriverExtension);
-
-       Status = IoCreateDevice(
-               DriverObject,
-               sizeof(FDO_DEVICE_EXTENSION) + 
DriverExtension->MiniControllerExtensionSize,
-               NULL,
-               FILE_DEVICE_BUS_EXTENDER,
-               FILE_DEVICE_SECURE_OPEN,
-               TRUE,
-               &Fdo);
-       if (!NT_SUCCESS(Status))
-       {
-               DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
-               return Status;
-       }
-
-       DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
-       RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
-
-       DeviceExtension->Common.IsFDO = TRUE;
-
-       Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, 
&DeviceExtension->LowerDevice);
-       if (!NT_SUCCESS(Status))
-       {
-               DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 
0x%08lx\n", Status);
-               return Status;
-       }
-
-       Status = GetBusInterface(DeviceExtension);
-       if (!NT_SUCCESS(Status))
-       {
-               DPRINT("GetBusInterface() failed with status 0x%08lx\n", 
Status);
-               IoDetachDevice(DeviceExtension->LowerDevice);
-               return Status;
-       }
-
-       BytesRead = (*DeviceExtension->BusInterface->GetBusData)(
-               DeviceExtension->BusInterface->Context,
-               PCI_WHICHSPACE_CONFIG,
-               &PciConfig,
-               0,
-               PCI_COMMON_HDR_LENGTH);
-       if (BytesRead != PCI_COMMON_HDR_LENGTH)
-       {
-               DPRINT("BusInterface->GetBusData() failed()\n");
-               ReleaseBusInterface(DeviceExtension);
-               IoDetachDevice(DeviceExtension->LowerDevice);
-               return STATUS_IO_DEVICE_ERROR;
-       }
-
-       DeviceExtension->VendorId = PciConfig.VendorID;
-       DeviceExtension->DeviceId = PciConfig.DeviceID;
-
-       Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
-
-       return STATUS_SUCCESS;
+    PPDO_DEVICE_EXTENSION PdoExtension;
+    NTSTATUS Status;
+    ULONG i;
+
+    PAGED_CODE();
+
+    PciIdeXFdoFreeResources(FdoExtension);
+
+    ExAcquireFastMutex(&FdoExtension->DeviceSyncMutex);
+
+    for (i = 0; i < MAX_IDE_CHANNEL; ++i)
+    {
+        PdoExtension = FdoExtension->Channels[i];
+
+        if (PdoExtension)
+        {
+            IoDeleteDevice(PdoExtension->Common.Self);
+
+            FdoExtension->Channels[i] = NULL;
+            break;
+        }
+    }
+
+    ExReleaseFastMutex(&FdoExtension->DeviceSyncMutex);
+
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    IoSkipCurrentIrpStackLocation(Irp);
+    Status = IoCallDriver(FdoExtension->Ldo, Irp);
+
+    IoDetachDevice(FdoExtension->Ldo);
+    IoDeleteDevice(FdoExtension->Common.Self);
+
+    return Status;
 }
 
-static NTSTATUS NTAPI
-PciIdeXUdmaModesSupported(
-       IN IDENTIFY_DATA IdentifyData,
-       OUT PULONG BestXferMode,
-       OUT PULONG CurrentXferMode)
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXFdoQueryPnpDeviceState(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ PIRP Irp)
 {
-       ULONG Best = PIO_MODE0;
-       ULONG Current = PIO_MODE0;
-
-       DPRINT("PciIdeXUdmaModesSupported(%lu, %p %p)\n",
-               IdentifyData, BestXferMode, CurrentXferMode);
-
-       /* FIXME: if current mode is a PIO mode, how to get it?
-        * At the moment, PIO_MODE0 is always returned...
-        */
-
-       if (IdentifyData.TranslationFieldsValid & 0x2)
-       {
-               /* PIO modes and some DMA modes are supported */
-               if (IdentifyData.AdvancedPIOModes & 0x10)
-                       Best = PIO_MODE4;
-               else if (IdentifyData.AdvancedPIOModes & 0x8)
-                       Best = PIO_MODE3;
-               else if (IdentifyData.AdvancedPIOModes & 0x4)
-                       Best = PIO_MODE2;
-               else if (IdentifyData.AdvancedPIOModes & 0x2)
-                       Best = PIO_MODE1;
-               else if (IdentifyData.AdvancedPIOModes & 0x1)
-                       Best = PIO_MODE0;
-
-               if (IdentifyData.SingleWordDMASupport & 0x4)
-                       Best = SWDMA_MODE2;
-               else if (IdentifyData.SingleWordDMASupport & 0x2)
-                       Best = SWDMA_MODE1;
-               else if (IdentifyData.SingleWordDMASupport & 0x1)
-                       Best = SWDMA_MODE0;
-
-               if (IdentifyData.SingleWordDMAActive & 0x4)
-                       Current = SWDMA_MODE2;
-               else if (IdentifyData.SingleWordDMAActive & 0x2)
-                       Current = SWDMA_MODE1;
-               else if (IdentifyData.SingleWordDMAActive & 0x1)
-                       Current = SWDMA_MODE0;
-
-               if (IdentifyData.MultiWordDMASupport & 0x4)
-                       Best = MWDMA_MODE2;
-               else if (IdentifyData.MultiWordDMASupport & 0x2)
-                       Best = MWDMA_MODE1;
-               else if (IdentifyData.MultiWordDMASupport & 0x1)
-                       Best = MWDMA_MODE0;
-
-               if (IdentifyData.MultiWordDMAActive & 0x4)
-                       Current = MWDMA_MODE2;
-               else if (IdentifyData.MultiWordDMAActive & 0x2)
-                       Current = MWDMA_MODE1;
-               else if (IdentifyData.MultiWordDMAActive & 0x1)
-                       Current = MWDMA_MODE0;
-       }
-
-       if (IdentifyData.TranslationFieldsValid & 0x4)
-       {
-               /* UDMA modes are supported */
-               if (IdentifyData.UltraDMAActive & 0x10)
-                       Current = UDMA_MODE4;
-               else if (IdentifyData.UltraDMAActive & 0x8)
-                       Current = UDMA_MODE3;
-               else if (IdentifyData.UltraDMAActive & 0x4)
-                       Current = UDMA_MODE2;
-               else if (IdentifyData.UltraDMAActive & 0x2)
-                       Current = UDMA_MODE1;
-               else if (IdentifyData.UltraDMAActive & 0x1)
-                       Current = UDMA_MODE0;
-
-               if (IdentifyData.UltraDMASupport & 0x10)
-                       Best = UDMA_MODE4;
-               else if (IdentifyData.UltraDMASupport & 0x8)
-                       Best = UDMA_MODE3;
-               else if (IdentifyData.UltraDMASupport & 0x4)
-                       Best = UDMA_MODE2;
-               else if (IdentifyData.UltraDMASupport & 0x2)
-                       Best = UDMA_MODE1;
-               else if (IdentifyData.UltraDMASupport & 0x1)
-                       Best = UDMA_MODE0;
-       }
-
-       *BestXferMode = Best;
-       *CurrentXferMode = Current;
-       return TRUE;
+    PAGED_CODE();
+
+    if (FdoExtension->Common.PageFiles ||
+        FdoExtension->Common.HibernateFiles ||
+        FdoExtension->Common.DumpFiles)
+    {
+        Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
+    }
+
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+
+    return STATUS_SUCCESS;
 }
 
-static NTSTATUS
-PciIdeXFdoStartDevice(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp)
+static
+CODE_SEG("PAGE")
+PPDO_DEVICE_EXTENSION
+PciIdeXPdoCreateDevice(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ ULONG ChannelNumber)
 {
-       PPCIIDEX_DRIVER_EXTENSION DriverExtension;
-       PFDO_DEVICE_EXTENSION DeviceExtension;
-       PCM_RESOURCE_LIST ResourceList;
-       NTSTATUS Status;
-
-       DPRINT("PciIdeXStartDevice(%p %p)\n", DeviceObject, Irp);
-
-       DriverExtension = 
IoGetDriverObjectExtension(DeviceObject->DriverObject, 
DeviceObject->DriverObject);
-       ASSERT(DriverExtension);
-       DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-       ASSERT(DeviceExtension);
-       ASSERT(DeviceExtension->Common.IsFDO);
-
-       DeviceExtension->Properties.Size = sizeof(IDE_CONTROLLER_PROPERTIES);
-       DeviceExtension->Properties.ExtensionSize = 
DriverExtension->MiniControllerExtensionSize;
-       Status = DriverExtension->HwGetControllerProperties(
-               DeviceExtension->MiniControllerExtension,
-               &DeviceExtension->Properties);
-       if (!NT_SUCCESS(Status))
-               return Status;
-
-       DriverExtension->HwUdmaModesSupported = 
DeviceExtension->Properties.PciIdeUdmaModesSupported;
-       if (!DriverExtension->HwUdmaModesSupported)
-               /* This method is optional, so provide our own one */
-               DriverExtension->HwUdmaModesSupported = 
PciIdeXUdmaModesSupported;
-
-       /* Get bus master port base, if any */
-       ResourceList = 
IoGetCurrentIrpStackLocation(Irp)->Parameters.StartDevice.AllocatedResources;
-       if (ResourceList
-               && ResourceList->Count == 1
-               && ResourceList->List[0].PartialResourceList.Count == 1
-               && ResourceList->List[0].PartialResourceList.Version == 1
-               && ResourceList->List[0].PartialResourceList.Revision == 1
-               && 
ResourceList->List[0].PartialResourceList.PartialDescriptors[0].Type == 
CmResourceTypePort
-               && 
ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Length 
== 16)
-       {
-               DeviceExtension->BusMasterPortBase = 
ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Start;
-       }
-       return STATUS_SUCCESS;
+    NTSTATUS Status;
+    UNICODE_STRING DeviceName;
+    WCHAR DeviceNameBuffer[sizeof("\\Device\\Ide\\PciIde999Channel9-FFF")];
+    PDEVICE_OBJECT Pdo;
+    PPDO_DEVICE_EXTENSION PdoExtension;
+    ULONG Alignment;
+    static ULONG DeviceNumber = 0;
+
+    PAGED_CODE();
+
+    Status = RtlStringCbPrintfW(DeviceNameBuffer,
+                                sizeof(DeviceNameBuffer),
+                                L"\\Device\\Ide\\PciIde%uChannel%u-%x",
+                                FdoExtension->ControllerNumber,
+                                ChannelNumber,
+                                DeviceNumber++);
+    ASSERT(NT_SUCCESS(Status));
+    RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
+
+    Status = IoCreateDevice(FdoExtension->Common.Self->DriverObject,
+                            sizeof(*PdoExtension),
+                            &DeviceName,
+                            FILE_DEVICE_CONTROLLER,
+                            FILE_DEVICE_SECURE_OPEN,
+                            FALSE,
+                            &Pdo);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create PDO 0x%lx\n", Status);
+        return NULL;
+    }
+
+    DPRINT("Created device object %p '%wZ'\n", Pdo, &DeviceName);
+
+    /* DMA buffers alignment */
+    Alignment = FdoExtension->Properties.AlignmentRequirement;
+    Alignment = max(Alignment, 
FdoExtension->Common.Self->AlignmentRequirement);
+    Alignment = max(Alignment, FILE_WORD_ALIGNMENT);
+    Pdo->AlignmentRequirement = Alignment;
+
+    PdoExtension = Pdo->DeviceExtension;
+
+    RtlZeroMemory(PdoExtension, sizeof(*PdoExtension));
+    PdoExtension->Common.Self = Pdo;
+    PdoExtension->Channel = ChannelNumber;
+    PdoExtension->ParentController = FdoExtension;
+
+    Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
+    return PdoExtension;
 }
 
-static NTSTATUS
+static
+CODE_SEG("PAGE")
+NTSTATUS
 PciIdeXFdoQueryBusRelations(
-       IN PDEVICE_OBJECT DeviceObject,
-       OUT PDEVICE_RELATIONS* pDeviceRelations)
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ PIRP Irp)
 {
-       PFDO_DEVICE_EXTENSION DeviceExtension;
-       PDEVICE_RELATIONS DeviceRelations = NULL;
-       PDEVICE_OBJECT Pdo;
-       PPDO_DEVICE_EXTENSION PdoDeviceExtension;
-       ULONG i, j;
-       ULONG PDOs = 0;
-       IDE_CHANNEL_STATE ChannelState;
-       NTSTATUS Status;
-
-       DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-       ASSERT(DeviceExtension);
-       ASSERT(DeviceExtension->Common.IsFDO);
-
-       for (i = 0; i < MAX_IDE_CHANNEL; i++)
-       {
-               if (DeviceExtension->Pdo[i])
-               {
-                       PDOs++;
-                       continue;
-               }
-               ChannelState = DeviceExtension->Properties.PciIdeChannelEnabled(
-                       DeviceExtension->MiniControllerExtension, i);
-               if (ChannelState == ChannelDisabled)
-               {
-                       DPRINT("Channel %lu is disabled\n", i);
-                       continue;
-               }
-
-               /* Need to create a PDO */
-               Status = IoCreateDevice(
-                       DeviceObject->DriverObject,
-                       sizeof(PDO_DEVICE_EXTENSION),
-                       NULL,
-                       FILE_DEVICE_CONTROLLER,
-                       FILE_AUTOGENERATED_DEVICE_NAME,
-                       FALSE,
-                       &Pdo);
-               if (!NT_SUCCESS(Status))
-                       /* FIXME: handle error */
-                       continue;
-
-               PdoDeviceExtension = 
(PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension;
-               RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
-               PdoDeviceExtension->Common.IsFDO = FALSE;
-               PdoDeviceExtension->Channel = i;
-               PdoDeviceExtension->ControllerFdo = DeviceObject;
-               Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
-               Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
-
-               DeviceExtension->Pdo[i] = Pdo;
-               PDOs++;
-       }
-
-       if (PDOs == 0)
-       {
-               DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
-                       PagedPool,
-                       sizeof(DEVICE_RELATIONS));
-       }
-       else
-       {
-               DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
-                       PagedPool,
-                       sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * 
(PDOs - 1));
-       }
-       if (!DeviceRelations)
-               return STATUS_INSUFFICIENT_RESOURCES;
-
-       DeviceRelations->Count = PDOs;
-       for (i = 0, j = 0; i < MAX_IDE_CHANNEL; i++)
-       {
-               if (DeviceExtension->Pdo[i])
-               {
-                       ObReferenceObject(DeviceExtension->Pdo[i]);
-                       DeviceRelations->Objects[j++] = DeviceExtension->Pdo[i];
-               }
-       }
-
-       *pDeviceRelations = DeviceRelations;
-       return STATUS_SUCCESS;
+    PPDO_DEVICE_EXTENSION PdoExtension;
+    IDE_CHANNEL_STATE ChannelState;
+    PDEVICE_RELATIONS DeviceRelations;
+    ULONG i;
+
+    PAGED_CODE();
+
+    DeviceRelations = ExAllocatePoolWithTag(PagedPool,
+                                            FIELD_OFFSET(DEVICE_RELATIONS,
+                                                         
Objects[MAX_IDE_CHANNEL]),
+                                            TAG_PCIIDEX);
+    if (!DeviceRelations)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    DeviceRelations->Count = 0;
+
+    ExAcquireFastMutex(&FdoExtension->DeviceSyncMutex);
+
+    for (i = 0; i < MAX_IDE_CHANNEL; ++i)
+    {
+        PdoExtension = FdoExtension->Channels[i];
+
+        /* Ignore disabled channels */
+        ChannelState = PciIdeXChannelState(FdoExtension, i);
+        if (ChannelState == ChannelDisabled)
+        {
+            if (PdoExtension)
+            {
+                PdoExtension->ReportedMissing = TRUE;
+            }
+
+            DPRINT("Channel %lu is disabled\n", i);
+            continue;
+        }
+
+        /* Need to create a PDO */
+        if (!PdoExtension)
+        {
+            PdoExtension = PciIdeXPdoCreateDevice(FdoExtension, i);
+
+            FdoExtension->Channels[i] = PdoExtension;
+        }
+
+        if (PdoExtension && !PdoExtension->ReportedMissing)
+        {
+            DeviceRelations->Objects[DeviceRelations->Count++] = 
PdoExtension->Common.Self;
+            ObReferenceObject(PdoExtension->Common.Self);
+        }
+    }
+
+    ExReleaseFastMutex(&FdoExtension->DeviceSyncMutex);
+
+    Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+    return STATUS_SUCCESS;
 }
 
-NTSTATUS NTAPI
-PciIdeXFdoPnpDispatch(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp)
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXFdoQueryDeviceUsageNotification(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ PIRP Irp)
 {
-       PFDO_DEVICE_EXTENSION FdoExtension;
-       ULONG MinorFunction;
-       PIO_STACK_LOCATION Stack;
-       ULONG_PTR Information = Irp->IoStatus.Information;
-       NTSTATUS Status;
-
-       Stack = IoGetCurrentIrpStackLocation(Irp);
-       MinorFunction = Stack->MinorFunction;
-
-       switch (MinorFunction)
-       {
-               case IRP_MN_START_DEVICE: /* 0x00 */
-               {
-                       DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
-                       
-                       /* Call lower driver */
-                       FdoExtension = DeviceObject->DeviceExtension;
-                       Status = STATUS_UNSUCCESSFUL;
-
-                       if 
(IoForwardIrpSynchronously(FdoExtension->LowerDevice, Irp))
-                       {
-                               Status = Irp->IoStatus.Status;
-                               if (NT_SUCCESS(Status))
-                               {
-                                       Status = 
PciIdeXFdoStartDevice(DeviceObject, Irp);
-                               }
-                       }
-                       break;
-               }
-                case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */
-                {
-                        DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
-                        Status = STATUS_UNSUCCESSFUL;
-                        break;
-                }
-               case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
-               {
-                       switch (Stack->Parameters.QueryDeviceRelations.Type)
-                       {
-                               case BusRelations:
-                               {
-                                       PDEVICE_RELATIONS DeviceRelations = 
NULL;
-                                       DPRINT("IRP_MJ_PNP / 
IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
-                                       Status = 
PciIdeXFdoQueryBusRelations(DeviceObject, &DeviceRelations);
-                                       Information = 
(ULONG_PTR)DeviceRelations;
-                                       break;
-                               }
-                               default:
-                               {
-                                       DPRINT1("IRP_MJ_PNP / 
IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
-                                               
Stack->Parameters.QueryDeviceRelations.Type);
-                                       Status = STATUS_NOT_IMPLEMENTED;
-                                       break;
-                               }
-                       }
-                       break;
-               }
-                case IRP_MN_QUERY_PNP_DEVICE_STATE: /* 0x14 */
-                {
-                        DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
-                        Information |= PNP_DEVICE_NOT_DISABLEABLE;
-                        Status = STATUS_SUCCESS;
-                        break;
-                }
-               case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */
-               {
-                       DPRINT("IRP_MJ_PNP / 
IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
-                       return ForwardIrpAndForget(DeviceObject, Irp);
-               }
-               case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */
-               {
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
-                       return ForwardIrpAndForget(DeviceObject, Irp);
-               }
-               default:
-               {
-                       DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", 
MinorFunction);
-                       return ForwardIrpAndForget(DeviceObject, Irp);
-               }
-       }
-
-       Irp->IoStatus.Information = Information;
-       Irp->IoStatus.Status = Status;
-       IoCompleteRequest(Irp, IO_NO_INCREMENT);
-       return Status;
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+    volatile LONG* Counter;
+
+    PAGED_CODE();
+
+    if (!NT_VERIFY(IoForwardIrpSynchronously(FdoExtension->Ldo, Irp)))
+    {
+        return STATUS_UNSUCCESSFUL;
+    }
+    Status = Irp->IoStatus.Status;
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    switch (IoStack->Parameters.UsageNotification.Type)
+    {
+        case DeviceUsageTypePaging:
+            Counter = &FdoExtension->Common.PageFiles;
+            break;
+
+        case DeviceUsageTypeHibernation:
+            Counter = &FdoExtension->Common.HibernateFiles;
+            break;
+
+        case DeviceUsageTypeDumpFile:
+            Counter = &FdoExtension->Common.DumpFiles;
+            break;
+
+        default:
+            return Status;
+    }
+
+    IoAdjustPagingPathCount(Counter, 
IoStack->Parameters.UsageNotification.InPath);
+
+    return STATUS_SUCCESS;
+}
+
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXFdoQueryInterface(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ PIO_STACK_LOCATION IoStack)
+{
+    PAGED_CODE();
+
+    if (IsEqualGUIDAligned(IoStack->Parameters.QueryInterface.InterfaceType,
+                           &GUID_TRANSLATOR_INTERFACE_STANDARD))
+    {
+        CM_RESOURCE_TYPE ResourceType;
+        ULONG BusNumber;
+
+        ResourceType = 
(ULONG_PTR)IoStack->Parameters.QueryInterface.InterfaceSpecificData;
+
+        /* In native mode the IDE controller does not use any legacy interrupt 
resources */
+        if (FdoExtension->InNativeMode ||
+            ResourceType != CmResourceTypeInterrupt ||
+            IoStack->Parameters.QueryInterface.Size < 
sizeof(TRANSLATOR_INTERFACE))
+        {
+            return STATUS_NOT_SUPPORTED;
+        }
+
+        return HalGetInterruptTranslator(PCIBus,
+                                         0,
+                                         InterfaceTypeUndefined,
+                                         sizeof(TRANSLATOR_INTERFACE),
+                                         
IoStack->Parameters.QueryInterface.Version,
+                                         (PTRANSLATOR_INTERFACE)IoStack->
+                                         Parameters.QueryInterface.Interface,
+                                         &BusNumber);
+    }
+
+    return STATUS_NOT_SUPPORTED;
+}
+
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXFdoDispatchPnp(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _Inout_ PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+
+    PAGED_CODE();
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    switch (IoStack->MinorFunction)
+    {
+        case IRP_MN_START_DEVICE:
+        {
+            Status = PciIdeXFdoStartDevice(FdoExtension, Irp);
+
+            Irp->IoStatus.Status = Status;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+            return Status;
+        }
+
+        case IRP_MN_STOP_DEVICE:
+        {
+            Status = PciIdeXFdoStopDevice(FdoExtension);
+            break;
+        }
+
+        case IRP_MN_REMOVE_DEVICE:
+            return PciIdeXFdoRemoveDevice(FdoExtension, Irp);
+
+        case IRP_MN_QUERY_PNP_DEVICE_STATE:
+        {
+            Status = PciIdeXFdoQueryPnpDeviceState(FdoExtension, Irp);
+            break;
+        }
+
+        case IRP_MN_QUERY_DEVICE_RELATIONS:
+        {
+            if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
+                break;
+
+            Status = PciIdeXFdoQueryBusRelations(FdoExtension, Irp);
+            if (!NT_SUCCESS(Status))
+            {
+                Irp->IoStatus.Status = Status;
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+                return Status;
+            }
+
+            Irp->IoStatus.Status = Status;
+            break;
+        }
+
+        case IRP_MN_DEVICE_USAGE_NOTIFICATION:
+        {
+            Status = PciIdeXFdoQueryDeviceUsageNotification(FdoExtension, Irp);
+            break;
+        }
+
+        case IRP_MN_QUERY_INTERFACE:
+        {
+            Status = PciIdeXFdoQueryInterface(FdoExtension, IoStack);
+            if (Status == STATUS_NOT_SUPPORTED)
+                break;
+
+            Irp->IoStatus.Status = Status;
+            break;
+        }
+
+        case IRP_MN_QUERY_STOP_DEVICE:
+        case IRP_MN_QUERY_REMOVE_DEVICE:
+        case IRP_MN_SURPRISE_REMOVAL:
+        case IRP_MN_CANCEL_STOP_DEVICE:
+        case IRP_MN_CANCEL_REMOVE_DEVICE:
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            break;
+
+        default:
+            break;
+    }
+
+    IoSkipCurrentIrpStackLocation(Irp);
+    return IoCallDriver(FdoExtension->Ldo, Irp);
 }
diff --git a/drivers/storage/ide/pciidex/miniport.c 
b/drivers/storage/ide/pciidex/miniport.c
index c58f3d1397b..0d8ed8044fb 100644
--- a/drivers/storage/ide/pciidex/miniport.c
+++ b/drivers/storage/ide/pciidex/miniport.c
@@ -1,9 +1,8 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         PCI IDE bus driver extension
- * FILE:            drivers/storage/pciidex/miniport.c
- * PURPOSE:         Miniport functions
- * PROGRAMMERS:     Herv� Poussineau ([email protected])
+ * PROJECT:     PCI IDE bus driver extension
+ * LICENSE:     See COPYING in the top level directory
+ * PURPOSE:     Miniport functions
+ * COPYRIGHT:   Copyright 2005 Hervé Poussineau <[email protected]>
  */
 
 #include "pciidex.h"
@@ -14,83 +13,51 @@
 /** @brief Global debugging level. Valid values are between 0 (Error) and 3 
(Trace). */
 ULONG PciIdeDebug = 0;
 
-static DRIVER_DISPATCH PciIdeXForwardOrIgnore;
-static NTSTATUS NTAPI
-PciIdeXForwardOrIgnore(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp)
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXStartMiniport(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension)
 {
-       if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
-               return ForwardIrpAndForget(DeviceObject, Irp);
-       else
-       {
-               ULONG MajorFunction = 
IoGetCurrentIrpStackLocation(Irp)->MajorFunction;
-               NTSTATUS Status;
-
-               if (MajorFunction == IRP_MJ_CREATE ||
-                   MajorFunction == IRP_MJ_CLEANUP ||
-                   MajorFunction == IRP_MJ_CLOSE)
-               {
-                       Status = STATUS_SUCCESS;
-               }
-               else
-               {
-                       DPRINT1("PDO stub for major function 0x%lx\n", 
MajorFunction);
-                       Status = STATUS_NOT_SUPPORTED;
-               }
-               Irp->IoStatus.Information = 0;
-               Irp->IoStatus.Status = Status;
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-               return Status;
-       }
-}
+    PPCIIDEX_DRIVER_EXTENSION DriverExtension;
+    NTSTATUS Status;
 
-_Dispatch_type_(IRP_MJ_POWER)
-static DRIVER_DISPATCH PciIdeXPowerDispatch;
-static NTSTATUS NTAPI
-PciIdeXPowerDispatch(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp)
-{
-       NTSTATUS Status;
-       PIO_STACK_LOCATION IoStack;
-       PDEVICE_OBJECT LowerDevice;
-
-       IoStack = IoGetCurrentIrpStackLocation(Irp);
-       if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
-       {
-               LowerDevice = 
((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
-               PoStartNextPowerIrp(Irp);
-               IoSkipCurrentIrpStackLocation(Irp);
-               return PoCallDriver(LowerDevice, Irp);
-       }
-       else
-       {
-               switch (IoStack->MinorFunction)
-               {
-                       case IRP_MN_SET_POWER:
-                       case IRP_MN_QUERY_POWER:
-                               Irp->IoStatus.Status = STATUS_SUCCESS;
-                               break;
-               }
-               Status = Irp->IoStatus.Status;
-               PoStartNextPowerIrp(Irp);
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-               return Status;
-       }
+    PAGED_CODE();
+
+    if (FdoExtension->MiniportStarted)
+        return STATUS_SUCCESS;
+
+    DPRINT("Starting miniport\n");
+
+    DriverExtension = IoGetDriverObjectExtension(FdoExtension->DriverObject,
+                                                 FdoExtension->DriverObject);
+    ASSERT(DriverExtension);
+
+    FdoExtension->Properties.Size = sizeof(IDE_CONTROLLER_PROPERTIES);
+    FdoExtension->Properties.ExtensionSize = 
DriverExtension->MiniControllerExtensionSize;
+    Status = 
DriverExtension->HwGetControllerProperties(FdoExtension->MiniControllerExtension,
+                                                        
&FdoExtension->Properties);
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    FdoExtension->MiniportStarted = TRUE;
+    return STATUS_SUCCESS;
 }
 
-_Dispatch_type_(IRP_MJ_PNP)
-static DRIVER_DISPATCH PciIdeXPnpDispatch;
-static NTSTATUS NTAPI
-PciIdeXPnpDispatch(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp)
+CODE_SEG("PAGE")
+IDE_CHANNEL_STATE
+PciIdeXChannelState(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ ULONG Channel)
 {
-       if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
-               return PciIdeXFdoPnpDispatch(DeviceObject, Irp);
-       else
-               return PciIdeXPdoPnpDispatch(DeviceObject, Irp);
+    PCIIDE_CHANNEL_ENABLED MiniportChannelEnabled;
+
+    PAGED_CODE();
+
+    MiniportChannelEnabled = FdoExtension->Properties.PciIdeChannelEnabled;
+    if (MiniportChannelEnabled)
+        return MiniportChannelEnabled(FdoExtension->MiniControllerExtension, 
Channel);
+
+    return ChannelStateUnknown;
 }
 
 /**
@@ -119,122 +86,88 @@ PciIdeXDebugPrint(
     va_end(ap);
 }
 
-NTSTATUS NTAPI
-PciIdeXInitialize(
-       IN PDRIVER_OBJECT DriverObject,
-       IN PUNICODE_STRING RegistryPath,
-       IN PCONTROLLER_PROPERTIES HwGetControllerProperties,
-       IN ULONG ExtensionSize)
-{
-       ULONG i;
-       PPCIIDEX_DRIVER_EXTENSION DriverExtension;
-       NTSTATUS Status;
-
-       DPRINT("PciIdeXInitialize(%p '%wZ' %p 0x%lx)\n",
-               DriverObject, RegistryPath, HwGetControllerProperties, 
ExtensionSize);
-
-       Status = IoAllocateDriverObjectExtension(
-               DriverObject,
-               DriverObject,
-               sizeof(PCIIDEX_DRIVER_EXTENSION),
-               (PVOID*)&DriverExtension);
-       if (!NT_SUCCESS(Status))
-               return Status;
-       RtlZeroMemory(DriverExtension, sizeof(PCIIDEX_DRIVER_EXTENSION));
-       DriverExtension->MiniControllerExtensionSize = ExtensionSize;
-       DriverExtension->HwGetControllerProperties = HwGetControllerProperties;
-
-       DriverObject->DriverExtension->AddDevice = PciIdeXAddDevice;
-
-       for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
-               DriverObject->MajorFunction[i] = PciIdeXForwardOrIgnore;
-       DriverObject->MajorFunction[IRP_MJ_POWER] = PciIdeXPowerDispatch;
-       DriverObject->MajorFunction[IRP_MJ_PNP] = PciIdeXPnpDispatch;
-
-       return STATUS_SUCCESS;
-}
-
 /* May be called at IRQL <= DISPATCH_LEVEL */
-NTSTATUS NTAPI
+NTSTATUS
+NTAPI
 PciIdeXGetBusData(
-       IN PVOID DeviceExtension,
-       IN PVOID Buffer,
-       IN ULONG ConfigDataOffset,
-       IN ULONG BufferLength)
+    _In_ PVOID DeviceExtension,
+    _Out_writes_bytes_all_(BufferLength) PVOID Buffer,
+    _In_ ULONG ConfigDataOffset,
+    _In_ ULONG BufferLength)
 {
-       PFDO_DEVICE_EXTENSION FdoDeviceExtension;
-       ULONG BytesRead;
-       NTSTATUS Status = STATUS_UNSUCCESSFUL;
-
-       DPRINT("PciIdeXGetBusData(%p %p 0x%lx 0x%lx)\n",
-               DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
-
-       FdoDeviceExtension = CONTAINING_RECORD(DeviceExtension, 
FDO_DEVICE_EXTENSION, MiniControllerExtension);
-       if (FdoDeviceExtension->BusInterface)
-       {
-               BytesRead = (*FdoDeviceExtension->BusInterface->GetBusData)(
-                       FdoDeviceExtension->BusInterface->Context,
-                       PCI_WHICHSPACE_CONFIG,
-                       Buffer,
-                       ConfigDataOffset,
-                       BufferLength);
-               if (BytesRead == BufferLength)
-                       Status = STATUS_SUCCESS;
-       }
-
-       return Status;
+    PFDO_DEVICE_EXTENSION FdoExtension;
+    ULONG BytesRead;
+
+    DPRINT("PciIdeXGetBusData(%p %p 0x%lx 0x%lx)\n",
+           DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
+
+    FdoExtension = CONTAINING_RECORD(DeviceExtension,
+                                     FDO_DEVICE_EXTENSION,
+                                     MiniControllerExtension);
+
+    BytesRead = 
(*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context,
+                                                         PCI_WHICHSPACE_CONFIG,
+                                                         Buffer,
+                                                         ConfigDataOffset,
+                                                         BufferLength);
+    if (BytesRead != BufferLength)
+        return STATUS_UNSUCCESSFUL;
+
+    return STATUS_SUCCESS;
 }
 
 /* May be called at IRQL <= DISPATCH_LEVEL */
-NTSTATUS NTAPI
+NTSTATUS
+NTAPI
 PciIdeXSetBusData(
-       IN PVOID DeviceExtension,
-       IN PVOID Buffer,
-       IN PVOID DataMask,
-       IN ULONG ConfigDataOffset,
-       IN ULONG BufferLength)
+    _In_ PVOID DeviceExtension,
+    _In_reads_bytes_(BufferLength) PVOID Buffer,
+    _In_reads_bytes_(BufferLength) PVOID DataMask,
+    _In_ ULONG ConfigDataOffset,
+    _In_ ULONG BufferLength)
 {
-       PFDO_DEVICE_EXTENSION FdoDeviceExtension;
-       PUCHAR CurrentBuffer = NULL;
-       ULONG i, BytesWritten;
-       NTSTATUS Status;
-
-       DPRINT("PciIdeXSetBusData(%p %p %p 0x%lx 0x%lx)\n",
-               DeviceExtension, Buffer, DataMask, ConfigDataOffset, 
BufferLength);
-
-       CurrentBuffer = ExAllocatePool(NonPagedPool, BufferLength);
-       if (!CurrentBuffer)
-       {
-               Status = STATUS_INSUFFICIENT_RESOURCES;
-               return Status;
-       }
-
-       Status = PciIdeXGetBusData(DeviceExtension, Buffer, ConfigDataOffset, 
BufferLength);
-       if (!NT_SUCCESS(Status))
-               goto cleanup;
-
-       for (i = 0; i < BufferLength; i++)
-               CurrentBuffer[i] = (CurrentBuffer[i] & ~((PUCHAR)DataMask)[i]) 
| (((PUCHAR)DataMask)[i] & ((PUCHAR)Buffer)[i]);
-
-       FdoDeviceExtension = CONTAINING_RECORD(DeviceExtension, 
FDO_DEVICE_EXTENSION, MiniControllerExtension);
-       if (!FdoDeviceExtension->BusInterface)
-       {
-               Status = STATUS_UNSUCCESSFUL;
-               goto cleanup;
-       }
-
-       BytesWritten = (*FdoDeviceExtension->BusInterface->SetBusData)(
-               FdoDeviceExtension->BusInterface->Context,
-               PCI_WHICHSPACE_CONFIG,
-               CurrentBuffer,
-               ConfigDataOffset,
-               BufferLength);
-       if (BytesWritten == BufferLength)
-               Status = STATUS_SUCCESS;
-       else
-               Status = STATUS_UNSUCCESSFUL;
-
-cleanup:
-       ExFreePool(CurrentBuffer);
-       return Status;
+    PFDO_DEVICE_EXTENSION FdoExtension;
+    ULONG i, BytesWritten;
+    PUCHAR CurrentBuffer;
+    KIRQL OldIrql;
+    NTSTATUS Status;
+
+    DPRINT("PciIdeXSetBusData(%p %p %p 0x%lx 0x%lx)\n",
+           DeviceExtension, Buffer, DataMask, ConfigDataOffset, BufferLength);
+
+    CurrentBuffer = ExAllocatePoolWithTag(NonPagedPool, BufferLength, 
TAG_PCIIDEX);
+    if (!CurrentBuffer)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    FdoExtension = CONTAINING_RECORD(DeviceExtension,
+                                     FDO_DEVICE_EXTENSION,
+                                     MiniControllerExtension);
+
+    KeAcquireSpinLock(&FdoExtension->BusDataLock, &OldIrql);
+
+    Status = PciIdeXGetBusData(DeviceExtension, Buffer, ConfigDataOffset, 
BufferLength);
+    if (!NT_SUCCESS(Status))
+        goto Cleanup;
+
+    for (i = 0; i < BufferLength; i++)
+    {
+        CurrentBuffer[i] = (CurrentBuffer[i] & ~((PUCHAR)DataMask)[i]) |
+                           (((PUCHAR)DataMask)[i] & ((PUCHAR)Buffer)[i]);
+    }
+
+    BytesWritten = 
(*FdoExtension->BusInterface.SetBusData)(FdoExtension->BusInterface.Context,
+                                                         PCI_WHICHSPACE_CONFIG,
+                                                         CurrentBuffer,
+                                                         ConfigDataOffset,
+                                                         BufferLength);
+    if (BytesWritten != BufferLength)
+        Status = STATUS_UNSUCCESSFUL;
+    else
+        Status = STATUS_SUCCESS;
+
+Cleanup:
+    KeReleaseSpinLock(&FdoExtension->BusDataLock, OldIrql);
+
+    ExFreePoolWithTag(CurrentBuffer, TAG_PCIIDEX);
+    return Status;
 }
diff --git a/drivers/storage/ide/pciidex/misc.c 
b/drivers/storage/ide/pciidex/misc.c
deleted file mode 100644
index 46ebf5d3847..00000000000
--- a/drivers/storage/ide/pciidex/misc.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         PCI IDE bus driver extension
- * FILE:            drivers/storage/pciidex/misc.c
- * PURPOSE:         Miscellaneous operations
- * PROGRAMMERS:     Herv� Poussineau ([email protected])
- */
-
-#include "pciidex.h"
-
-#define NDEBUG
-#include <debug.h>
-
-
-NTSTATUS NTAPI
-ForwardIrpAndForget(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp)
-{
-       PDEVICE_OBJECT LowerDevice;
-
-       
ASSERT(((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO);
-       LowerDevice = 
((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
-       ASSERT(LowerDevice);
-
-       IoSkipCurrentIrpStackLocation(Irp);
-       return IoCallDriver(LowerDevice, Irp);
-}
-
-NTSTATUS
-DuplicateUnicodeString(
-       IN ULONG Flags,
-       IN PCUNICODE_STRING SourceString,
-       OUT PUNICODE_STRING DestinationString)
-{
-       if (SourceString == NULL || DestinationString == NULL
-        || SourceString->Length > SourceString->MaximumLength
-        || (SourceString->Length == 0 && SourceString->MaximumLength > 0 && 
SourceString->Buffer == NULL)
-        || Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || Flags 
>= 4)
-       {
-               return STATUS_INVALID_PARAMETER;
-       }
-
-
-       if ((SourceString->Length == 0)
-        && (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE |
-                      RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING)))
-       {
-               DestinationString->Length = 0;
-               DestinationString->MaximumLength = 0;
-               DestinationString->Buffer = NULL;
-       }
-       else
-       {
-               USHORT DestMaxLength = SourceString->Length;
-
-               if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
-                       DestMaxLength += sizeof(UNICODE_NULL);
-
-               DestinationString->Buffer = ExAllocatePool(PagedPool, 
DestMaxLength);
-               if (DestinationString->Buffer == NULL)
-                       return STATUS_NO_MEMORY;
-
-               RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, 
SourceString->Length);
-               DestinationString->Length = SourceString->Length;
-               DestinationString->MaximumLength = DestMaxLength;
-
-               if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
-                       DestinationString->Buffer[DestinationString->Length / 
sizeof(WCHAR)] = 0;
-       }
-
-       return STATUS_SUCCESS;
-}
diff --git a/drivers/storage/ide/pciidex/pciidex.c 
b/drivers/storage/ide/pciidex/pciidex.c
index c080aa43a84..9f4bdb9768f 100644
--- a/drivers/storage/ide/pciidex/pciidex.c
+++ b/drivers/storage/ide/pciidex/pciidex.c
@@ -1,9 +1,8 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         PCI IDE bus driver extension
- * FILE:            drivers/storage/pciidex/pciidex.c
- * PURPOSE:         Main file
- * PROGRAMMERS:     Herv� Poussineau ([email protected])
+ * PROJECT:     PCI IDE bus driver extension
+ * LICENSE:     See COPYING in the top level directory
+ * PURPOSE:     Main file
+ * COPYRIGHT:   Copyright 2005 Hervé Poussineau <[email protected]>
  */
 
 #include "pciidex.h"
@@ -11,10 +10,330 @@
 #define NDEBUG
 #include <debug.h>
 
-NTSTATUS NTAPI
+ULONG PciIdeControllerNumber = 0;
+
+CODE_SEG("PAGE")
+NTSTATUS
+NTAPI
+PciIdeXDispatchWmi(
+    _In_ PDEVICE_OBJECT DeviceObject,
+    _Inout_ PIRP Irp)
+{
+    NTSTATUS Status;
+
+    PAGED_CODE();
+
+    if (IS_FDO(DeviceObject->DeviceExtension))
+    {
+        PFDO_DEVICE_EXTENSION FdoExtension = DeviceObject->DeviceExtension;
+
+        IoSkipCurrentIrpStackLocation(Irp);
+        Status = IoCallDriver(FdoExtension->Ldo, Irp);
+    }
+    else
+    {
+        Status = Irp->IoStatus.Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
+
+    return Status;
+}
+
+CODE_SEG("PAGE")
+VOID
+NTAPI
+PciIdeXUnload(
+    _In_ PDRIVER_OBJECT DriverObject)
+{
+    UNREFERENCED_PARAMETER(DriverObject);
+
+    PAGED_CODE();
+
+    NOTHING;
+}
+
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXQueryInterface(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ const GUID* Guid,
+    _Out_ PVOID Interface,
+    _In_ ULONG Size)
+{
+    KEVENT Event;
+    IO_STATUS_BLOCK IoStatus;
+    PIRP Irp;
+    PIO_STACK_LOCATION Stack;
+    NTSTATUS Status;
+
+    PAGED_CODE();
+
+    KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+                                       FdoExtension->Ldo,
+                                       NULL,
+                                       0,
+                                       NULL,
+                                       &Event,
+                                       &IoStatus);
+    if (!Irp)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+    Irp->IoStatus.Information = 0;
+
+    Stack = IoGetNextIrpStackLocation(Irp);
+    Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
+    Stack->Parameters.QueryInterface.InterfaceType = Guid;
+    Stack->Parameters.QueryInterface.Version = 1;
+    Stack->Parameters.QueryInterface.Size = Size;
+    Stack->Parameters.QueryInterface.Interface = Interface;
+    Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
+
+    Status = IoCallDriver(FdoExtension->Ldo, Irp);
+    if (Status == STATUS_PENDING)
+    {
+        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+        Status = IoStatus.Status;
+    }
+
+    return Status;
+}
+
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXGetConfigurationInfo(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension)
+{
+    UCHAR Buffer[RTL_SIZEOF_THROUGH_FIELD(PCI_COMMON_HEADER, BaseClass)];
+    PPCI_COMMON_HEADER PciConfig = (PPCI_COMMON_HEADER)Buffer;
+    ULONG BytesRead;
+
+    PAGED_CODE();
+
+    BytesRead = 
(*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context,
+                                                         PCI_WHICHSPACE_CONFIG,
+                                                         Buffer,
+                                                         0,
+                                                         sizeof(Buffer));
+    if (BytesRead != sizeof(Buffer))
+        return STATUS_IO_DEVICE_ERROR;
+
+    FdoExtension->VendorId = PciConfig->VendorID;
+    FdoExtension->DeviceId = PciConfig->DeviceID;
+
+    if (PciConfig->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR)
+    {
+        if (PciConfig->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR)
+        {
+            /* Both IDE channels in native mode */
+            FdoExtension->InNativeMode =
+                (PciConfig->ProgIf & 
PCIIDE_PROGIF_PRIMARY_CHANNEL_NATIVE_MODE) &&
+                (PciConfig->ProgIf & 
PCIIDE_PROGIF_SECONDARY_CHANNEL_NATIVE_MODE);
+        }
+        else if (PciConfig->SubClass == PCI_SUBCLASS_MSC_RAID_CTLR)
+        {
+            FdoExtension->InNativeMode = TRUE;
+        }
+    }
+
+    DPRINT("Controller %04x:%04x, Interface byte 0x%02x, Native mode %d\n",
+           FdoExtension->VendorId,
+           FdoExtension->DeviceId,
+           PciConfig->ProgIf,
+           FdoExtension->InNativeMode);
+
+    return STATUS_SUCCESS;
+}
+
+CODE_SEG("PAGE")
+NTSTATUS
+NTAPI
+PciIdeXAddDevice(
+    _In_ PDRIVER_OBJECT DriverObject,
+    _In_ PDEVICE_OBJECT PhysicalDeviceObject)
+{
+    PPCIIDEX_DRIVER_EXTENSION DriverExtension;
+    PFDO_DEVICE_EXTENSION FdoExtension;
+    ULONG DeviceExtensionSize;
+    PDEVICE_OBJECT Fdo;
+    UNICODE_STRING DeviceName;
+    WCHAR DeviceNameBuffer[sizeof("\\Device\\Ide\\PciIde999")];
+    NTSTATUS Status;
+
+    PAGED_CODE();
+
+    Status = RtlStringCbPrintfW(DeviceNameBuffer,
+                                sizeof(DeviceNameBuffer),
+                                L"\\Device\\Ide\\PciIde%u",
+                                PciIdeControllerNumber);
+    ASSERT(NT_SUCCESS(Status));
+    RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
+
+    DPRINT("%s(%p, %p) '%wZ'\n", __FUNCTION__, DriverObject, 
PhysicalDeviceObject, &DeviceName);
+
+    DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
+    ASSERT(DriverExtension);
+
+    Status = RtlULongAdd(DriverExtension->MiniControllerExtensionSize,
+                         sizeof(FDO_DEVICE_EXTENSION),
+                         &DeviceExtensionSize);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Invalid miniport extension size %lx\n",
+                DriverExtension->MiniControllerExtensionSize);
+        return Status;
+    }
+
+    Status = IoCreateDevice(DriverObject,
+                            DeviceExtensionSize,
+                            &DeviceName,
+                            FILE_DEVICE_BUS_EXTENDER,
+                            FILE_DEVICE_SECURE_OPEN,
+                            FALSE,
+                            &Fdo);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create FDO 0x%lx\n", Status);
+        return Status;
+    }
+
+    FdoExtension = Fdo->DeviceExtension;
+
+    RtlZeroMemory(FdoExtension, sizeof(FDO_DEVICE_EXTENSION));
+    FdoExtension->Common.IsFDO = TRUE;
+    FdoExtension->Common.Self = Fdo;
+    FdoExtension->DriverObject = DriverObject;
+    FdoExtension->ControllerNumber = PciIdeControllerNumber++;
+
+    KeInitializeSpinLock(&FdoExtension->BusDataLock);
+    ExInitializeFastMutex(&FdoExtension->DeviceSyncMutex);
+
+    Status = IoAttachDeviceToDeviceStackSafe(Fdo, PhysicalDeviceObject, 
&FdoExtension->Ldo);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("Failed to attach FDO 0x%lx\n", Status);
+        goto Failure;
+    }
+
+    /* DMA buffers alignment */
+    Fdo->AlignmentRequirement = max(FdoExtension->Ldo->AlignmentRequirement, 
FILE_WORD_ALIGNMENT);
+
+    Status = PciIdeXQueryInterface(FdoExtension,
+                                   &GUID_BUS_INTERFACE_STANDARD,
+                                   &FdoExtension->BusInterface,
+                                   sizeof(BUS_INTERFACE_STANDARD));
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("No bus interface 0x%lx\n", Status);
+        goto Failure;
+    }
+
+    Status = PciIdeXGetConfigurationInfo(FdoExtension);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Unable to retrieve the configuration info %lx\n", Status);
+        goto Failure;
+    }
+
+    Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+
+    return STATUS_SUCCESS;
+
+Failure:
+    if (FdoExtension->Ldo)
+        IoDetachDevice(FdoExtension->Ldo);
+
+    IoDeleteDevice(Fdo);
+
+    return Status;
+}
+
+static
+CODE_SEG("PAGE")
+VOID
+PciIdeXCreateIdeDirectory(VOID)
+{
+    HANDLE Handle;
+    NTSTATUS Status;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING DirectoryName = RTL_CONSTANT_STRING(L"\\Device\\Ide");
+
+    PAGED_CODE();
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &DirectoryName,
+                               OBJ_CASE_INSENSITIVE | OBJ_PERMANENT | 
OBJ_KERNEL_HANDLE,
+                               NULL,
+                               NULL);
+
+    Status = ZwCreateDirectoryObject(&Handle, DIRECTORY_ALL_ACCESS, 
&ObjectAttributes);
+    if (NT_SUCCESS(Status))
+    {
+        /* We don't need a handle for a permanent object */
+        ZwClose(Handle);
+    }
+    /*
+     * Ignore directory creation failures (don't report them as a driver 
initialization error)
+     * as the directory may have already been created by another driver.
+     * We will handle fatal errors later via IoCreateDevice() call.
+     */
+}
+
+CODE_SEG("PAGE")
+NTSTATUS
+NTAPI
+PciIdeXInitialize(
+    _In_ PDRIVER_OBJECT DriverObject,
+    _In_ PUNICODE_STRING RegistryPath,
+    _In_ PCONTROLLER_PROPERTIES HwGetControllerProperties,
+    _In_ ULONG ExtensionSize)
+{
+    PPCIIDEX_DRIVER_EXTENSION DriverExtension;
+    NTSTATUS Status;
+
+    PAGED_CODE();
+
+    DPRINT("PciIdeXInitialize(%p '%wZ' %p 0x%lx)\n",
+           DriverObject, RegistryPath, HwGetControllerProperties, 
ExtensionSize);
+
+    Status = IoAllocateDriverObjectExtension(DriverObject,
+                                             DriverObject,
+                                             sizeof(PCIIDEX_DRIVER_EXTENSION),
+                                             (PVOID*)&DriverExtension);
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    RtlZeroMemory(DriverExtension, sizeof(PCIIDEX_DRIVER_EXTENSION));
+    DriverExtension->MiniControllerExtensionSize = ExtensionSize;
+    DriverExtension->HwGetControllerProperties = HwGetControllerProperties;
+
+    DriverObject->MajorFunction[IRP_MJ_PNP] = PciIdeXDispatchPnp;
+    DriverObject->MajorFunction[IRP_MJ_POWER] = PciIdeXDispatchPower;
+    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = PciIdeXDispatchWmi;
+    DriverObject->DriverExtension->AddDevice = PciIdeXAddDevice;
+    DriverObject->DriverUnload = PciIdeXUnload;
+
+    /* Create a directory to hold the driver's device objects */
+    PciIdeXCreateIdeDirectory();
+
+    return STATUS_SUCCESS;
+}
+
+CODE_SEG("PAGE") /* This function is too small to be placed into INIT section 
*/
+NTSTATUS
+NTAPI
 DriverEntry(
-       IN PDRIVER_OBJECT DriverObject,
-       IN PUNICODE_STRING RegistryPath)
+    _In_ PDRIVER_OBJECT DriverObject,
+    _In_ PUNICODE_STRING RegistryPath)
 {
-       return STATUS_SUCCESS;
+    UNREFERENCED_PARAMETER(DriverObject);
+    UNREFERENCED_PARAMETER(RegistryPath);
+
+    PAGED_CODE();
+
+    return STATUS_SUCCESS;
 }
diff --git a/drivers/storage/ide/pciidex/pciidex.h 
b/drivers/storage/ide/pciidex/pciidex.h
index 4dde936a44f..2a546d61a8a 100644
--- a/drivers/storage/ide/pciidex/pciidex.h
+++ b/drivers/storage/ide/pciidex/pciidex.h
@@ -1,74 +1,146 @@
+/*
+ * PROJECT:     PCI IDE bus driver extension
+ * LICENSE:     See COPYING in the top level directory
+ * PURPOSE:     Common header file
+ * COPYRIGHT:   Copyright 2005 Hervé Poussineau <[email protected]>
+ *              Copyright 2023 Dmitry Borisov <[email protected]>
+ */
+
 #ifndef _PCIIDEX_PCH_
 #define _PCIIDEX_PCH_
 
-#include <ntifs.h>
+#include <ntddk.h>
+#include <ntstrsafe.h>
+#include <ntintsafe.h>
+#include <initguid.h>
+#include <wdmguid.h>
 #include <ide.h>
 
+#define TAG_PCIIDEX    'XedI'
+
+#define IS_FDO(p)    (((PCOMMON_DEVICE_EXTENSION)(p))->IsFDO)
+
+#define IS_PRIMARY_CHANNEL(PdoExtension)    (PdoExtension->Channel == 0)
+
+/*
+ * Legacy ranges and interrupts
+ */
+#define PCIIDE_LEGACY_RESOURCE_COUNT                3
+#define PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH       8
+#define PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH       1
+#define PCIIDE_LEGACY_PRIMARY_COMMAND_BASE      0x1F0
+#define PCIIDE_LEGACY_PRIMARY_CONTROL_BASE      0x3F6
+#define PCIIDE_LEGACY_PRIMARY_IRQ                  14
+#define PCIIDE_LEGACY_SECONDARY_COMMAND_BASE    0x170
+#define PCIIDE_LEGACY_SECONDARY_CONTROL_BASE    0x376
+#define PCIIDE_LEGACY_SECONDARY_IRQ                15
+
+/*
+ * Programming Interface Register
+ */
+#define PCIIDE_PROGIF_PRIMARY_CHANNEL_NATIVE_MODE              0x01
+#define PCIIDE_PROGIF_PRIMARY_CHANNEL_NATIVE_MODE_CAPABLE      0x02
+#define PCIIDE_PROGIF_SECONDARY_CHANNEL_NATIVE_MODE            0x04
+#define PCIIDE_PROGIF_SECONDARY_CHANNEL_NATIVE_MODE_CAPABLE    0x08
+#define PCIIDE_PROGIF_DMA_CAPABLE                              0x80
+
+#define BM_SECONDARY_CHANNEL_OFFSET      8
+
+typedef struct _PDO_DEVICE_EXTENSION    PDO_DEVICE_EXTENSION, 
*PPDO_DEVICE_EXTENSION;
+
 typedef struct _PCIIDEX_DRIVER_EXTENSION
 {
-       PCONTROLLER_PROPERTIES HwGetControllerProperties;
-       ULONG MiniControllerExtensionSize;
-       PCIIDE_UDMA_MODES_SUPPORTED HwUdmaModesSupported;
+    PCONTROLLER_PROPERTIES HwGetControllerProperties;
+    ULONG MiniControllerExtensionSize;
 } PCIIDEX_DRIVER_EXTENSION, *PPCIIDEX_DRIVER_EXTENSION;
 
 typedef struct _COMMON_DEVICE_EXTENSION
 {
-       BOOLEAN IsFDO;
+    BOOLEAN IsFDO;
+    PDEVICE_OBJECT Self;
+
+    _Write_guarded_by_(_Global_interlock_)
+    volatile LONG PageFiles;
+
+    _Write_guarded_by_(_Global_interlock_)
+    volatile LONG HibernateFiles;
+
+    _Write_guarded_by_(_Global_interlock_)
+    volatile LONG DumpFiles;
 } COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
 
 typedef struct _FDO_DEVICE_EXTENSION
 {
-       COMMON_DEVICE_EXTENSION Common;
-
-       PBUS_INTERFACE_STANDARD BusInterface;
-       IDE_CONTROLLER_PROPERTIES Properties;
-       PHYSICAL_ADDRESS BusMasterPortBase;
-       PDEVICE_OBJECT LowerDevice;
-       PDEVICE_OBJECT Pdo[MAX_IDE_CHANNEL];
-       USHORT VendorId;
-       USHORT DeviceId;
-       PUCHAR MiniControllerExtension[0];
+    COMMON_DEVICE_EXTENSION Common;
+    PDEVICE_OBJECT Ldo;
+
+    ULONG ControllerNumber;
+    BOOLEAN InNativeMode;
+    BOOLEAN IoBaseMapped;
+    BOOLEAN MiniportStarted;
+
+    FAST_MUTEX DeviceSyncMutex;
+    _Guarded_by_(DeviceSyncMutex)
+    PPDO_DEVICE_EXTENSION Channels[MAX_IDE_CHANNEL];
+
+    USHORT VendorId;
+    USHORT DeviceId;
+    PDRIVER_OBJECT DriverObject;
+    PUCHAR BusMasterPortBase;
+
+    KSPIN_LOCK BusDataLock;
+    BUS_INTERFACE_STANDARD BusInterface;
+
+    IDE_CONTROLLER_PROPERTIES Properties;
+
+    /* Must be the last entry */
+    PUCHAR MiniControllerExtension[0];
 } FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
 
 typedef struct _PDO_DEVICE_EXTENSION
 {
-       COMMON_DEVICE_EXTENSION Common;
-
-       ULONG Channel;
-       PDEVICE_OBJECT ControllerFdo;
+    COMMON_DEVICE_EXTENSION Common;
+    ULONG Channel;
+    PFDO_DEVICE_EXTENSION ParentController;
+    BOOLEAN ReportedMissing;
+    PUCHAR IoBase;
 } PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
 
-/* fdo.c */
+CODE_SEG("PAGE")
+DRIVER_INITIALIZE DriverEntry;
+
+CODE_SEG("PAGE")
+DRIVER_UNLOAD PciIdeXUnload;
 
+CODE_SEG("PAGE")
 DRIVER_ADD_DEVICE PciIdeXAddDevice;
-NTSTATUS NTAPI
-PciIdeXAddDevice(
-       IN PDRIVER_OBJECT DriverObject,
-       IN PDEVICE_OBJECT Pdo);
 
-NTSTATUS NTAPI
-PciIdeXFdoPnpDispatch(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp);
+_Dispatch_type_(IRP_MJ_PNP)
+CODE_SEG("PAGE")
+DRIVER_DISPATCH_PAGED PciIdeXDispatchPnp;
 
-/* misc.c */
+_Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
+CODE_SEG("PAGE")
+DRIVER_DISPATCH_PAGED PciIdeXDispatchWmi;
 
-NTSTATUS NTAPI
-ForwardIrpAndForget(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp);
+_Dispatch_type_(IRP_MJ_POWER)
+DRIVER_DISPATCH_RAISED PciIdeXDispatchPower;
 
+CODE_SEG("PAGE")
 NTSTATUS
-DuplicateUnicodeString(
-       IN ULONG Flags,
-       IN PCUNICODE_STRING SourceString,
-       OUT PUNICODE_STRING DestinationString);
+PciIdeXFdoDispatchPnp(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _Inout_ PIRP Irp);
 
-/* pdo.c */
-
-NTSTATUS NTAPI
-PciIdeXPdoPnpDispatch(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp);
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXStartMiniport(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension);
+
+CODE_SEG("PAGE")
+IDE_CHANNEL_STATE
+PciIdeXChannelState(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ ULONG Channel);
 
 #endif /* _PCIIDEX_PCH_ */
diff --git a/drivers/storage/ide/pciidex/pdo.c 
b/drivers/storage/ide/pciidex/pdo.c
index 7289cd44001..780d52891ba 100644
--- a/drivers/storage/ide/pciidex/pdo.c
+++ b/drivers/storage/ide/pciidex/pdo.c
@@ -1,537 +1,850 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         PCI IDE bus driver extension
- * FILE:            drivers/storage/pciidex/pdo.c
- * PURPOSE:         IRP_MJ_PNP operations for PDOs
- * PROGRAMMERS:     Herv� Poussineau ([email protected])
+ * PROJECT:     PCI IDE bus driver extension
+ * LICENSE:     See COPYING in the top level directory
+ * PURPOSE:     IRP_MJ_PNP operations for PDOs
+ * COPYRIGHT:   Copyright 2005 Hervé Poussineau <[email protected]>
+ *              Copyright 2023 Dmitry Borisov <[email protected]>
  */
 
 #include "pciidex.h"
 
-#include <stdio.h>
-
 #define NDEBUG
 #include <debug.h>
 
-static NTSTATUS
-PciIdeXPdoQueryId(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp,
-       OUT ULONG_PTR* Information)
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXPdoStartDevice(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _In_ PCM_RESOURCE_LIST ResourceList)
+{
+    PUCHAR IoBase;
+
+    PAGED_CODE();
+
+    IoBase = PdoExtension->ParentController->BusMasterPortBase;
+    if (!IS_PRIMARY_CHANNEL(PdoExtension))
+    {
+        IoBase += BM_SECONDARY_CHANNEL_OFFSET;
+    }
+    DPRINT("Bus Master Base %p\n", IoBase);
+
+    return STATUS_SUCCESS;
+}
+
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXPdoStopDevice(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension)
+{
+    PAGED_CODE();
+
+    return STATUS_SUCCESS;
+}
+
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXPdoRemoveDevice(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _In_ BOOLEAN FinalRemove)
 {
-       PPDO_DEVICE_EXTENSION DeviceExtension;
-       PFDO_DEVICE_EXTENSION FdoDeviceExtension;
-       WCHAR Buffer[256];
-       ULONG Index = 0;
-       ULONG IdType;
-       UNICODE_STRING SourceString;
-       UNICODE_STRING String;
-       NTSTATUS Status;
-
-       IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
-       DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-       FdoDeviceExtension = 
(PFDO_DEVICE_EXTENSION)DeviceExtension->ControllerFdo->DeviceExtension;
-
-       switch (IdType)
-       {
-               case BusQueryDeviceID:
-               {
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / 
BusQueryDeviceID\n");
-                       RtlInitUnicodeString(&SourceString, 
L"PCIIDE\\IDEChannel");
-                       break;
-               }
-               case BusQueryHardwareIDs:
-               {
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / 
BusQueryHardwareIDs\n");
-
-                       switch (FdoDeviceExtension->VendorId)
-                       {
-                               case 0x0e11:
-                                       Index += swprintf(&Buffer[Index], 
L"Compaq-%04x", FdoDeviceExtension->DeviceId) + 1;
-                                       break;
-                               case 0x1039:
-                                       Index += swprintf(&Buffer[Index], 
L"SiS-%04x", FdoDeviceExtension->DeviceId) + 1;
-                                       break;
-                               case 0x1050:
-                                       Index += swprintf(&Buffer[Index], 
L"WinBond-%04x", FdoDeviceExtension->DeviceId) + 1;
-                                       break;
-                               case 0x1095:
-                                       Index += swprintf(&Buffer[Index], 
L"CMD-%04x", FdoDeviceExtension->DeviceId) + 1;
-                                       break;
-                               case 0x8086:
-                               {
-                                       switch (FdoDeviceExtension->DeviceId)
-                                       {
-                                               case 0x1230:
-                                                       Index += 
swprintf(&Buffer[Index], L"Intel-PIIX") + 1;
-                                                       break;
-                                               case 0x7010:
-                                                       Index += 
swprintf(&Buffer[Index], L"Intel-PIIX3") + 1;
-                                                       break;
-                                               case 0x7111:
-                                                       Index += 
swprintf(&Buffer[Index], L"Intel-PIIX4") + 1;
-                                                       break;
-                                               default:
-                                                       Index += 
swprintf(&Buffer[Index], L"Intel-%04x", FdoDeviceExtension->DeviceId) + 1;
-                                                       break;
-                                       }
-                                       break;
-                               }
-                               default:
-                                       break;
-                       }
-                       if (DeviceExtension->Channel == 0)
-                               Index += swprintf(&Buffer[Index], 
L"Primary_IDE_Channel") + 1;
-                       else
-                               Index += swprintf(&Buffer[Index], 
L"Secondary_IDE_Channel") + 1;
-                       Index += swprintf(&Buffer[Index], L"*PNP0600") + 1;
-                       Buffer[Index] = UNICODE_NULL;
-                       SourceString.Length = SourceString.MaximumLength = 
Index * sizeof(WCHAR);
-                       SourceString.Buffer = Buffer;
-                       break;
-               }
-               case BusQueryCompatibleIDs:
-               {
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / 
BusQueryCompatibleIDs\n");
-
-                       Index += swprintf(&Buffer[Index], L"*PNP0600") + 1;
-                       Buffer[Index] = UNICODE_NULL;
-                       SourceString.Length = SourceString.MaximumLength = 
Index * sizeof(WCHAR);
-                       SourceString.Buffer = Buffer;
-                       break;
-               }
-               case BusQueryInstanceID:
-               {
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / 
BusQueryInstanceID\n");
-                       swprintf(Buffer, L"%lu", DeviceExtension->Channel);
-                       RtlInitUnicodeString(&SourceString, Buffer);
-                       break;
-               }
-               default:
-                       DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query 
id type 0x%lx\n", IdType);
-                       ASSERT(FALSE);
-                       return STATUS_NOT_SUPPORTED;
-       }
-
-       Status = DuplicateUnicodeString(
-               RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
-               &SourceString,
-               &String);
-       *Information = (ULONG_PTR)String.Buffer;
-       return Status;
+    PFDO_DEVICE_EXTENSION FdoExtension = PdoExtension->ParentController;
+    ULONG i;
+
+    PAGED_CODE();
+
+    if (FinalRemove && PdoExtension->ReportedMissing)
+    {
+        ExAcquireFastMutex(&FdoExtension->DeviceSyncMutex);
+
+        for (i = 0; i < MAX_IDE_CHANNEL; ++i)
+        {
+            if (FdoExtension->Channels[i] == PdoExtension)
+            {
+                FdoExtension->Channels[i] = NULL;
+                break;
+            }
+        }
+
+        ExReleaseFastMutex(&FdoExtension->DeviceSyncMutex);
+
+        IoDeleteDevice(PdoExtension->Common.Self);
+    }
+
+    return STATUS_SUCCESS;
 }
 
-static NTSTATUS
-GetCurrentResources(
-       IN PDEVICE_OBJECT DeviceObject,
-       OUT PULONG CommandPortBase,
-       OUT PULONG ControlPortBase,
-       OUT PULONG BusMasterPortBase,
-       OUT PULONG InterruptVector)
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXPdoQueryStopRemoveDevice(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension)
 {
-       PPDO_DEVICE_EXTENSION DeviceExtension;
-       PFDO_DEVICE_EXTENSION FdoDeviceExtension;
-       ULONG BaseIndex;
-       ULONG BytesRead;
-       PCI_COMMON_CONFIG PciConfig;
-       NTSTATUS ret = STATUS_UNSUCCESSFUL;
-
-       DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-       FdoDeviceExtension = 
(PFDO_DEVICE_EXTENSION)DeviceExtension->ControllerFdo->DeviceExtension;
-       BaseIndex = DeviceExtension->Channel * 2;
-
-       BytesRead = (*FdoDeviceExtension->BusInterface->GetBusData)(
-               FdoDeviceExtension->BusInterface->Context,
-               PCI_WHICHSPACE_CONFIG,
-               &PciConfig,
-               0,
-               PCI_COMMON_HDR_LENGTH);
-       if (BytesRead != PCI_COMMON_HDR_LENGTH)
-               return STATUS_IO_DEVICE_ERROR;
-
-       /* We have found a known native pci ide controller */
-       if ((PciConfig.ProgIf & 0x80) && (PciConfig.u.type0.BaseAddresses[4] & 
PCI_ADDRESS_IO_SPACE))
-       {
-               DPRINT("Found IDE Bus Master controller!\n");
-               *BusMasterPortBase = PciConfig.u.type0.BaseAddresses[4] & 
PCI_ADDRESS_IO_ADDRESS_MASK;
-               DPRINT("  IDE Bus Master Registers at IO %lx\n", 
*BusMasterPortBase);
-       }
-       else
-       {
-               *BusMasterPortBase = 0;
-       }
-
-       if ((PciConfig.ProgIf >> BaseIndex) & 0x1)
-       {
-               /* Native mode */
-               if ((PciConfig.u.type0.BaseAddresses[BaseIndex + 0] & 
PCI_ADDRESS_IO_SPACE) &&
-                   (PciConfig.u.type0.BaseAddresses[BaseIndex + 1] & 
PCI_ADDRESS_IO_SPACE))
-               {
-                       /* Channel is enabled */
-                       *CommandPortBase = 
PciConfig.u.type0.BaseAddresses[BaseIndex + 0] & PCI_ADDRESS_IO_ADDRESS_MASK;
-                       *ControlPortBase = 
PciConfig.u.type0.BaseAddresses[BaseIndex + 1] & PCI_ADDRESS_IO_ADDRESS_MASK;
-                       *InterruptVector = PciConfig.u.type0.InterruptLine;
-                       ret = STATUS_SUCCESS;
-               }
-       }
-       else
-       {
-               /* Compatibility mode */
-               switch (DeviceExtension->Channel)
-               {
-                       case 0:
-                               if 
(IoGetConfigurationInformation()->AtDiskPrimaryAddressClaimed)
-                                       ret = STATUS_INSUFFICIENT_RESOURCES;
-                               else
-                               {
-                                       *CommandPortBase = 0x1F0;
-                                       *ControlPortBase = 0x3F6;
-                                       *InterruptVector = 14;
-                                       ret = STATUS_SUCCESS;
-                               }
-                               break;
-                       case 1:
-                               if 
(IoGetConfigurationInformation()->AtDiskSecondaryAddressClaimed)
-                                       ret = STATUS_INSUFFICIENT_RESOURCES;
-                               else
-                               {
-                                       *CommandPortBase = 0x170;
-                                       *ControlPortBase = 0x376;
-                                       *InterruptVector = 15;
-                                       ret = STATUS_SUCCESS;
-                               }
-                               break;
-               }
-       }
-
-       return ret;
+    PAGED_CODE();
+
+    if (PdoExtension->Common.PageFiles ||
+        PdoExtension->Common.HibernateFiles ||
+        PdoExtension->Common.DumpFiles)
+    {
+        return STATUS_DEVICE_BUSY;
+    }
+
+    return STATUS_SUCCESS;
 }
 
-static NTSTATUS
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXPdoQueryTargetDeviceRelations(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _In_ PIRP Irp)
+{
+    PDEVICE_RELATIONS DeviceRelations;
+
+    PAGED_CODE();
+
+    DeviceRelations = ExAllocatePoolWithTag(PagedPool,
+                                            sizeof(DEVICE_RELATIONS),
+                                            TAG_PCIIDEX);
+    if (!DeviceRelations)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    DeviceRelations->Count = 1;
+    DeviceRelations->Objects[0] = PdoExtension->Common.Self;
+    ObReferenceObject(PdoExtension->Common.Self);
+
+    Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+    return STATUS_SUCCESS;
+}
+
+static IO_COMPLETION_ROUTINE PciIdeXOnRepeaterCompletion;
+
+static
+NTSTATUS
+NTAPI
+PciIdeXOnRepeaterCompletion(
+    _In_ PDEVICE_OBJECT DeviceObject,
+    _In_ PIRP Irp,
+    _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
+{
+    UNREFERENCED_PARAMETER(DeviceObject);
+
+    if (Irp->PendingReturned)
+        KeSetEvent(Context, IO_NO_INCREMENT, FALSE);
+
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXPdoRepeatRequest(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _In_ PIRP Irp,
+    _In_opt_ PDEVICE_CAPABILITIES DeviceCapabilities)
+{
+    PDEVICE_OBJECT Fdo, TopDeviceObject;
+    PIO_STACK_LOCATION IoStack, SubStack;
+    PIRP SubIrp;
+    KEVENT Event;
+    NTSTATUS Status;
+
+    PAGED_CODE();
+
+    Fdo = PdoExtension->ParentController->Common.Self;
+    TopDeviceObject = IoGetAttachedDeviceReference(Fdo);
+
+    SubIrp = IoAllocateIrp(TopDeviceObject->StackSize, FALSE);
+    if (!SubIrp)
+    {
+        ObDereferenceObject(TopDeviceObject);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    SubStack = IoGetNextIrpStackLocation(SubIrp);
+    RtlCopyMemory(SubStack, IoStack, sizeof(IO_STACK_LOCATION));
+
+    if (DeviceCapabilities)
+        SubStack->Parameters.DeviceCapabilities.Capabilities = 
DeviceCapabilities;
+
+    IoSetCompletionRoutine(SubIrp,
+                           PciIdeXOnRepeaterCompletion,
+                           &Event,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+
+    SubIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+
+    Status = IoCallDriver(TopDeviceObject, SubIrp);
+    if (Status == STATUS_PENDING)
+    {
+        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+    }
+
+    ObDereferenceObject(TopDeviceObject);
+
+    Status = SubIrp->IoStatus.Status;
+    IoFreeIrp(SubIrp);
+
+    return Status;
+}
+
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXPdoQueryCapabilities(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _In_ PIRP Irp)
+{
+    DEVICE_CAPABILITIES ParentCapabilities;
+    PDEVICE_CAPABILITIES DeviceCapabilities;
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+
+    PAGED_CODE();
+
+    /* Get the capabilities of the parent device */
+    RtlZeroMemory(&ParentCapabilities, sizeof(ParentCapabilities));
+    ParentCapabilities.Size = sizeof(ParentCapabilities);
+    ParentCapabilities.Version = 1;
+    ParentCapabilities.Address = MAXULONG;
+    ParentCapabilities.UINumber = MAXULONG;
+    Status = PciIdeXPdoRepeatRequest(PdoExtension, Irp, &ParentCapabilities);
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    DeviceCapabilities = IoStack->Parameters.DeviceCapabilities.Capabilities;
+    *DeviceCapabilities = ParentCapabilities;
+
+    /* Override some fields */
+    DeviceCapabilities->UniqueID = FALSE;
+    DeviceCapabilities->Address = PdoExtension->Channel;
+
+    return STATUS_SUCCESS;
+}
+
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXPdoQueryPnpDeviceState(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _In_ PIRP Irp)
+{
+    PAGED_CODE();
+
+    if (PdoExtension->Common.PageFiles ||
+        PdoExtension->Common.HibernateFiles ||
+        PdoExtension->Common.DumpFiles)
+    {
+        Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXPdoQueryResources(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _In_ PIRP Irp)
+{
+    PFDO_DEVICE_EXTENSION FdoExtension;
+    IDE_CHANNEL_STATE ChannelState;
+    PCM_RESOURCE_LIST ResourceList;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+    ULONG CommandPortBase, ControlPortBase, InterruptVector;
+    ULONG ListSize;
+
+    PAGED_CODE();
+
+    FdoExtension = PdoExtension->ParentController;
+    if (FdoExtension->InNativeMode)
+        return Irp->IoStatus.Status;
+
+    ChannelState = PciIdeXChannelState(FdoExtension, PdoExtension->Channel);
+    if (ChannelState == ChannelDisabled)
+        return Irp->IoStatus.Status;
+
+    ListSize = sizeof(CM_RESOURCE_LIST) +
+               sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 
(PCIIDE_LEGACY_RESOURCE_COUNT - 1);
+    ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_PCIIDEX);
+    if (!ResourceList)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* Legacy mode resources */
+    ResourceList->Count = 1;
+    ResourceList->List[0].InterfaceType = Isa;
+    ResourceList->List[0].PartialResourceList.Version = 1;
+    ResourceList->List[0].PartialResourceList.Revision = 1;
+    ResourceList->List[0].PartialResourceList.Count = 
PCIIDE_LEGACY_RESOURCE_COUNT;
+
+    if (IS_PRIMARY_CHANNEL(PdoExtension))
+    {
+        CommandPortBase = PCIIDE_LEGACY_PRIMARY_COMMAND_BASE;
+        ControlPortBase = PCIIDE_LEGACY_PRIMARY_CONTROL_BASE;
+        InterruptVector = PCIIDE_LEGACY_PRIMARY_IRQ;
+    }
+    else
+    {
+        CommandPortBase = PCIIDE_LEGACY_SECONDARY_COMMAND_BASE;
+        ControlPortBase = PCIIDE_LEGACY_SECONDARY_CONTROL_BASE;
+        InterruptVector = PCIIDE_LEGACY_SECONDARY_IRQ;
+    }
+
+    Descriptor = 
&ResourceList->List[0].PartialResourceList.PartialDescriptors[0];
+
+    /* Command port base */
+    Descriptor->Type = CmResourceTypePort;
+    Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+    Descriptor->Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
+    Descriptor->u.Port.Length = PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH;
+    Descriptor->u.Port.Start.LowPart = CommandPortBase;
+    ++Descriptor;
+
+    /* Control port base */
+    Descriptor->Type = CmResourceTypePort;
+    Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+    Descriptor->Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
+    Descriptor->u.Port.Length = PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH;
+    Descriptor->u.Port.Start.LowPart = ControlPortBase;
+    ++Descriptor;
+
+    /* Interrupt */
+    Descriptor->Type = CmResourceTypeInterrupt;
+    Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+    Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+    Descriptor->u.Interrupt.Level = InterruptVector;
+    Descriptor->u.Interrupt.Vector = InterruptVector;
+    Descriptor->u.Interrupt.Affinity = (KAFFINITY)-1;
+
+    Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
+    return STATUS_SUCCESS;
+}
+
+static
+CODE_SEG("PAGE")
+NTSTATUS
 PciIdeXPdoQueryResourceRequirements(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp,
-       OUT ULONG_PTR* Information)
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _In_ PIRP Irp)
+{
+    PFDO_DEVICE_EXTENSION FdoExtension;
+    PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
+    PIO_RESOURCE_DESCRIPTOR Descriptor;
+    IDE_CHANNEL_STATE ChannelState;
+    ULONG CommandPortBase, ControlPortBase, InterruptVector;
+    ULONG ListSize;
+
+    PAGED_CODE();
+
+    FdoExtension = PdoExtension->ParentController;
+    if (FdoExtension->InNativeMode)
+        return Irp->IoStatus.Status;
+
+    ChannelState = PciIdeXChannelState(FdoExtension, PdoExtension->Channel);
+    if (ChannelState == ChannelDisabled)
+        return Irp->IoStatus.Status;
+
+    ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
+               sizeof(IO_RESOURCE_DESCRIPTOR) * (PCIIDE_LEGACY_RESOURCE_COUNT 
- 1);
+    RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_PCIIDEX);
+    if (!RequirementsList)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* Legacy mode resources */
+    RequirementsList->InterfaceType = Isa;
+    RequirementsList->ListSize = ListSize;
+    RequirementsList->AlternativeLists = 1;
+    RequirementsList->List[0].Version = 1;
+    RequirementsList->List[0].Revision = 1;
+    RequirementsList->List[0].Count = PCIIDE_LEGACY_RESOURCE_COUNT;
+
+    if (IS_PRIMARY_CHANNEL(PdoExtension))
+    {
+        CommandPortBase = PCIIDE_LEGACY_PRIMARY_COMMAND_BASE;
+        ControlPortBase = PCIIDE_LEGACY_PRIMARY_CONTROL_BASE;
+        InterruptVector = PCIIDE_LEGACY_PRIMARY_IRQ;
+    }
+    else
+    {
+        CommandPortBase = PCIIDE_LEGACY_SECONDARY_COMMAND_BASE;
+        ControlPortBase = PCIIDE_LEGACY_SECONDARY_CONTROL_BASE;
+        InterruptVector = PCIIDE_LEGACY_SECONDARY_IRQ;
+    }
+
+    Descriptor = &RequirementsList->List[0].Descriptors[0];
+
+    /* Command port base */
+    Descriptor->Type = CmResourceTypePort;
+    Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+    Descriptor->Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
+    Descriptor->u.Port.Length = PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH;
+    Descriptor->u.Port.Alignment = 1;
+    Descriptor->u.Port.MinimumAddress.LowPart = CommandPortBase;
+    Descriptor->u.Port.MaximumAddress.LowPart = CommandPortBase +
+                                                
PCIIDE_LEGACY_COMMAND_IO_RANGE_LENGTH - 1;
+    ++Descriptor;
+
+    /* Control port base */
+    Descriptor->Type = CmResourceTypePort;
+    Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+    Descriptor->Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
+    Descriptor->u.Port.Length = PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH;
+    Descriptor->u.Port.Alignment = 1;
+    Descriptor->u.Port.MinimumAddress.LowPart = ControlPortBase;
+    Descriptor->u.Port.MaximumAddress.LowPart = ControlPortBase +
+                                                
PCIIDE_LEGACY_CONTROL_IO_RANGE_LENGTH - 1;
+    ++Descriptor;
+
+    /* Interrupt */
+    Descriptor->Type = CmResourceTypeInterrupt;
+    Descriptor->ShareDisposition = CmResourceShareShared;
+    Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+    Descriptor->u.Interrupt.MinimumVector = InterruptVector;
+    Descriptor->u.Interrupt.MaximumVector = InterruptVector;
+
+    Irp->IoStatus.Information = (ULONG_PTR)RequirementsList;
+    return STATUS_SUCCESS;
+}
+
+static
+CODE_SEG("PAGE")
+PCWSTR
+PciIdeXGetControllerVendorId(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension)
+{
+    PAGED_CODE();
+
+    switch (FdoExtension->VendorId)
+    {
+        case 0x0E11:
+            return L"Compaq";
+        case 0x1039:
+            return L"SiS";
+        case 0x1050:
+            return L"WinBond";
+        case 0x1095:
+            return L"CMD";
+        case 0x10B9:
+            return L"ALi";
+        case 0x8086:
+            return L"Intel";
+
+        default:
+            break;
+    }
+
+    /* Only certain controllers have a non-numeric identifier */
+    return NULL;
+}
+
+static
+CODE_SEG("PAGE")
+PCWSTR
+PciIdeXGetControllerDeviceId(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension)
 {
-       ULONG CommandPortBase;
-       ULONG ControlPortBase;
-       ULONG BusMasterPortBase;
-       ULONG InterruptVector;
-       ULONG ListSize;
-       PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
-       PIO_RESOURCE_DESCRIPTOR Descriptor;
-       NTSTATUS Status;
-
-       Status = GetCurrentResources(DeviceObject, &CommandPortBase,
-               &ControlPortBase, &BusMasterPortBase, &InterruptVector);
-       if (!NT_SUCCESS(Status))
-               return Status;
-
-       DPRINT("IDE Channel %lu: IO %x and %x, BM %lx, Irq %lu\n",
-               ((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Channel,
-               CommandPortBase, ControlPortBase,
-               BusMasterPortBase, InterruptVector);
-
-       /* FIXME: what to do with BusMasterPortBase? */
-
-       ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST)
-               + 2 * sizeof(IO_RESOURCE_DESCRIPTOR);
-       RequirementsList = ExAllocatePool(PagedPool, ListSize);
-       if (!RequirementsList)
-               return STATUS_INSUFFICIENT_RESOURCES;
-
-       RtlZeroMemory(RequirementsList, ListSize);
-       RequirementsList->ListSize = ListSize;
-       RequirementsList->AlternativeLists = 1;
-
-       RequirementsList->List[0].Version = 1;
-       RequirementsList->List[0].Revision = 1;
-       RequirementsList->List[0].Count = 3;
-
-       Descriptor = &RequirementsList->List[0].Descriptors[0];
-
-       /* Command port base */
-       Descriptor->Option = 0; /* Required */
-       Descriptor->Type = CmResourceTypePort;
-       Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
-       Descriptor->Flags = CM_RESOURCE_PORT_IO |
-                           CM_RESOURCE_PORT_16_BIT_DECODE |
-                           CM_RESOURCE_PORT_POSITIVE_DECODE;
-       Descriptor->u.Port.Length = 8;
-       Descriptor->u.Port.Alignment = 1;
-       Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)CommandPortBase;
-       Descriptor->u.Port.MaximumAddress.QuadPart = 
(ULONGLONG)(CommandPortBase + Descriptor->u.Port.Length - 1);
-       Descriptor++;
-
-       /* Control port base */
-       Descriptor->Option = 0; /* Required */
-       Descriptor->Type = CmResourceTypePort;
-       Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
-       Descriptor->Flags = CM_RESOURCE_PORT_IO |
-                           CM_RESOURCE_PORT_16_BIT_DECODE |
-                           CM_RESOURCE_PORT_POSITIVE_DECODE;
-       Descriptor->u.Port.Length = 1;
-       Descriptor->u.Port.Alignment = 1;
-       Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)ControlPortBase;
-       Descriptor->u.Port.MaximumAddress.QuadPart = 
(ULONGLONG)(ControlPortBase + Descriptor->u.Port.Length - 1);
-       Descriptor++;
-
-       /* Interrupt */
-       Descriptor->Option = 0; /* Required */
-       Descriptor->Type = CmResourceTypeInterrupt;
-       Descriptor->ShareDisposition = CmResourceShareShared;
-       Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
-       Descriptor->u.Interrupt.MinimumVector = InterruptVector;
-       Descriptor->u.Interrupt.MaximumVector = InterruptVector;
-
-       *Information = (ULONG_PTR)RequirementsList;
-       return STATUS_SUCCESS;
+    PAGED_CODE();
+
+    /* Intel */
+    if (FdoExtension->VendorId == 0x8086)
+    {
+        switch (FdoExtension->DeviceId)
+        {
+            case 0x1230:
+                return L"PIIX";
+            case 0x7010:
+                return L"PIIX3";
+            case 0x7111:
+                return L"PIIX4";
+
+            default:
+                break;
+        }
+    }
+
+    return NULL;
 }
 
-static NTSTATUS
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXPdoQueryId(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _In_ PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+    PWCHAR Buffer, End;
+    size_t CharCount, Remaining;
+    static const WCHAR IdeCompatibleId[] = L"*PNP0600";
+
+    PAGED_CODE();
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    switch (IoStack->Parameters.QueryId.IdType)
+    {
+      case BusQueryDeviceID:
+      {
+          static const WCHAR PciIdeDeviceId[] = L"PCIIDE\\IDEChannel";
+
+          Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(PciIdeDeviceId), 
TAG_PCIIDEX);
+          if (!Buffer)
+              return STATUS_INSUFFICIENT_RESOURCES;
+
+          RtlCopyMemory(Buffer, PciIdeDeviceId, sizeof(PciIdeDeviceId));
+
+          DPRINT("Device ID: '%S'\n", Buffer);
+          break;
+      }
+
+      case BusQueryHardwareIDs:
+      {
+          PFDO_DEVICE_EXTENSION FdoExtension;
+          PCWSTR VendorString;
+          PWCHAR IdStart;
+
+          DBG_UNREFERENCED_LOCAL_VARIABLE(IdStart);
+
+          /* Maximum string length */
+          CharCount = sizeof("WinBond-1234") +
+                      sizeof("Secondary_IDE_Channel") +
+                      sizeof(IdeCompatibleId) +
+                      sizeof(ANSI_NULL); /* multi-string */
+
+          Buffer = ExAllocatePoolWithTag(PagedPool,
+                                         CharCount * sizeof(WCHAR),
+                                         TAG_PCIIDEX);
+          if (!Buffer)
+              return STATUS_INSUFFICIENT_RESOURCES;
+
+          FdoExtension = PdoExtension->ParentController;
+          VendorString = PciIdeXGetControllerVendorId(FdoExtension);
+
+          DPRINT("HardwareIDs:\n");
+
+          /* ID 1 */
+          if (VendorString)
+          {
+              PCWSTR DeviceString = PciIdeXGetControllerDeviceId(FdoExtension);
+
+              if (DeviceString)
+              {
+                  Status = RtlStringCchPrintfExW(Buffer,
+                                                 CharCount,
+                                                 &End,
+                                                 &Remaining,
+                                                 0,
+                                                 L"%ls-%ls",
+                                                 VendorString,
+                                                 DeviceString);
+              }
+              else
+              {
+                  Status = RtlStringCchPrintfExW(Buffer,
+                                                 CharCount,
+                                                 &End,
+                                                 &Remaining,
+                                                 0,
+                                                 L"%ls-%04x",
+                                                 VendorString,
+                                                 FdoExtension->DeviceId);
+              }
+          }
+          else
+          {
+              Status = RtlStringCchPrintfExW(Buffer,
+                                             CharCount,
+                                             &End,
+                                             &Remaining,
+                                             0,
+                                             L"%04x-%04x",
+                                             FdoExtension->VendorId,
+                                             FdoExtension->DeviceId);
+          }
+          ASSERT(NT_SUCCESS(Status));
+
+          DPRINT("  '%S'\n", Buffer);
+
+          ++End;
+          --Remaining;
+
+          /* ID 2 */
+          IdStart = End;
+          Status = RtlStringCchPrintfExW(End,
+                                         Remaining,
+                                         &End,
+                                         &Remaining,
+                                         0,
+                                         L"%ls",
+                                         IS_PRIMARY_CHANNEL(PdoExtension) ?
+                                         L"Primary_IDE_Channel" :
+                                         L"Secondary_IDE_Channel");
+          ASSERT(NT_SUCCESS(Status));
+
+          DPRINT("  '%S'\n", IdStart);
+
+          ++End;
+          --Remaining;
+
+          /* ID 3 */
+          IdStart = End;
+          Status = RtlStringCchPrintfExW(End,
+                                         Remaining,
+                                         &End,
+                                         &Remaining,
+                                         0,
+                                         L"%ls",
+                                         IdeCompatibleId);
+          ASSERT(NT_SUCCESS(Status));
+
+          DPRINT("  '%S'\n", IdStart);
+
+          *++End = UNICODE_NULL; /* multi-string */
+          break;
+      }
+
+      case BusQueryCompatibleIDs:
+      {
+          Buffer = ExAllocatePoolWithTag(PagedPool,
+                                         sizeof(IdeCompatibleId) + 
sizeof(UNICODE_NULL),
+                                         TAG_PCIIDEX);
+          if (!Buffer)
+              return STATUS_INSUFFICIENT_RESOURCES;
+
+          RtlCopyMemory(Buffer, IdeCompatibleId, sizeof(IdeCompatibleId));
+
+          Buffer[sizeof(IdeCompatibleId) / sizeof(WCHAR)] = UNICODE_NULL; /* 
multi-string */
+
+          DPRINT("Compatible ID: '%S'\n", Buffer);
+          break;
+      }
+
+      case BusQueryInstanceID:
+      {
+          CharCount = sizeof("0");
+
+          Buffer = ExAllocatePoolWithTag(PagedPool,
+                                         CharCount * sizeof(WCHAR),
+                                         TAG_PCIIDEX);
+          if (!Buffer)
+              return STATUS_INSUFFICIENT_RESOURCES;
+
+          Status = RtlStringCchPrintfExW(Buffer,
+                                         CharCount,
+                                         NULL,
+                                         NULL,
+                                         0,
+                                         L"%lu",
+                                         PdoExtension->Channel);
+          ASSERT(NT_SUCCESS(Status));
+
+          DPRINT("Instance ID: '%S'\n", Buffer);
+          break;
+      }
+
+      default:
+          return Irp->IoStatus.Status;
+    }
+
+    Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+    return STATUS_SUCCESS;
+}
+
+static
+CODE_SEG("PAGE")
+NTSTATUS
 PciIdeXPdoQueryDeviceText(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp,
-       OUT ULONG_PTR* Information)
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _In_ PIRP Irp)
 {
-       PPDO_DEVICE_EXTENSION DeviceExtension;
-       ULONG DeviceTextType;
-       PCWSTR SourceString;
-       UNICODE_STRING String;
-
-       DeviceTextType = 
IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType;
-       DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-       switch (DeviceTextType)
-       {
-               case DeviceTextDescription:
-               case DeviceTextLocationInformation:
-               {
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / %S\n",
-                               DeviceTextType == DeviceTextDescription ? 
L"DeviceTextDescription" : L"DeviceTextLocationInformation");
-                       if (DeviceExtension->Channel == 0)
-                               SourceString = L"Primary channel";
-                       else
-                               SourceString = L"Secondary channel";
-                       break;
-               }
-               default:
-                       DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / 
unknown type 0x%lx\n", DeviceTextType);
-                       ASSERT(FALSE);
-                       return STATUS_NOT_SUPPORTED;
-       }
-
-       if (RtlCreateUnicodeString(&String, SourceString))
-       {
-               *Information = (ULONG_PTR)String.Buffer;
-               return STATUS_SUCCESS;
-       }
-       else
-               return STATUS_INSUFFICIENT_RESOURCES;
+    PIO_STACK_LOCATION IoStack;
+    PWCHAR Buffer;
+    ULONG Size;
+
+    PAGED_CODE();
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    switch (IoStack->Parameters.QueryDeviceText.DeviceTextType)
+    {
+        case DeviceTextLocationInformation:
+        {
+            static const WCHAR PrimaryChannelText[] = L"Primary channel";
+            static const WCHAR SecondaryChannelText[] = L"Secondary channel";
+
+            if (IS_PRIMARY_CHANNEL(PdoExtension))
+                Size = sizeof(PrimaryChannelText);
+            else
+                Size = sizeof(SecondaryChannelText);
+
+            Buffer = ExAllocatePoolWithTag(PagedPool, Size, TAG_PCIIDEX);
+            if (!Buffer)
+                return STATUS_INSUFFICIENT_RESOURCES;
+
+            RtlCopyMemory(Buffer,
+                          IS_PRIMARY_CHANNEL(PdoExtension) ?
+                          PrimaryChannelText : SecondaryChannelText,
+                          Size);
+
+            DPRINT("Device ID: '%S'\n", Buffer);
+            break;
+        }
+
+        default:
+            return Irp->IoStatus.Status;
+    }
+
+    Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+    return STATUS_SUCCESS;
 }
 
-static NTSTATUS
-PciIdeXPdoQueryDeviceRelations(
-       IN PDEVICE_OBJECT DeviceObject,
-       OUT PDEVICE_RELATIONS* pDeviceRelations)
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXPdoQueryDeviceUsageNotification(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _In_ PIRP Irp)
 {
-       PFDO_DEVICE_EXTENSION DeviceExtension;
-       PDEVICE_RELATIONS DeviceRelations;
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+    volatile LONG* Counter;
+
+    PAGED_CODE();
+
+    Status = PciIdeXPdoRepeatRequest(PdoExtension, Irp, NULL);
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    switch (IoStack->Parameters.UsageNotification.Type)
+    {
+        case DeviceUsageTypePaging:
+            Counter = &PdoExtension->Common.PageFiles;
+            break;
+
+        case DeviceUsageTypeHibernation:
+            Counter = &PdoExtension->Common.HibernateFiles;
+            break;
 
-       DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-       ASSERT(DeviceExtension->Common.IsFDO);
+        case DeviceUsageTypeDumpFile:
+            Counter = &PdoExtension->Common.DumpFiles;
+            break;
 
-       DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
-               PagedPool,
-               sizeof(DEVICE_RELATIONS));
-       if (!DeviceRelations)
-               return STATUS_INSUFFICIENT_RESOURCES;
+        default:
+            return Status;
+    }
 
-       ObReferenceObject(DeviceObject);
-       DeviceRelations->Count = 1;
-       DeviceRelations->Objects[0] = DeviceObject;
+    IoAdjustPagingPathCount(Counter, 
IoStack->Parameters.UsageNotification.InPath);
+    IoInvalidateDeviceState(PdoExtension->Common.Self);
 
-       *pDeviceRelations = DeviceRelations;
-       return STATUS_SUCCESS;
+    return STATUS_SUCCESS;
 }
 
-NTSTATUS NTAPI
-PciIdeXPdoPnpDispatch(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp)
+static
+CODE_SEG("PAGE")
+NTSTATUS
+PciIdeXPdoDispatchPnp(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _Inout_ PIRP Irp)
 {
-       ULONG MinorFunction;
-       PIO_STACK_LOCATION Stack;
-       ULONG_PTR Information = Irp->IoStatus.Information;
-       NTSTATUS Status;
-
-       Stack = IoGetCurrentIrpStackLocation(Irp);
-       MinorFunction = Stack->MinorFunction;
-
-       switch (MinorFunction)
-       {
-               /* FIXME:
-                * Those are required:
-                *    IRP_MN_START_DEVICE (done)
-                *    IRP_MN_QUERY_STOP_DEVICE
-                *    IRP_MN_STOP_DEVICE
-                *    IRP_MN_CANCEL_STOP_DEVICE
-                *    IRP_MN_QUERY_REMOVE_DEVICE
-                *    IRP_MN_REMOVE_DEVICE
-                *    IRP_MN_CANCEL_REMOVE_DEVICE
-                *    IRP_MN_SURPRISE_REMOVAL
-                *    IRP_MN_QUERY_CAPABILITIES (done)
-                *    IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelations 
(done)
-                *    IRP_MN_QUERY_ID / BusQueryDeviceID (done)
-                * Those may be required/optional:
-                *    IRP_MN_DEVICE_USAGE_NOTIFICATION
-                *    IRP_MN_QUERY_RESOURCES
-                *    IRP_MN_QUERY_RESOURCE_REQUIREMENTS (done)
-                *    IRP_MN_QUERY_DEVICE_TEXT
-                *    IRP_MN_QUERY_BUS_INFORMATION
-                *    IRP_MN_QUERY_INTERFACE
-                *    IRP_MN_READ_CONFIG
-                *    IRP_MN_WRITE_CONFIG
-                *    IRP_MN_EJECT
-                *    IRP_MN_SET_LOCK
-                * Those are optional:
-                *    IRP_MN_QUERY_DEVICE_RELATIONS / EjectionRelations
-                *    IRP_MN_QUERY_ID / BusQueryHardwareIDs (done)
-                *    IRP_MN_QUERY_ID / BusQueryCompatibleIDs (done)
-                *    IRP_MN_QUERY_ID / BusQueryInstanceID (done)
-                */
-               case IRP_MN_START_DEVICE: /* 0x00 */
-               {
-                       DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
-                       Status = STATUS_SUCCESS;
-                       break;
-               }
-                case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */
-                {
-                        DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
-                        Status = STATUS_UNSUCCESSFUL;
-                        break;
-                }
-               case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
-               {
-                       switch (Stack->Parameters.QueryDeviceRelations.Type)
-                       {
-                               case TargetDeviceRelation:
-                               {
-                                       PDEVICE_RELATIONS DeviceRelations = 
NULL;
-                                       DPRINT("IRP_MJ_PNP / 
IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
-                                       Status = 
PciIdeXPdoQueryDeviceRelations(DeviceObject, &DeviceRelations);
-                                       Information = 
(ULONG_PTR)DeviceRelations;
-                                       break;
-                               }
-                               default:
-                               {
-                                       DPRINT1("IRP_MJ_PNP / 
IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
-                                               
Stack->Parameters.QueryDeviceRelations.Type);
-                                       Status = Irp->IoStatus.Status;
-                                       break;
-                               }
-                       }
-                       break;
-               }
-               case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */
-               {
-                       PDEVICE_CAPABILITIES DeviceCapabilities;
-                       ULONG i;
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
-
-                       DeviceCapabilities = 
(PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
-                       /* FIXME: capabilities can change with connected device 
*/
-                       DeviceCapabilities->LockSupported = FALSE;
-                       DeviceCapabilities->EjectSupported = FALSE;
-                       DeviceCapabilities->Removable = TRUE;
-                       DeviceCapabilities->DockDevice = FALSE;
-                       DeviceCapabilities->UniqueID = FALSE;
-                       DeviceCapabilities->SilentInstall = FALSE;
-                       DeviceCapabilities->RawDeviceOK = FALSE;
-                       DeviceCapabilities->SurpriseRemovalOK = TRUE;
-                       DeviceCapabilities->HardwareDisabled = FALSE; /* FIXME 
*/
-                       //DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */
-                       DeviceCapabilities->DeviceState[0] = PowerDeviceD0; /* 
FIXME */
-                       for (i = 0; i < PowerSystemMaximum; i++)
-                               DeviceCapabilities->DeviceState[i] = 
PowerDeviceD3; /* FIXME */
-                       //DeviceCapabilities->DeviceWake = 
PowerDeviceUndefined; /* FIXME */
-                       DeviceCapabilities->D1Latency = 0; /* FIXME */
-                       DeviceCapabilities->D2Latency = 0; /* FIXME */
-                       DeviceCapabilities->D3Latency = 0; /* FIXME */
-                       Status = STATUS_SUCCESS;
-                       break;
-               }
-               case IRP_MN_QUERY_RESOURCES: /* 0x0a */
-               {
-                       /* This IRP is optional; do nothing */
-                       Information = Irp->IoStatus.Information;
-                       Status = Irp->IoStatus.Status;
-                       break;
-               }
-               case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0x0b */
-               {
-                       DPRINT("IRP_MJ_PNP / 
IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
-                       Status = 
PciIdeXPdoQueryResourceRequirements(DeviceObject, Irp, &Information);
-                       break;
-               }
-               case IRP_MN_QUERY_DEVICE_TEXT: /* 0x0c */
-               {
-                       Status = PciIdeXPdoQueryDeviceText(DeviceObject, Irp, 
&Information);
-                       break;
-               }
-               case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */
-               {
-                       DPRINT("IRP_MJ_PNP / 
IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
-                       Information = Irp->IoStatus.Information;
-                       Status = Irp->IoStatus.Status;
-                       break;
-               }
-               case IRP_MN_QUERY_ID: /* 0x13 */
-               {
-                       Status = PciIdeXPdoQueryId(DeviceObject, Irp, 
&Information);
-                       break;
-               }
-                case IRP_MN_QUERY_PNP_DEVICE_STATE: /* 0x14 */
-                {
-                        DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
-                        Information |= PNP_DEVICE_NOT_DISABLEABLE;
-                        Status = STATUS_SUCCESS;
-                        break;
-                }
-               case IRP_MN_QUERY_BUS_INFORMATION: /* 0x15 */
-               {
-                       PPNP_BUS_INFORMATION BusInfo;
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
-
-                       BusInfo = 
(PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
-                       if (!BusInfo)
-                               Status = STATUS_INSUFFICIENT_RESOURCES;
-                       else
-                       {
-                               /*RtlCopyMemory(
-                                       &BusInfo->BusTypeGuid,
-                                       &GUID_DEVINTERFACE_XXX,
-                                       sizeof(GUID));*/
-                               BusInfo->LegacyBusType = PNPBus;
-                               BusInfo->BusNumber = 0; /* FIXME */
-                               Information = (ULONG_PTR)BusInfo;
-                               Status = STATUS_SUCCESS;
-                       }
-                       break;
-               }
-               default:
-               {
-                       /* We can't forward request to the lower driver, because
-                        * we are a Pdo, so we don't have lower driver... */
-                       DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", 
MinorFunction);
-                       Information = Irp->IoStatus.Information;
-                       Status = Irp->IoStatus.Status;
-               }
-       }
-
-       Irp->IoStatus.Information = Information;
-       Irp->IoStatus.Status = Status;
-       IoCompleteRequest(Irp, IO_NO_INCREMENT);
-       return Status;
+    NTSTATUS Status;
+    PIO_STACK_LOCATION IoStack;
+
+    PAGED_CODE();
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    switch (IoStack->MinorFunction)
+    {
+        case IRP_MN_START_DEVICE:
+            Status = PciIdeXPdoStartDevice(PdoExtension,
+                                           
IoStack->Parameters.StartDevice.AllocatedResources);
+            break;
+
+        case IRP_MN_STOP_DEVICE:
+            Status = PciIdeXPdoStopDevice(PdoExtension);
+            break;
+
+        case IRP_MN_QUERY_STOP_DEVICE:
+        case IRP_MN_QUERY_REMOVE_DEVICE:
+            Status = PciIdeXPdoQueryStopRemoveDevice(PdoExtension);
+            break;
+
+        case IRP_MN_CANCEL_REMOVE_DEVICE:
+        case IRP_MN_CANCEL_STOP_DEVICE:
+            Status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MN_SURPRISE_REMOVAL:
+        case IRP_MN_REMOVE_DEVICE:
+            Status = PciIdeXPdoRemoveDevice(PdoExtension,
+                                            IoStack->MinorFunction == 
IRP_MN_REMOVE_DEVICE);
+            break;
+
+        case IRP_MN_QUERY_DEVICE_RELATIONS:
+            if (IoStack->Parameters.QueryDeviceRelations.Type == 
TargetDeviceRelation)
+                Status = PciIdeXPdoQueryTargetDeviceRelations(PdoExtension, 
Irp);
+            else
+                Status = Irp->IoStatus.Status;
+            break;
+
+        case IRP_MN_QUERY_CAPABILITIES:
+            Status = PciIdeXPdoQueryCapabilities(PdoExtension, Irp);
+            break;
+
+        case IRP_MN_QUERY_PNP_DEVICE_STATE:
+            Status = PciIdeXPdoQueryPnpDeviceState(PdoExtension, Irp);
+            break;
+
+        case IRP_MN_QUERY_RESOURCES:
+            Status = PciIdeXPdoQueryResources(PdoExtension, Irp);
+            break;
+
+        case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
+            Status = PciIdeXPdoQueryResourceRequirements(PdoExtension, Irp);
+            break;
+
+        case IRP_MN_QUERY_ID:
+            Status = PciIdeXPdoQueryId(PdoExtension, Irp);
+            break;
+
+        case IRP_MN_QUERY_DEVICE_TEXT:
+            Status = PciIdeXPdoQueryDeviceText(PdoExtension, Irp);
+            break;
+
+        case IRP_MN_DEVICE_USAGE_NOTIFICATION:
+            Status = PciIdeXPdoQueryDeviceUsageNotification(PdoExtension, Irp);
+            break;
+
+        default:
+            Status = Irp->IoStatus.Status;
+            break;
+    }
+
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+CODE_SEG("PAGE")
+NTSTATUS
+NTAPI
+PciIdeXDispatchPnp(
+    _In_ PDEVICE_OBJECT DeviceObject,
+    _Inout_ PIRP Irp)
+{
+    PAGED_CODE();
+
+    if (IS_FDO(DeviceObject->DeviceExtension))
+        return PciIdeXFdoDispatchPnp(DeviceObject->DeviceExtension, Irp);
+    else
+        return PciIdeXPdoDispatchPnp(DeviceObject->DeviceExtension, Irp);
 }
diff --git a/drivers/storage/ide/pciidex/power.c 
b/drivers/storage/ide/pciidex/power.c
new file mode 100644
index 00000000000..63075c27bf7
--- /dev/null
+++ b/drivers/storage/ide/pciidex/power.c
@@ -0,0 +1,66 @@
+/*
+ * PROJECT:     PCI IDE bus driver extension
+ * LICENSE:     See COPYING in the top level directory
+ * PURPOSE:     Power support functions
+ * COPYRIGHT:   Copyright 2023 Dmitry Borisov <[email protected]>
+ */
+
+#include "pciidex.h"
+
+#define NDEBUG
+#include <debug.h>
+
+static
+NTSTATUS
+PciIdeXPdoDispatchPower(
+    _In_ PPDO_DEVICE_EXTENSION PdoExtension,
+    _In_ PIRP Irp)
+{
+    NTSTATUS Status;
+    PIO_STACK_LOCATION IoStack;
+
+    UNREFERENCED_PARAMETER(PdoExtension);
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    switch (IoStack->MinorFunction)
+    {
+        case IRP_MN_SET_POWER:
+        case IRP_MN_QUERY_POWER:
+            Status = STATUS_SUCCESS;
+            Irp->IoStatus.Status = Status;
+            break;
+
+        default:
+            Status = Irp->IoStatus.Status;
+            break;
+    }
+
+    PoStartNextPowerIrp(Irp);
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return Status;
+}
+
+static
+NTSTATUS
+PciIdeXFdoDispatchPower(
+    _In_ PFDO_DEVICE_EXTENSION FdoExtension,
+    _In_ PIRP Irp)
+{
+    PoStartNextPowerIrp(Irp);
+    IoSkipCurrentIrpStackLocation(Irp);
+    return PoCallDriver(FdoExtension->Ldo, Irp);
+}
+
+NTSTATUS
+NTAPI
+PciIdeXDispatchPower(
+    _In_ PDEVICE_OBJECT DeviceObject,
+    _Inout_ PIRP Irp)
+{
+    PVOID DeviceExtension = DeviceObject->DeviceExtension;
+
+    if (IS_FDO(DeviceExtension))
+        return PciIdeXFdoDispatchPower(DeviceExtension, Irp);
+    else
+        return PciIdeXPdoDispatchPower(DeviceExtension, Irp);
+}
diff --git a/sdk/include/ddk/ide.h b/sdk/include/ddk/ide.h
index 4f3ea9f4650..83e416a5f57 100644
--- a/sdk/include/ddk/ide.h
+++ b/sdk/include/ddk/ide.h
@@ -246,6 +246,7 @@ typedef NTSTATUS
     _In_ PVOID DeviceExtension,
     _In_ PIDE_CONTROLLER_PROPERTIES ControllerProperties);
 
+CODE_SEG("PAGE")
 NTSTATUS NTAPI
 PciIdeXInitialize(
     _In_ PDRIVER_OBJECT DriverObject,

Reply via email to