https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c0c57e2324a7326de3e06…
commit c0c57e2324a7326de3e060c6296af177a75ff54f
Author: Dmitry Borisov <di.sean(a)protonmail.com>
AuthorDate: Sun Jan 8 18:07:14 2023 +0600
Commit: Stanislav Motylkov <x86corez(a)gmail.com>
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 (hpoussin(a)reactos.org)
+ * 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 <hpoussin(a)reactos.org>
+ * Copyright 2023 Dmitry Borisov <di.sean(a)protonmail.com>
*/
#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 (hpoussin(a)reactos.org)
+ * PROJECT: PCI IDE bus driver extension
+ * LICENSE: See COPYING in the top level directory
+ * PURPOSE: Miniport functions
+ * COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin(a)reactos.org>
*/
#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 (hpoussin(a)reactos.org)
- */
-
-#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 (hpoussin(a)reactos.org)
+ * PROJECT: PCI IDE bus driver extension
+ * LICENSE: See COPYING in the top level directory
+ * PURPOSE: Main file
+ * COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin(a)reactos.org>
*/
#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 <hpoussin(a)reactos.org>
+ * Copyright 2023 Dmitry Borisov <di.sean(a)protonmail.com>
+ */
+
#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 (hpoussin(a)reactos.org)
+ * 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 <hpoussin(a)reactos.org>
+ * Copyright 2023 Dmitry Borisov <di.sean(a)protonmail.com>
*/
#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 <di.sean(a)protonmail.com>
+ */
+
+#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,