/* * 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" #define NDEBUG #include 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) { 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_ 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) { 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_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PIRP Irp) { 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 CODE_SEG("PAGE") NTSTATUS PciIdeXPdoQueryDeviceUsageNotification( _In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PIRP Irp) { 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; case DeviceUsageTypeDumpFile: Counter = &PdoExtension->Common.DumpFiles; break; default: return Status; } IoAdjustPagingPathCount(Counter, IoStack->Parameters.UsageNotification.InPath); IoInvalidateDeviceState(PdoExtension->Common.Self); return STATUS_SUCCESS; } static CODE_SEG("PAGE") NTSTATUS PciIdeXPdoDispatchPnp( _In_ PPDO_DEVICE_EXTENSION PdoExtension, _Inout_ PIRP Irp) { 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); }