From c0c57e2324a7326de3e060c6296af177a75ff54f Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Sun, 8 Jan 2023 18:07:14 +0600 Subject: [PATCH] [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 | 906 +++++++------- drivers/storage/ide/pciidex/miniport.c | 283 ++--- drivers/storage/ide/pciidex/misc.c | 73 -- drivers/storage/ide/pciidex/pciidex.c | 339 +++++- drivers/storage/ide/pciidex/pciidex.h | 154 ++- drivers/storage/ide/pciidex/pdo.c | 1279 ++++++++++++-------- drivers/storage/ide/pciidex/power.c | 66 + sdk/include/ddk/ide.h | 1 + 9 files changed, 1876 insertions(+), 1229 deletions(-) delete mode 100644 drivers/storage/ide/pciidex/misc.c create mode 100644 drivers/storage/ide/pciidex/power.c 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@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 + * Copyright 2023 Dmitry Borisov */ #include "pciidex.h" @@ -11,481 +11,497 @@ #define NDEBUG #include -#include -#include - -static NTSTATUS -GetBusInterface( - IN PFDO_DEVICE_EXTENSION DeviceExtension) +static +CODE_SEG("PAGE") +NTSTATUS +PciIdeXFdoParseResources( + _In_ PFDO_DEVICE_EXTENSION FdoExtension, + _In_ PCM_RESOURCE_LIST ResourcesTranslated) { - PBUS_INTERFACE_STANDARD BusInterface = NULL; - KEVENT Event; - IO_STATUS_BLOCK IoStatus; - PIRP Irp; - PIO_STACK_LOCATION Stack; - NTSTATUS Status = STATUS_UNSUCCESSFUL; + PCM_PARTIAL_RESOURCE_DESCRIPTOR BusMasterDescriptor = NULL; + PVOID IoBase; + ULONG i; - if (DeviceExtension->BusInterface) - { - DPRINT("We already have the bus interface\n"); - goto cleanup; - } + PAGED_CODE(); - BusInterface = ExAllocatePool(PagedPool, sizeof(BUS_INTERFACE_STANDARD)); - if (!BusInterface) - { - DPRINT("ExAllocatePool() failed\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - goto cleanup; - } + if (!ResourcesTranslated) + return STATUS_INVALID_PARAMETER; - 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; - } + for (i = 0; i < ResourcesTranslated->List[0].PartialResourceList.Count; ++i) + { + PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - Irp->IoStatus.Information = 0; + 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; + } - 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; + default: + break; + } + } - Status = IoCallDriver(DeviceExtension->LowerDevice, Irp); - if (Status == STATUS_PENDING) - { - KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); - Status = IoStatus.Status; - } - if (!NT_SUCCESS(Status)) - goto cleanup; + default: + break; + } + } - DeviceExtension->BusInterface = BusInterface; - BusInterface = NULL; - Status = STATUS_SUCCESS; + if (!BusMasterDescriptor) + return STATUS_DEVICE_CONFIGURATION_ERROR; -cleanup: - if (BusInterface) ExFreePool(BusInterface); - return Status; + 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 -ReleaseBusInterface( - IN PFDO_DEVICE_EXTENSION DeviceExtension) -{ - NTSTATUS Status = STATUS_UNSUCCESSFUL; - - if (DeviceExtension->BusInterface) - { - (*DeviceExtension->BusInterface->InterfaceDereference)( - DeviceExtension->BusInterface->Context); - DeviceExtension->BusInterface = NULL; - Status = STATUS_SUCCESS; - } - - return Status; -} - -NTSTATUS NTAPI -PciIdeXAddDevice( - IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT Pdo) -{ - 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; -} - -static NTSTATUS NTAPI -PciIdeXUdmaModesSupported( - IN IDENTIFY_DATA IdentifyData, - OUT PULONG BestXferMode, - OUT PULONG CurrentXferMode) -{ - 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; -} - -static NTSTATUS +static +CODE_SEG("PAGE") +NTSTATUS PciIdeXFdoStartDevice( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) + _In_ PFDO_DEVICE_EXTENSION FdoExtension, + _In_ PIRP Irp) { - PPCIIDEX_DRIVER_EXTENSION DriverExtension; - PFDO_DEVICE_EXTENSION DeviceExtension; - PCM_RESOURCE_LIST ResourceList; - NTSTATUS Status; + NTSTATUS Status; + PIO_STACK_LOCATION IoStack; - DPRINT("PciIdeXStartDevice(%p %p)\n", DeviceObject, Irp); + PAGED_CODE(); - DriverExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject, DeviceObject->DriverObject); - ASSERT(DriverExtension); - DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - ASSERT(DeviceExtension); - ASSERT(DeviceExtension->Common.IsFDO); + if (!NT_VERIFY(IoForwardIrpSynchronously(FdoExtension->Ldo, Irp))) + { + return STATUS_UNSUCCESSFUL; + } + Status = Irp->IoStatus.Status; + if (!NT_SUCCESS(Status)) + { + return Status; + } - 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; + IoStack = IoGetCurrentIrpStackLocation(Irp); - DriverExtension->HwUdmaModesSupported = DeviceExtension->Properties.PciIdeUdmaModesSupported; - if (!DriverExtension->HwUdmaModesSupported) - /* This method is optional, so provide our own one */ - DriverExtension->HwUdmaModesSupported = PciIdeXUdmaModesSupported; + Status = PciIdeXFdoParseResources(FdoExtension, + IoStack->Parameters.StartDevice.AllocatedResourcesTranslated); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to parse resources 0x%lx\n", Status); + return Status; + } - /* 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; + Status = PciIdeXStartMiniport(FdoExtension); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Miniport initialization failed 0x%lx\n", Status); + return Status; + } + + return STATUS_SUCCESS; } -static NTSTATUS +static +CODE_SEG("PAGE") +VOID +PciIdeXFdoFreeResources( + _In_ PFDO_DEVICE_EXTENSION FdoExtension) +{ + PAGED_CODE(); + + if (FdoExtension->IoBaseMapped) + { + MmUnmapIoSpace(FdoExtension->BusMasterPortBase, 16); + FdoExtension->IoBaseMapped = FALSE; + } +} + +static +CODE_SEG("PAGE") +NTSTATUS +PciIdeXFdoStopDevice( + _In_ PFDO_DEVICE_EXTENSION FdoExtension) +{ + PAGED_CODE(); + + PciIdeXFdoFreeResources(FdoExtension); + + return STATUS_SUCCESS; +} + +static +CODE_SEG("PAGE") +NTSTATUS +PciIdeXFdoRemoveDevice( + _In_ PFDO_DEVICE_EXTENSION FdoExtension, + _In_ PIRP Irp) +{ + 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 +CODE_SEG("PAGE") +NTSTATUS +PciIdeXFdoQueryPnpDeviceState( + _In_ PFDO_DEVICE_EXTENSION FdoExtension, + _In_ PIRP Irp) +{ + 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 +CODE_SEG("PAGE") +PPDO_DEVICE_EXTENSION +PciIdeXPdoCreateDevice( + _In_ PFDO_DEVICE_EXTENSION FdoExtension, + _In_ ULONG ChannelNumber) +{ + 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 +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; + PPDO_DEVICE_EXTENSION PdoExtension; + IDE_CHANNEL_STATE ChannelState; + PDEVICE_RELATIONS DeviceRelations; + ULONG i; - DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - ASSERT(DeviceExtension); - ASSERT(DeviceExtension->Common.IsFDO); + PAGED_CODE(); - 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; - } + DeviceRelations = ExAllocatePoolWithTag(PagedPool, + FIELD_OFFSET(DEVICE_RELATIONS, + Objects[MAX_IDE_CHANNEL]), + TAG_PCIIDEX); + if (!DeviceRelations) + return STATUS_INSUFFICIENT_RESOURCES; - /* 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; + DeviceRelations->Count = 0; - 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; + ExAcquireFastMutex(&FdoExtension->DeviceSyncMutex); - DeviceExtension->Pdo[i] = Pdo; - PDOs++; - } + for (i = 0; i < MAX_IDE_CHANNEL; ++i) + { + PdoExtension = FdoExtension->Channels[i]; - 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; + /* Ignore disabled channels */ + ChannelState = PciIdeXChannelState(FdoExtension, i); + if (ChannelState == ChannelDisabled) + { + if (PdoExtension) + { + PdoExtension->ReportedMissing = TRUE; + } - 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]; - } - } + DPRINT("Channel %lu is disabled\n", i); + continue; + } - *pDeviceRelations = DeviceRelations; - return STATUS_SUCCESS; + /* 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; + PIO_STACK_LOCATION IoStack; + NTSTATUS Status; + volatile LONG* Counter; - Stack = IoGetCurrentIrpStackLocation(Irp); - MinorFunction = Stack->MinorFunction; + PAGED_CODE(); - 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 (!NT_VERIFY(IoForwardIrpSynchronously(FdoExtension->Ldo, Irp))) + { + return STATUS_UNSUCCESSFUL; + } + Status = Irp->IoStatus.Status; + if (!NT_SUCCESS(Status)) + { + return Status; + } - 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); - } - } + IoStack = IoGetCurrentIrpStackLocation(Irp); + switch (IoStack->Parameters.UsageNotification.Type) + { + case DeviceUsageTypePaging: + Counter = &FdoExtension->Common.PageFiles; + break; - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; + 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@reactos.org) + * PROJECT: PCI IDE bus driver extension + * LICENSE: See COPYING in the top level directory + * PURPOSE: Miniport functions + * COPYRIGHT: Copyright 2005 HervĂ© Poussineau */ #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; + PPCIIDEX_DRIVER_EXTENSION DriverExtension; + 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; - } + 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_POWER) -static DRIVER_DISPATCH PciIdeXPowerDispatch; -static NTSTATUS NTAPI -PciIdeXPowerDispatch( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) +CODE_SEG("PAGE") +IDE_CHANNEL_STATE +PciIdeXChannelState( + _In_ PFDO_DEVICE_EXTENSION FdoExtension, + _In_ ULONG Channel) { - NTSTATUS Status; - PIO_STACK_LOCATION IoStack; - PDEVICE_OBJECT LowerDevice; + PCIIDE_CHANNEL_ENABLED MiniportChannelEnabled; - 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(); -_Dispatch_type_(IRP_MJ_PNP) -static DRIVER_DISPATCH PciIdeXPnpDispatch; -static NTSTATUS NTAPI -PciIdeXPnpDispatch( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) - return PciIdeXFdoPnpDispatch(DeviceObject, Irp); - else - return PciIdeXPdoPnpDispatch(DeviceObject, Irp); + 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; + PFDO_DEVICE_EXTENSION FdoExtension; + ULONG BytesRead; - DPRINT("PciIdeXGetBusData(%p %p 0x%lx 0x%lx)\n", - DeviceExtension, Buffer, ConfigDataOffset, BufferLength); + 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; - } + FdoExtension = CONTAINING_RECORD(DeviceExtension, + FDO_DEVICE_EXTENSION, + MiniControllerExtension); - return Status; + 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; + 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); + 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; - } + CurrentBuffer = ExAllocatePoolWithTag(NonPagedPool, BufferLength, TAG_PCIIDEX); + if (!CurrentBuffer) + return STATUS_INSUFFICIENT_RESOURCES; - Status = PciIdeXGetBusData(DeviceExtension, Buffer, ConfigDataOffset, BufferLength); - if (!NT_SUCCESS(Status)) - goto cleanup; + FdoExtension = CONTAINING_RECORD(DeviceExtension, + FDO_DEVICE_EXTENSION, + MiniControllerExtension); - for (i = 0; i < BufferLength; i++) - CurrentBuffer[i] = (CurrentBuffer[i] & ~((PUCHAR)DataMask)[i]) | (((PUCHAR)DataMask)[i] & ((PUCHAR)Buffer)[i]); + KeAcquireSpinLock(&FdoExtension->BusDataLock, &OldIrql); - FdoDeviceExtension = CONTAINING_RECORD(DeviceExtension, FDO_DEVICE_EXTENSION, MiniControllerExtension); - if (!FdoDeviceExtension->BusInterface) - { - Status = STATUS_UNSUCCESSFUL; - goto cleanup; - } + Status = PciIdeXGetBusData(DeviceExtension, Buffer, ConfigDataOffset, BufferLength); + if (!NT_SUCCESS(Status)) + 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; + for (i = 0; i < BufferLength; i++) + { + CurrentBuffer[i] = (CurrentBuffer[i] & ~((PUCHAR)DataMask)[i]) | + (((PUCHAR)DataMask)[i] & ((PUCHAR)Buffer)[i]); + } -cleanup: - ExFreePool(CurrentBuffer); - return Status; + 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@reactos.org) - */ - -#include "pciidex.h" - -#define NDEBUG -#include - - -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@reactos.org) + * PROJECT: PCI IDE bus driver extension + * LICENSE: See COPYING in the top level directory + * PURPOSE: Main file + * COPYRIGHT: Copyright 2005 HervĂ© Poussineau */ #include "pciidex.h" @@ -11,10 +10,330 @@ #define NDEBUG #include -NTSTATUS NTAPI -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath) +ULONG PciIdeControllerNumber = 0; + +CODE_SEG("PAGE") +NTSTATUS +NTAPI +PciIdeXDispatchWmi( + _In_ PDEVICE_OBJECT DeviceObject, + _Inout_ PIRP Irp) { - return STATUS_SUCCESS; + 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) +{ + 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 + * Copyright 2023 Dmitry Borisov + */ + #ifndef _PCIIDEX_PCH_ #define _PCIIDEX_PCH_ -#include +#include +#include +#include +#include +#include #include +#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; + COMMON_DEVICE_EXTENSION Common; + PDEVICE_OBJECT Ldo; - 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]; + 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 */ +CODE_SEG("PAGE") +NTSTATUS +PciIdeXStartMiniport( + _In_ PFDO_DEVICE_EXTENSION FdoExtension); -NTSTATUS NTAPI -PciIdeXPdoPnpDispatch( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); +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@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 + * Copyright 2023 Dmitry Borisov */ #include "pciidex.h" -#include - #define NDEBUG #include -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) { - PPDO_DEVICE_EXTENSION DeviceExtension; - PFDO_DEVICE_EXTENSION FdoDeviceExtension; - WCHAR Buffer[256]; - ULONG Index = 0; - ULONG IdType; - UNICODE_STRING SourceString; - UNICODE_STRING String; - NTSTATUS Status; + PUCHAR IoBase; - IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType; - DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->ControllerFdo->DeviceExtension; + PAGED_CODE(); - 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"); + IoBase = PdoExtension->ParentController->BusMasterPortBase; + if (!IS_PRIMARY_CHANNEL(PdoExtension)) + { + IoBase += BM_SECONDARY_CHANNEL_OFFSET; + } + DPRINT("Bus Master Base %p\n", IoBase); - 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; + 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 +PciIdeXPdoStopDevice( + _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; + PAGED_CODE(); - 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; + return STATUS_SUCCESS; } -static NTSTATUS +static +CODE_SEG("PAGE") +NTSTATUS +PciIdeXPdoRemoveDevice( + _In_ PPDO_DEVICE_EXTENSION PdoExtension, + _In_ BOOLEAN FinalRemove) +{ + 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 +CODE_SEG("PAGE") +NTSTATUS +PciIdeXPdoQueryStopRemoveDevice( + _In_ PPDO_DEVICE_EXTENSION PdoExtension) +{ + PAGED_CODE(); + + if (PdoExtension->Common.PageFiles || + PdoExtension->Common.HibernateFiles || + PdoExtension->Common.DumpFiles) + { + return STATUS_DEVICE_BUSY; + } + + return STATUS_SUCCESS; +} + +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) { - ULONG CommandPortBase; - ULONG ControlPortBase; - ULONG BusMasterPortBase; - ULONG InterruptVector; - ULONG ListSize; - PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; - PIO_RESOURCE_DESCRIPTOR Descriptor; - NTSTATUS Status; + PFDO_DEVICE_EXTENSION FdoExtension; + PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; + PIO_RESOURCE_DESCRIPTOR Descriptor; + IDE_CHANNEL_STATE ChannelState; + ULONG CommandPortBase, ControlPortBase, InterruptVector; + ULONG ListSize; - Status = GetCurrentResources(DeviceObject, &CommandPortBase, - &ControlPortBase, &BusMasterPortBase, &InterruptVector); - if (!NT_SUCCESS(Status)) - return Status; + PAGED_CODE(); - DPRINT("IDE Channel %lu: IO %x and %x, BM %lx, Irq %lu\n", - ((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Channel, - CommandPortBase, ControlPortBase, - BusMasterPortBase, InterruptVector); + FdoExtension = PdoExtension->ParentController; + if (FdoExtension->InNativeMode) + return Irp->IoStatus.Status; - /* FIXME: what to do with BusMasterPortBase? */ + ChannelState = PciIdeXChannelState(FdoExtension, PdoExtension->Channel); + if (ChannelState == ChannelDisabled) + return Irp->IoStatus.Status; - ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) - + 2 * sizeof(IO_RESOURCE_DESCRIPTOR); - RequirementsList = ExAllocatePool(PagedPool, ListSize); - if (!RequirementsList) - return STATUS_INSUFFICIENT_RESOURCES; + 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; - RtlZeroMemory(RequirementsList, ListSize); - RequirementsList->ListSize = ListSize; - RequirementsList->AlternativeLists = 1; + /* 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; - RequirementsList->List[0].Version = 1; - RequirementsList->List[0].Revision = 1; - RequirementsList->List[0].Count = 3; + 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]; + 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++; + /* 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->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++; + /* 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->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; + /* Interrupt */ + Descriptor->Type = CmResourceTypeInterrupt; + Descriptor->ShareDisposition = CmResourceShareShared; + Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; + Descriptor->u.Interrupt.MinimumVector = InterruptVector; + Descriptor->u.Interrupt.MaximumVector = InterruptVector; - *Information = (ULONG_PTR)RequirementsList; - return STATUS_SUCCESS; + Irp->IoStatus.Information = (ULONG_PTR)RequirementsList; + return STATUS_SUCCESS; } -static NTSTATUS +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) +{ + 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 +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; + PIO_STACK_LOCATION IoStack; + PWCHAR Buffer; + ULONG Size; - DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType; - DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + PAGED_CODE(); - 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; - } + 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 (RtlCreateUnicodeString(&String, SourceString)) - { - *Information = (ULONG_PTR)String.Buffer; - return STATUS_SUCCESS; - } - else - return STATUS_INSUFFICIENT_RESOURCES; + 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; - DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - ASSERT(DeviceExtension->Common.IsFDO); + PAGED_CODE(); - DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool( - PagedPool, - sizeof(DEVICE_RELATIONS)); - if (!DeviceRelations) - return STATUS_INSUFFICIENT_RESOURCES; + Status = PciIdeXPdoRepeatRequest(PdoExtension, Irp, NULL); + if (!NT_SUCCESS(Status)) + return Status; - ObReferenceObject(DeviceObject); - DeviceRelations->Count = 1; - DeviceRelations->Objects[0] = DeviceObject; + IoStack = IoGetCurrentIrpStackLocation(Irp); + switch (IoStack->Parameters.UsageNotification.Type) + { + case DeviceUsageTypePaging: + Counter = &PdoExtension->Common.PageFiles; + break; - *pDeviceRelations = DeviceRelations; - return STATUS_SUCCESS; + case DeviceUsageTypeHibernation: + Counter = &PdoExtension->Common.HibernateFiles; + break; + + case DeviceUsageTypeDumpFile: + Counter = &PdoExtension->Common.DumpFiles; + break; + + default: + return Status; + } + + IoAdjustPagingPathCount(Counter, IoStack->Parameters.UsageNotification.InPath); + IoInvalidateDeviceState(PdoExtension->Common.Self); + + 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; + NTSTATUS Status; + PIO_STACK_LOCATION IoStack; - Stack = IoGetCurrentIrpStackLocation(Irp); - MinorFunction = Stack->MinorFunction; + PAGED_CODE(); - 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"); + IoStack = IoGetCurrentIrpStackLocation(Irp); + switch (IoStack->MinorFunction) + { + case IRP_MN_START_DEVICE: + Status = PciIdeXPdoStartDevice(PdoExtension, + IoStack->Parameters.StartDevice.AllocatedResources); + break; - 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"); + case IRP_MN_STOP_DEVICE: + Status = PciIdeXPdoStopDevice(PdoExtension); + break; - 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; - } - } + case IRP_MN_QUERY_STOP_DEVICE: + case IRP_MN_QUERY_REMOVE_DEVICE: + Status = PciIdeXPdoQueryStopRemoveDevice(PdoExtension); + break; - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; + 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 + */ + +#include "pciidex.h" + +#define NDEBUG +#include + +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,