reactos/drivers/bus/isapnp/pdo.c
Dmitry Borisov c4b6330b14 [ISAPNP] Implement the Read Port resource management
Currently disabled until the kernel is ready
2021-06-20 19:24:31 +06:00

820 lines
23 KiB
C

/*
* PROJECT: ReactOS ISA PnP Bus driver
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: PDO-specific code
* COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
* Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
* Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
*/
#include "isapnp.h"
#define NDEBUG
#include <debug.h>
static
CODE_SEG("PAGE")
NTSTATUS
IsaPdoQueryDeviceRelations(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_Inout_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp)
{
PDEVICE_RELATIONS DeviceRelations;
PAGED_CODE();
if (IrpSp->Parameters.QueryDeviceRelations.Type == RemovalRelations &&
PdoExt->Common.Signature == IsaPnpReadDataPort)
{
return IsaPnpFillDeviceRelations(PdoExt->FdoExt, Irp, FALSE);
}
if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
return Irp->IoStatus.Status;
DeviceRelations = ExAllocatePoolWithTag(PagedPool, sizeof(*DeviceRelations), TAG_ISAPNP);
if (!DeviceRelations)
return STATUS_NO_MEMORY;
DeviceRelations->Count = 1;
DeviceRelations->Objects[0] = PdoExt->Common.Self;
ObReferenceObject(PdoExt->Common.Self);
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
NTSTATUS
IsaPdoQueryCapabilities(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_Inout_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp)
{
PDEVICE_CAPABILITIES DeviceCapabilities;
ULONG i;
UNREFERENCED_PARAMETER(Irp);
PAGED_CODE();
DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
if (DeviceCapabilities->Version != 1)
return STATUS_REVISION_MISMATCH;
DeviceCapabilities->LockSupported =
DeviceCapabilities->EjectSupported =
DeviceCapabilities->Removable =
DeviceCapabilities->DockDevice = FALSE;
DeviceCapabilities->UniqueID = TRUE;
if (PdoExt->Common.Signature == IsaPnpReadDataPort)
{
DeviceCapabilities->RawDeviceOK = TRUE;
DeviceCapabilities->SilentInstall = TRUE;
}
for (i = 0; i < POWER_SYSTEM_MAXIMUM; i++)
DeviceCapabilities->DeviceState[i] = PowerDeviceD3;
DeviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
NTSTATUS
IsaPdoQueryPnpDeviceState(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_Inout_ PIRP Irp)
{
PAGED_CODE();
if (PdoExt->Flags & ISAPNP_READ_PORT_NEED_REBALANCE)
{
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE |
PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED |
PNP_DEVICE_FAILED;
return STATUS_SUCCESS;
}
else if (PdoExt->SpecialFiles > 0)
{
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
return STATUS_SUCCESS;
}
return Irp->IoStatus.Status;
}
static
CODE_SEG("PAGE")
NTSTATUS
IsaPdoQueryId(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_Inout_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp)
{
PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
NTSTATUS Status;
PWCHAR Buffer, End, IdStart;
size_t CharCount, Remaining;
PAGED_CODE();
switch (IrpSp->Parameters.QueryId.IdType)
{
case BusQueryDeviceID:
{
CharCount = sizeof("ISAPNP\\XXXFFFF");
Buffer = ExAllocatePoolWithTag(PagedPool,
CharCount * sizeof(WCHAR),
TAG_ISAPNP);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
Status = RtlStringCchPrintfExW(Buffer,
CharCount,
&End,
&Remaining,
0,
L"ISAPNP\\%.3S%04x",
LogDev->VendorId,
LogDev->ProdId);
if (!NT_VERIFY(NT_SUCCESS(Status)))
goto Failure;
DPRINT("Device ID: '%S'\n", Buffer);
break;
}
case BusQueryHardwareIDs:
{
CharCount = sizeof("ISAPNP\\XXXFFFF") +
sizeof("*PNPxxxx") +
sizeof(ANSI_NULL); /* multi-string */
Buffer = ExAllocatePoolWithTag(PagedPool,
CharCount * sizeof(WCHAR),
TAG_ISAPNP);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
DPRINT("Hardware IDs:\n");
/* 1 */
Status = RtlStringCchPrintfExW(Buffer,
CharCount,
&End,
&Remaining,
0,
L"ISAPNP\\%.3S%04x",
LogDev->VendorId,
LogDev->ProdId);
if (!NT_VERIFY(NT_SUCCESS(Status)))
goto Failure;
DPRINT(" '%S'\n", Buffer);
++End;
--Remaining;
/* 2 */
IdStart = End;
Status = RtlStringCchPrintfExW(End,
Remaining,
&End,
&Remaining,
0,
L"*%.3S%04x",
LogDev->VendorId,
LogDev->ProdId);
if (!NT_VERIFY(NT_SUCCESS(Status)))
goto Failure;
DPRINT(" '%S'\n", IdStart);
*++End = UNICODE_NULL;
--Remaining;
break;
}
case BusQueryCompatibleIDs:
return STATUS_NOT_IMPLEMENTED;
case BusQueryInstanceID:
{
CharCount = sizeof(LogDev->SerialNumber) * 2 + sizeof(ANSI_NULL);
Buffer = ExAllocatePoolWithTag(PagedPool,
CharCount * sizeof(WCHAR),
TAG_ISAPNP);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
Status = RtlStringCchPrintfExW(Buffer,
CharCount,
NULL,
NULL,
0,
L"%X",
LogDev->SerialNumber);
if (!NT_VERIFY(NT_SUCCESS(Status)))
goto Failure;
DPRINT("Instance ID: '%S'\n", Buffer);
break;
}
default:
return Irp->IoStatus.Status;
}
Irp->IoStatus.Information = (ULONG_PTR)Buffer;
return STATUS_SUCCESS;
Failure:
ExFreePoolWithTag(Buffer, TAG_ISAPNP);
return Status;
}
static
CODE_SEG("PAGE")
NTSTATUS
IsaReadPortQueryId(
_Inout_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp)
{
PWCHAR Buffer;
static const WCHAR ReadPortId[] = L"ISAPNP\\ReadDataPort";
PAGED_CODE();
switch (IrpSp->Parameters.QueryId.IdType)
{
case BusQueryDeviceID:
{
Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(ReadPortId), TAG_ISAPNP);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyMemory(Buffer, ReadPortId, sizeof(ReadPortId));
DPRINT("Device ID: '%S'\n", Buffer);
break;
}
case BusQueryHardwareIDs:
{
Buffer = ExAllocatePoolWithTag(PagedPool,
sizeof(ReadPortId) + sizeof(UNICODE_NULL),
TAG_ISAPNP);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyMemory(Buffer, ReadPortId, sizeof(ReadPortId));
Buffer[sizeof(ReadPortId) / sizeof(WCHAR)] = UNICODE_NULL; /* multi-string */
DPRINT("Hardware ID: '%S'\n", Buffer);
break;
}
case BusQueryCompatibleIDs:
{
/* Empty multi-string */
Buffer = ExAllocatePoolZero(PagedPool, sizeof(UNICODE_NULL) * 2, TAG_ISAPNP);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
DPRINT("Compatible ID: '%S'\n", Buffer);
break;
}
case BusQueryInstanceID:
{
/* Even if there are multiple ISA buses, the driver has only one Read Port */
static const WCHAR InstanceId[] = L"0";
Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(InstanceId), TAG_ISAPNP);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyMemory(Buffer, InstanceId, sizeof(InstanceId));
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
IsaPdoQueryResources(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_Inout_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp)
{
ULONG ListSize;
PCM_RESOURCE_LIST ResourceList;
UNREFERENCED_PARAMETER(IrpSp);
PAGED_CODE();
if (!PdoExt->ResourceList)
return Irp->IoStatus.Status;
ListSize = PdoExt->ResourceListSize;
ResourceList = ExAllocatePoolWithTag(PagedPool, ListSize, TAG_ISAPNP);
if (!ResourceList)
return STATUS_NO_MEMORY;
RtlCopyMemory(ResourceList, PdoExt->ResourceList, ListSize);
Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
NTSTATUS
IsaPdoQueryResourceRequirements(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_Inout_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp)
{
ULONG ListSize;
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
UNREFERENCED_PARAMETER(IrpSp);
PAGED_CODE();
if (!PdoExt->RequirementsList)
return Irp->IoStatus.Status;
ListSize = PdoExt->RequirementsList->ListSize;
RequirementsList = ExAllocatePoolWithTag(PagedPool, ListSize, TAG_ISAPNP);
if (!RequirementsList)
return STATUS_NO_MEMORY;
RtlCopyMemory(RequirementsList, PdoExt->RequirementsList, ListSize);
Irp->IoStatus.Information = (ULONG_PTR)RequirementsList;
return STATUS_SUCCESS;
}
#define IS_READ_PORT(_d) ((_d)->Type == CmResourceTypePort && (_d)->u.Port.Length > 1)
static
CODE_SEG("PAGE")
NTSTATUS
IsaPdoStartReadPort(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_In_ PCM_RESOURCE_LIST ResourceList)
{
PISAPNP_FDO_EXTENSION FdoExt = PdoExt->FdoExt;
NTSTATUS Status;
ULONG i;
PAGED_CODE();
if (!ResourceList)
{
DPRINT1("No resource list\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
if (ResourceList->List[0].PartialResourceList.Version != 1 ||
ResourceList->List[0].PartialResourceList.Revision != 1)
{
DPRINT1("Bad resource list version (%u.%u)\n",
ResourceList->List[0].PartialResourceList.Version,
ResourceList->List[0].PartialResourceList.Revision);
return STATUS_REVISION_MISMATCH;
}
#if 0
/* Try various Read Ports from the list */
if (ResourceList->List[0].PartialResourceList.Count > 3)
{
ULONG SelectedPort = 0;
for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor =
&ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
if (IS_READ_PORT(PartialDescriptor))
{
PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3);
/*
* Remember the first Read Port in the resource list.
* It will be selected by default even if no card has been detected.
*/
if (!SelectedPort)
SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart;
/* We detected some ISAPNP cards */
if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort)))
{
SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart;
break;
}
}
}
ASSERT(SelectedPort != 0);
if (PdoExt->RequirementsList)
{
ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP);
PdoExt->RequirementsList = NULL;
}
/* Discard the Read Ports at conflicting locations */
Status = IsaPnpCreateReadPortDORequirements(PdoExt, SelectedPort);
if (!NT_SUCCESS(Status))
return Status;
PdoExt->Flags |= ISAPNP_READ_PORT_NEED_REBALANCE;
IoInvalidateDeviceState(PdoExt->Common.Self);
return STATUS_SUCCESS;
}
/* Set the Read Port */
else if (ResourceList->List[0].PartialResourceList.Count == 3)
#else
if (ResourceList->List[0].PartialResourceList.Count > 3) /* Temporary HACK */
#endif
{
PdoExt->Flags &= ~ISAPNP_READ_PORT_NEED_REBALANCE;
for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor =
&ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
if (IS_READ_PORT(PartialDescriptor))
{
PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3);
/* Run the isolation protocol */
if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort)))
{
FdoExt->ReadDataPort = ReadDataPort;
IsaPnpAcquireDeviceDataLock(FdoExt);
/* Card identification */
Status = IsaHwFillDeviceList(FdoExt);
if (FdoExt->DeviceCount > 0)
{
PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN |
ISAPNP_SCANNED_BY_READ_PORT;
IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations);
IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations);
}
IsaPnpReleaseDeviceDataLock(FdoExt);
return Status;
}
else
{
break;
}
}
}
}
else
{
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
/* Mark Read Port as started, even if no card has been detected */
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
NTSTATUS
IsaPdoFilterResourceRequirements(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_Inout_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
/* TODO: Handle */
UNREFERENCED_PARAMETER(PdoExt);
UNREFERENCED_PARAMETER(IrpSp);
return Irp->IoStatus.Status;
}
static
CODE_SEG("PAGE")
NTSTATUS
IsaPdoQueryBusInformation(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_Inout_ PIRP Irp)
{
PPNP_BUS_INFORMATION BusInformation;
PAGED_CODE();
BusInformation = ExAllocatePoolWithTag(PagedPool,
sizeof(PNP_BUS_INFORMATION),
TAG_ISAPNP);
if (!BusInformation)
return STATUS_INSUFFICIENT_RESOURCES;
BusInformation->BusTypeGuid = GUID_BUS_TYPE_ISAPNP;
BusInformation->LegacyBusType = Isa;
BusInformation->BusNumber = PdoExt->FdoExt->BusNumber;
Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
NTSTATUS
IsaPdoQueryDeviceUsageNotification(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_Inout_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp)
{
BOOLEAN InPath = IrpSp->Parameters.UsageNotification.InPath;
PAGED_CODE();
switch (IrpSp->Parameters.UsageNotification.Type)
{
case DeviceUsageTypePaging:
case DeviceUsageTypeHibernation:
case DeviceUsageTypeDumpFile:
IoAdjustPagingPathCount(&PdoExt->SpecialFiles, InPath);
IoInvalidateDeviceState(PdoExt->Common.Self);
break;
default:
return Irp->IoStatus.Status;
}
/* Do not send it to FDO for compatibility */
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
NTSTATUS
IsaPdoRemoveDevice(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_In_ BOOLEAN FinalRemove)
{
PISAPNP_FDO_EXTENSION FdoExt = PdoExt->FdoExt;
PAGED_CODE();
if (FinalRemove && !(PdoExt->Flags & ISAPNP_ENUMERATED))
{
IsaPnpAcquireDeviceDataLock(FdoExt);
RemoveEntryList(&PdoExt->IsaPnpDevice->DeviceLink);
--FdoExt->DeviceCount;
IsaPnpReleaseDeviceDataLock(FdoExt);
IsaPnpRemoveLogicalDeviceDO(PdoExt->Common.Self);
}
return STATUS_SUCCESS;
}
static
CODE_SEG("PAGE")
NTSTATUS
IsaReadPortRemoveDevice(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_In_ BOOLEAN FinalRemove)
{
PISAPNP_FDO_EXTENSION FdoExt = PdoExt->FdoExt;
PLIST_ENTRY Entry;
PAGED_CODE();
IsaPnpAcquireDeviceDataLock(FdoExt);
/* Logical devices will receive a remove request afterwards */
for (Entry = FdoExt->DeviceListHead.Flink;
Entry != &FdoExt->DeviceListHead;
Entry = Entry->Flink)
{
PISAPNP_LOGICAL_DEVICE LogDevice = CONTAINING_RECORD(Entry,
ISAPNP_LOGICAL_DEVICE,
DeviceLink);
LogDevice->Flags &= ~ISAPNP_PRESENT;
}
IsaPnpReleaseDeviceDataLock(FdoExt);
PdoExt->Flags &= ~ISAPNP_READ_PORT_ALLOW_FDO_SCAN;
IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations);
if (FinalRemove && !(PdoExt->Flags & ISAPNP_ENUMERATED))
{
IsaPnpRemoveReadPortDO(PdoExt->Common.Self);
}
return STATUS_SUCCESS;
}
CODE_SEG("PAGE")
VOID
IsaPnpRemoveLogicalDeviceDO(
_In_ PDEVICE_OBJECT Pdo)
{
PISAPNP_PDO_EXTENSION PdoExt = Pdo->DeviceExtension;
PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
PAGED_CODE();
ASSERT(LogDev);
DPRINT("Removing CSN %u, LDN %u\n", LogDev->CSN, LogDev->LDN);
if (PdoExt->RequirementsList)
ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP);
if (PdoExt->ResourceList)
ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP);
ExFreePoolWithTag(LogDev, TAG_ISAPNP);
IoDeleteDevice(PdoExt->Common.Self);
}
CODE_SEG("PAGE")
NTSTATUS
IsaPdoPnp(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_Inout_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp)
{
NTSTATUS Status = Irp->IoStatus.Status;
PAGED_CODE();
if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
{
DPRINT("%s(%p, %p) CSN %u, LDN %u, Minor - %X\n",
__FUNCTION__,
PdoExt,
Irp,
PdoExt->IsaPnpDevice->CSN,
PdoExt->IsaPnpDevice->LDN,
IrpSp->MinorFunction);
}
else
{
DPRINT("%s(%p, %p) ReadPort, Minor - %X\n",
__FUNCTION__,
PdoExt,
Irp,
IrpSp->MinorFunction);
}
switch (IrpSp->MinorFunction)
{
case IRP_MN_START_DEVICE:
if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
Status = IsaHwActivateDevice(PdoExt->IsaPnpDevice);
else
{
Status = IsaPdoStartReadPort(PdoExt,
IrpSp->Parameters.StartDevice.AllocatedResources);
}
if (NT_SUCCESS(Status))
PdoExt->Common.State = dsStarted;
break;
case IRP_MN_STOP_DEVICE:
if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
Status = IsaHwDeactivateDevice(PdoExt->IsaPnpDevice);
else
{
PdoExt->Flags &= ~ISAPNP_READ_PORT_ALLOW_FDO_SCAN;
Status = STATUS_SUCCESS;
}
if (NT_SUCCESS(Status))
PdoExt->Common.State = dsStopped;
break;
case IRP_MN_QUERY_STOP_DEVICE:
{
if (PdoExt->SpecialFiles > 0)
Status = STATUS_DEVICE_BUSY;
else if (PdoExt->Flags & ISAPNP_READ_PORT_NEED_REBALANCE)
Status = STATUS_RESOURCE_REQUIREMENTS_CHANGED;
else
Status = STATUS_SUCCESS;
break;
}
case IRP_MN_QUERY_REMOVE_DEVICE:
{
if (PdoExt->SpecialFiles > 0)
Status = STATUS_DEVICE_BUSY;
else
Status = STATUS_SUCCESS;
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS:
Status = IsaPdoQueryDeviceRelations(PdoExt, Irp, IrpSp);
break;
case IRP_MN_QUERY_CAPABILITIES:
Status = IsaPdoQueryCapabilities(PdoExt, Irp, IrpSp);
break;
case IRP_MN_SURPRISE_REMOVAL:
if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
Status = IsaPdoRemoveDevice(PdoExt, FALSE);
else
Status = IsaReadPortRemoveDevice(PdoExt, FALSE);
break;
case IRP_MN_REMOVE_DEVICE:
if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
Status = IsaPdoRemoveDevice(PdoExt, TRUE);
else
Status = IsaReadPortRemoveDevice(PdoExt, TRUE);
break;
case IRP_MN_QUERY_PNP_DEVICE_STATE:
Status = IsaPdoQueryPnpDeviceState(PdoExt, Irp);
break;
case IRP_MN_QUERY_RESOURCES:
Status = IsaPdoQueryResources(PdoExt, Irp, IrpSp);
break;
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
Status = IsaPdoQueryResourceRequirements(PdoExt, Irp, IrpSp);
break;
case IRP_MN_QUERY_ID:
if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
Status = IsaPdoQueryId(PdoExt, Irp, IrpSp);
else
Status = IsaReadPortQueryId(Irp, IrpSp);
break;
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
Status = IsaPdoFilterResourceRequirements(PdoExt, Irp, IrpSp);
break;
case IRP_MN_QUERY_BUS_INFORMATION:
Status = IsaPdoQueryBusInformation(PdoExt, Irp);
break;
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
Status = IsaPdoQueryDeviceUsageNotification(PdoExt, Irp, IrpSp);
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
Status = STATUS_SUCCESS;
break;
default:
DPRINT("Unknown PnP code: %X\n", IrpSp->MinorFunction);
break;
}
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}