reactos/drivers/storage/ide/pciidex/pdo.c
Dmitry Borisov c0c57e2324 [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
2023-07-16 13:20:30 +03:00

851 lines
24 KiB
C

/*
* PROJECT: PCI IDE bus driver extension
* LICENSE: See COPYING in the top level directory
* PURPOSE: IRP_MJ_PNP operations for PDOs
* COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
* Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
*/
#include "pciidex.h"
#define NDEBUG
#include <debug.h>
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);
}