[ISAPNP] Fixes and improvements for IRP handling

- Implement device removal.
- Finish the Read Port special handling
  introduced in 21514e473f.
- Gracefully handle low memory situations.
- Implement IRQ translator.
- Correctly stub power IRP handling.
- Remove unneeded dispatch routines; implement WMI IRP handling.
- Do not handle requests like WRITE_CONFIG.
- Add a signature member to device extensions to make checks clearer.
This commit is contained in:
Dmitry Borisov 2021-03-04 18:48:43 +06:00
parent e19595572a
commit f15de15554
6 changed files with 682 additions and 225 deletions

View file

@ -4,6 +4,7 @@ list(APPEND SOURCE
pdo.c pdo.c
fdo.c fdo.c
hardware.c hardware.c
interface.c
isapnp.h) isapnp.h)
add_library(isapnp MODULE ${SOURCE} isapnp.rc) add_library(isapnp MODULE ${SOURCE} isapnp.rc)

View file

@ -4,6 +4,7 @@
* PURPOSE: FDO-specific code * PURPOSE: FDO-specific code
* COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org> * COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
* Copyright 2020 Hervé Poussineau <hpoussin@reactos.org> * Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
* Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
*/ */
#include "isapnp.h" #include "isapnp.h"
@ -16,14 +17,22 @@ CODE_SEG("PAGE")
NTSTATUS NTSTATUS
IsaFdoStartDevice( IsaFdoStartDevice(
_In_ PISAPNP_FDO_EXTENSION FdoExt, _In_ PISAPNP_FDO_EXTENSION FdoExt,
_Inout_ PIRP Irp, _Inout_ PIRP Irp)
_In_ PIO_STACK_LOCATION IrpSp)
{ {
UNREFERENCED_PARAMETER(Irp); NTSTATUS Status;
UNREFERENCED_PARAMETER(IrpSp);
PAGED_CODE(); PAGED_CODE();
if (!IoForwardIrpSynchronously(FdoExt->Ldo, Irp))
{
return STATUS_UNSUCCESSFUL;
}
Status = Irp->IoStatus.Status;
if (!NT_SUCCESS(Status))
{
return Status;
}
FdoExt->Common.State = dsStarted; FdoExt->Common.State = dsStarted;
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -32,19 +41,83 @@ IsaFdoStartDevice(
static static
CODE_SEG("PAGE") CODE_SEG("PAGE")
NTSTATUS NTSTATUS
IsaFdoQueryDeviceRelations( IsaFdoQueryBusRelations(
_In_ PISAPNP_FDO_EXTENSION FdoExt, _In_ PISAPNP_FDO_EXTENSION FdoExt,
_Inout_ PIRP Irp, _Inout_ PIRP Irp)
_In_ PIO_STACK_LOCATION IrpSp)
{ {
PAGED_CODE(); PAGED_CODE();
if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
return Irp->IoStatus.Status;
return IsaPnpFillDeviceRelations(FdoExt, Irp, TRUE); return IsaPnpFillDeviceRelations(FdoExt, Irp, TRUE);
} }
static
CODE_SEG("PAGE")
NTSTATUS
IsaFdoRemoveDevice(
_In_ PISAPNP_FDO_EXTENSION FdoExt,
_Inout_ PIRP Irp)
{
NTSTATUS Status;
PLIST_ENTRY Entry;
PAGED_CODE();
IsaPnpAcquireDeviceDataLock(FdoExt);
/* Remove our logical devices */
while (!IsListEmpty(&FdoExt->DeviceListHead))
{
PISAPNP_LOGICAL_DEVICE LogDevice = CONTAINING_RECORD(RemoveHeadList(&FdoExt->
DeviceListHead),
ISAPNP_LOGICAL_DEVICE,
DeviceLink);
--FdoExt->DeviceCount;
if (LogDevice->Pdo)
{
IsaPnpRemoveLogicalDeviceDO(LogDevice->Pdo);
}
}
IsaPnpReleaseDeviceDataLock(FdoExt);
IsaPnpAcquireBusDataLock();
/* Remove the Read Port */
if (FdoExt->ReadPortPdo)
{
IsaPnpRemoveReadPortDO(FdoExt->ReadPortPdo);
ReadPortCreated = FALSE;
}
/* Find the next ISA bus, if any */
Entry = BusListHead.Flink;
if (Entry != &BusListHead)
{
PISAPNP_FDO_EXTENSION NextIsaBus = CONTAINING_RECORD(Entry,
ISAPNP_FDO_EXTENSION,
BusLink);
/* Create a new Read Port for it */
if (!ReadPortCreated)
IoInvalidateDeviceRelations(NextIsaBus->Pdo, BusRelations);
}
RemoveEntryList(&FdoExt->BusLink);
IsaPnpReleaseBusDataLock();
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(FdoExt->Ldo, Irp);
IoDetachDevice(FdoExt->Ldo);
IoDeleteDevice(FdoExt->Common.Self);
return Status;
}
CODE_SEG("PAGE") CODE_SEG("PAGE")
NTSTATUS NTSTATUS
IsaFdoPnp( IsaFdoPnp(
@ -52,43 +125,82 @@ IsaFdoPnp(
_Inout_ PIRP Irp, _Inout_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp) _In_ PIO_STACK_LOCATION IrpSp)
{ {
NTSTATUS Status = Irp->IoStatus.Status; NTSTATUS Status;
PAGED_CODE(); PAGED_CODE();
DPRINT("%s(%p, %p) FDO %lu, Minor - %X\n",
__FUNCTION__,
FdoExt,
Irp,
FdoExt->BusNumber,
IrpSp->MinorFunction);
switch (IrpSp->MinorFunction) switch (IrpSp->MinorFunction)
{ {
case IRP_MN_START_DEVICE: case IRP_MN_START_DEVICE:
Status = IsaForwardIrpSynchronous(FdoExt, Irp); Status = IsaFdoStartDevice(FdoExt, Irp);
if (NT_SUCCESS(Status))
Status = IsaFdoStartDevice(FdoExt, Irp, IrpSp);
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status; return Status;
case IRP_MN_STOP_DEVICE:
FdoExt->Common.State = dsStopped;
Status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_DEVICE_RELATIONS: case IRP_MN_QUERY_DEVICE_RELATIONS:
Status = IsaFdoQueryDeviceRelations(FdoExt, Irp, IrpSp); {
if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
break;
Status = IsaFdoQueryBusRelations(FdoExt, Irp);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
break;
}
IoCompleteRequest(Irp, IO_NO_INCREMENT); case IRP_MN_REMOVE_DEVICE:
return Status; return IsaFdoRemoveDevice(FdoExt, Irp);
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: case IRP_MN_QUERY_PNP_DEVICE_STATE:
DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_INTERFACE:
{
Status = IsaFdoQueryInterface(FdoExt, IrpSp);
if (Status == STATUS_NOT_SUPPORTED)
{
break;
}
else if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
Irp->IoStatus.Status = Status;
break;
}
case IRP_MN_SURPRISE_REMOVAL:
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_STOP_DEVICE:
Irp->IoStatus.Status = STATUS_SUCCESS;
break; break;
default: default:
DPRINT1("Unknown PnP code: %x\n", IrpSp->MinorFunction); DPRINT("Unknown PnP code: %X\n", IrpSp->MinorFunction);
break; break;
} }

View file

@ -0,0 +1,73 @@
/*
* PROJECT: ReactOS ISA PnP Bus driver
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Driver interface
* COPYRIGHT: Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
*/
/* INCLUDES *******************************************************************/
#include "isapnp.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ******************************************************************/
CODE_SEG("PAGE")
NTSTATUS
IsaFdoQueryInterface(
_In_ PISAPNP_FDO_EXTENSION FdoExt,
_In_ PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
if (IsEqualGUIDAligned(IrpSp->Parameters.QueryInterface.InterfaceType,
&GUID_TRANSLATOR_INTERFACE_STANDARD))
{
NTSTATUS Status;
CM_RESOURCE_TYPE ResourceType;
ULONG ParentBusType, ParentBusNumber, Dummy;
ResourceType = PtrToUlong(IrpSp->Parameters.QueryInterface.InterfaceSpecificData);
if (IrpSp->Parameters.QueryInterface.Size < sizeof(TRANSLATOR_INTERFACE) ||
ResourceType != CmResourceTypeInterrupt)
{
return STATUS_NOT_SUPPORTED;
}
Status = IoGetDeviceProperty(FdoExt->Pdo,
DevicePropertyLegacyBusType,
sizeof(ParentBusType),
&ParentBusType,
&Dummy);
if (!NT_SUCCESS(Status))
{
DPRINT1("BusType request failed with status 0x%08lx\n", Status);
return Status;
}
Status = IoGetDeviceProperty(FdoExt->Pdo,
DevicePropertyBusNumber,
sizeof(ParentBusNumber),
&ParentBusNumber,
&Dummy);
if (!NT_SUCCESS(Status))
{
DPRINT1("BusNumber request failed with status 0x%08lx\n", Status);
return Status;
}
return HalGetInterruptTranslator(ParentBusType,
ParentBusNumber,
Isa,
IrpSp->Parameters.QueryInterface.Size,
IrpSp->Parameters.QueryInterface.Version,
(PTRANSLATOR_INTERFACE)IrpSp->
Parameters.QueryInterface.Interface,
&ParentBusNumber);
}
return STATUS_NOT_SUPPORTED;
}

View file

@ -4,15 +4,28 @@
* PURPOSE: Driver entry * PURPOSE: Driver entry
* COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org> * COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
* Copyright 2020 Hervé Poussineau <hpoussin@reactos.org> * Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
* Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
*/ */
/* INCLUDES *******************************************************************/
#include "isapnp.h" #include "isapnp.h"
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* GLOBALS ********************************************************************/
KEVENT BusSyncEvent;
_Guarded_by_(BusSyncEvent)
BOOLEAN ReadPortCreated = FALSE; BOOLEAN ReadPortCreated = FALSE;
_Guarded_by_(BusSyncEvent)
LIST_ENTRY BusListHead;
/* FUNCTIONS ******************************************************************/
static static
CODE_SEG("PAGE") CODE_SEG("PAGE")
NTSTATUS NTSTATUS
@ -301,49 +314,6 @@ IsaPnpCreateLogicalDeviceResources(
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
static IO_COMPLETION_ROUTINE ForwardIrpCompletion;
static
NTSTATUS
NTAPI
ForwardIrpCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
UNREFERENCED_PARAMETER(DeviceObject);
if (Irp->PendingReturned)
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
NTAPI
IsaForwardIrpSynchronous(
IN PISAPNP_FDO_EXTENSION FdoExt,
IN PIRP Irp)
{
KEVENT Event;
NTSTATUS Status;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, ForwardIrpCompletion, &Event, TRUE, TRUE, TRUE);
Status = IoCallDriver(FdoExt->Ldo, Irp);
if (Status == STATUS_PENDING)
{
Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
if (NT_SUCCESS(Status))
Status = Irp->IoStatus.Status;
}
return Status;
}
_Dispatch_type_(IRP_MJ_CREATE) _Dispatch_type_(IRP_MJ_CREATE)
_Dispatch_type_(IRP_MJ_CLOSE) _Dispatch_type_(IRP_MJ_CLOSE)
static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaCreateClose; static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaCreateClose;
@ -359,7 +329,6 @@ IsaCreateClose(
PAGED_CODE(); PAGED_CODE();
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp);
@ -368,51 +337,37 @@ IsaCreateClose(
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
static DRIVER_DISPATCH IsaIoctl; _Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
_Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaForwardOrIgnore;
static static
CODE_SEG("PAGE")
NTSTATUS NTSTATUS
NTAPI NTAPI
IsaIoctl( IsaForwardOrIgnore(
IN PDEVICE_OBJECT DeviceObject, _In_ PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) _Inout_ PIRP Irp)
{ {
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PISAPNP_COMMON_EXTENSION CommonExt = DeviceObject->DeviceExtension;
NTSTATUS Status;
DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); PAGED_CODE();
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) DPRINT("%s(%p, %p) Minor - %X\n", __FUNCTION__, DeviceObject, Irp,
IoGetCurrentIrpStackLocation(Irp)->MinorFunction);
if (CommonExt->Signature == IsaPnpBus)
{ {
default: IoSkipCurrentIrpStackLocation(Irp);
DPRINT1("Unknown ioctl code: %x\n", IrpSp->Parameters.DeviceIoControl.IoControlCode); return IoCallDriver(((PISAPNP_FDO_EXTENSION)CommonExt)->Ldo, Irp);
Status = STATUS_NOT_SUPPORTED;
break;
} }
else
{
NTSTATUS Status = Irp->IoStatus.Status;
Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status;
}
return Status;
}
static DRIVER_DISPATCH IsaReadWrite;
static
NTSTATUS
NTAPI
IsaReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp);
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_SUPPORTED;
} }
static static
@ -533,7 +488,7 @@ IsaPnpCreateReadPortDO(
PdoExt = FdoExt->ReadPortPdo->DeviceExtension; PdoExt = FdoExt->ReadPortPdo->DeviceExtension;
RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION)); RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION));
PdoExt->Common.IsFdo = FALSE; PdoExt->Common.Signature = IsaPnpReadDataPort;
PdoExt->Common.Self = FdoExt->ReadPortPdo; PdoExt->Common.Self = FdoExt->ReadPortPdo;
PdoExt->Common.State = dsStopped; PdoExt->Common.State = dsStopped;
PdoExt->FdoExt = FdoExt; PdoExt->FdoExt = FdoExt;
@ -551,17 +506,33 @@ IsaPnpCreateReadPortDO(
return Status; return Status;
Failure: Failure:
if (PdoExt->RequirementsList) IsaPnpRemoveReadPortDO(FdoExt->ReadPortPdo);
ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP);
if (PdoExt->ResourceList) FdoExt->ReadPortPdo = NULL;
ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP);
IoDeleteDevice(FdoExt->ReadPortPdo);
return Status; return Status;
} }
CODE_SEG("PAGE")
VOID
IsaPnpRemoveReadPortDO(
_In_ PDEVICE_OBJECT Pdo)
{
PISAPNP_PDO_EXTENSION ReadPortExt = Pdo->DeviceExtension;
PAGED_CODE();
DPRINT("Removing Read Port\n");
if (ReadPortExt->RequirementsList)
ExFreePoolWithTag(ReadPortExt->RequirementsList, TAG_ISAPNP);
if (ReadPortExt->ResourceList)
ExFreePoolWithTag(ReadPortExt->ResourceList, TAG_ISAPNP);
IoDeleteDevice(Pdo);
}
CODE_SEG("PAGE") CODE_SEG("PAGE")
NTSTATUS NTSTATUS
IsaPnpFillDeviceRelations( IsaPnpFillDeviceRelations(
@ -577,6 +548,8 @@ IsaPnpFillDeviceRelations(
PAGED_CODE(); PAGED_CODE();
IsaPnpAcquireBusDataLock();
/* Try to claim the Read Port for our FDO */ /* Try to claim the Read Port for our FDO */
if (!ReadPortCreated) if (!ReadPortCreated)
{ {
@ -587,26 +560,68 @@ IsaPnpFillDeviceRelations(
ReadPortCreated = TRUE; ReadPortCreated = TRUE;
} }
IsaPnpReleaseBusDataLock();
/* Inactive ISA bus */ /* Inactive ISA bus */
if (!FdoExt->ReadPortPdo) if (!FdoExt->ReadPortPdo)
IncludeDataPort = FALSE; IncludeDataPort = FALSE;
IsaPnpAcquireDeviceDataLock(FdoExt);
/* If called from the FDO dispatch routine && Active bus */
if (IncludeDataPort && FdoExt->ReadPortPdo)
{
PISAPNP_PDO_EXTENSION ReadPortExt = FdoExt->ReadPortPdo->DeviceExtension;
if ((ReadPortExt->Flags & ISAPNP_READ_PORT_ALLOW_FDO_SCAN) &&
!(ReadPortExt->Flags & ISAPNP_SCANNED_BY_READ_PORT))
{
DPRINT("Rescan ISA PnP bus\n");
/* Run the isolation protocol */
if (NT_SUCCESS(IsaHwTryReadDataPort(FdoExt->ReadDataPort)))
{
/* Card identification */
(VOID)IsaHwFillDeviceList(FdoExt);
}
}
ReadPortExt->Flags &= ~ISAPNP_SCANNED_BY_READ_PORT;
}
PdoCount = FdoExt->DeviceCount; PdoCount = FdoExt->DeviceCount;
if (IncludeDataPort) if (IncludeDataPort)
++PdoCount; ++PdoCount;
CurrentEntry = FdoExt->DeviceListHead.Flink;
while (CurrentEntry != &FdoExt->DeviceListHead)
{
IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink);
if (!(IsaDevice->Flags & ISAPNP_PRESENT))
--PdoCount;
CurrentEntry = CurrentEntry->Flink;
}
DeviceRelations = ExAllocatePoolWithTag(PagedPool, DeviceRelations = ExAllocatePoolWithTag(PagedPool,
FIELD_OFFSET(DEVICE_RELATIONS, Objects[PdoCount]), FIELD_OFFSET(DEVICE_RELATIONS, Objects[PdoCount]),
TAG_ISAPNP); TAG_ISAPNP);
if (!DeviceRelations) if (!DeviceRelations)
{ {
IsaPnpReleaseDeviceDataLock(FdoExt);
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
} }
if (IncludeDataPort) if (IncludeDataPort)
{ {
PISAPNP_PDO_EXTENSION ReadPortExt = FdoExt->ReadPortPdo->DeviceExtension;
DeviceRelations->Objects[i++] = FdoExt->ReadPortPdo; DeviceRelations->Objects[i++] = FdoExt->ReadPortPdo;
ObReferenceObject(FdoExt->ReadPortPdo); ObReferenceObject(FdoExt->ReadPortPdo);
/* The Read Port PDO can only be removed by FDO */
ReadPortExt->Flags |= ISAPNP_ENUMERATED;
} }
CurrentEntry = FdoExt->DeviceListHead.Flink; CurrentEntry = FdoExt->DeviceListHead.Flink;
@ -616,6 +631,9 @@ IsaPnpFillDeviceRelations(
IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink); IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink);
if (!(IsaDevice->Flags & ISAPNP_PRESENT))
goto SkipPdo;
if (!IsaDevice->Pdo) if (!IsaDevice->Pdo)
{ {
Status = IoCreateDevice(FdoExt->DriverObject, Status = IoCreateDevice(FdoExt->DriverObject,
@ -626,43 +644,66 @@ IsaPnpFillDeviceRelations(
FALSE, FALSE,
&IsaDevice->Pdo); &IsaDevice->Pdo);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ goto SkipPdo;
break;
}
IsaDevice->Pdo->Flags &= ~DO_DEVICE_INITIALIZING; IsaDevice->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
/* The power pagable flag is always unset */
//Device->Pdo->Flags |= DO_POWER_PAGABLE;
PdoExt = IsaDevice->Pdo->DeviceExtension; PdoExt = IsaDevice->Pdo->DeviceExtension;
RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION)); RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION));
PdoExt->Common.Signature = IsaPnpLogicalDevice;
PdoExt->Common.IsFdo = FALSE;
PdoExt->Common.Self = IsaDevice->Pdo; PdoExt->Common.Self = IsaDevice->Pdo;
PdoExt->Common.State = dsStopped; PdoExt->Common.State = dsStopped;
PdoExt->IsaPnpDevice = IsaDevice; PdoExt->IsaPnpDevice = IsaDevice;
PdoExt->FdoExt = FdoExt; PdoExt->FdoExt = FdoExt;
Status = IsaPnpCreateLogicalDeviceRequirements(PdoExt); if (!NT_SUCCESS(IsaPnpCreateLogicalDeviceRequirements(PdoExt)) ||
!NT_SUCCESS(IsaPnpCreateLogicalDeviceResources(PdoExt)))
if (NT_SUCCESS(Status))
Status = IsaPnpCreateLogicalDeviceResources(PdoExt);
if (!NT_SUCCESS(Status))
{ {
if (PdoExt->RequirementsList)
{
ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP);
PdoExt->RequirementsList = NULL;
}
if (PdoExt->ResourceList)
{
ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP);
PdoExt->ResourceList = NULL;
}
IoDeleteDevice(IsaDevice->Pdo); IoDeleteDevice(IsaDevice->Pdo);
IsaDevice->Pdo = NULL; IsaDevice->Pdo = NULL;
break; goto SkipPdo;
} }
} }
else
{
PdoExt = IsaDevice->Pdo->DeviceExtension;
}
DeviceRelations->Objects[i++] = IsaDevice->Pdo; DeviceRelations->Objects[i++] = IsaDevice->Pdo;
ObReferenceObject(IsaDevice->Pdo); ObReferenceObject(IsaDevice->Pdo);
PdoExt->Flags |= ISAPNP_ENUMERATED;
CurrentEntry = CurrentEntry->Flink;
continue;
SkipPdo:
if (IsaDevice->Pdo)
{
PdoExt = IsaDevice->Pdo->DeviceExtension;
if (PdoExt)
PdoExt->Flags &= ~ISAPNP_ENUMERATED;
}
CurrentEntry = CurrentEntry->Flink; CurrentEntry = CurrentEntry->Flink;
} }
IsaPnpReleaseDeviceDataLock(FdoExt);
DeviceRelations->Count = i; DeviceRelations->Count = i;
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
@ -694,7 +735,7 @@ IsaAddDevice(
NULL, NULL,
FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_BUS_EXTENDER,
FILE_DEVICE_SECURE_OPEN, FILE_DEVICE_SECURE_OPEN,
TRUE, FALSE,
&Fdo); &Fdo);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -706,17 +747,26 @@ IsaAddDevice(
RtlZeroMemory(FdoExt, sizeof(*FdoExt)); RtlZeroMemory(FdoExt, sizeof(*FdoExt));
FdoExt->Common.Self = Fdo; FdoExt->Common.Self = Fdo;
FdoExt->Common.IsFdo = TRUE; FdoExt->Common.Signature = IsaPnpBus;
FdoExt->Common.State = dsStopped; FdoExt->Common.State = dsStopped;
FdoExt->DriverObject = DriverObject; FdoExt->DriverObject = DriverObject;
FdoExt->BusNumber = BusNumber++; FdoExt->BusNumber = BusNumber++;
FdoExt->Pdo = PhysicalDeviceObject; FdoExt->Pdo = PhysicalDeviceObject;
FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo, FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo,
PhysicalDeviceObject); PhysicalDeviceObject);
if (!FdoExt->Ldo)
{
IoDeleteDevice(Fdo);
return STATUS_DEVICE_REMOVED;
}
InitializeListHead(&FdoExt->DeviceListHead); InitializeListHead(&FdoExt->DeviceListHead);
KeInitializeEvent(&FdoExt->DeviceSyncEvent, SynchronizationEvent, TRUE); KeInitializeEvent(&FdoExt->DeviceSyncEvent, SynchronizationEvent, TRUE);
IsaPnpAcquireBusDataLock();
InsertTailList(&BusListHead, &FdoExt->BusLink);
IsaPnpReleaseBusDataLock();
Fdo->Flags &= ~DO_DEVICE_INITIALIZING; Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -735,9 +785,22 @@ IsaPower(
PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension; PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension;
NTSTATUS Status; NTSTATUS Status;
if (!DevExt->IsFdo) if (DevExt->Signature != IsaPnpBus)
{ {
Status = Irp->IoStatus.Status; switch (IoGetCurrentIrpStackLocation(Irp)->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); IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status; return Status;
} }
@ -763,9 +826,7 @@ IsaPnp(
PAGED_CODE(); PAGED_CODE();
DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); if (DevExt->Signature == IsaPnpBus)
if (DevExt->IsFdo)
return IsaFdoPnp((PISAPNP_FDO_EXTENSION)DevExt, Irp, IrpSp); return IsaFdoPnp((PISAPNP_FDO_EXTENSION)DevExt, Irp, IrpSp);
else else
return IsaPdoPnp((PISAPNP_PDO_EXTENSION)DevExt, Irp, IrpSp); return IsaPdoPnp((PISAPNP_PDO_EXTENSION)DevExt, Irp, IrpSp);
@ -782,13 +843,25 @@ DriverEntry(
DriverObject->MajorFunction[IRP_MJ_CREATE] = IsaCreateClose; DriverObject->MajorFunction[IRP_MJ_CREATE] = IsaCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = IsaCreateClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = IsaCreateClose;
DriverObject->MajorFunction[IRP_MJ_READ] = IsaReadWrite; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IsaForwardOrIgnore;
DriverObject->MajorFunction[IRP_MJ_WRITE] = IsaReadWrite; DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IsaForwardOrIgnore;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IsaIoctl;
DriverObject->MajorFunction[IRP_MJ_PNP] = IsaPnp; DriverObject->MajorFunction[IRP_MJ_PNP] = IsaPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = IsaPower; DriverObject->MajorFunction[IRP_MJ_POWER] = IsaPower;
DriverObject->DriverExtension->AddDevice = IsaAddDevice; DriverObject->DriverExtension->AddDevice = IsaAddDevice;
/* FIXME: Fix SDK headers */
#if 0
_No_competing_thread_begin_
#endif
KeInitializeEvent(&BusSyncEvent, SynchronizationEvent, TRUE);
InitializeListHead(&BusListHead);
/* FIXME: Fix SDK headers */
#if 0
_No_competing_thread_end_
#endif
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -9,7 +9,7 @@
#ifndef _ISAPNP_PCH_ #ifndef _ISAPNP_PCH_
#define _ISAPNP_PCH_ #define _ISAPNP_PCH_
#include <wdm.h> #include <ntddk.h>
#include <ntstrsafe.h> #include <ntstrsafe.h>
#include <section_attribs.h> #include <section_attribs.h>
#include "isapnphw.h" #include "isapnphw.h"
@ -60,13 +60,24 @@ typedef struct _ISAPNP_LOGICAL_DEVICE
ISAPNP_DMA Dma[2]; ISAPNP_DMA Dma[2];
UCHAR CSN; UCHAR CSN;
UCHAR LDN; UCHAR LDN;
ULONG Flags;
#define ISAPNP_PRESENT 0x00000001 /**< @brief Cleared when the device is physically removed. */
LIST_ENTRY DeviceLink; LIST_ENTRY DeviceLink;
} ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE; } ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE;
typedef enum _ISAPNP_SIGNATURE
{
IsaPnpBus = 'odFI',
IsaPnpLogicalDevice = 'veDI',
IsaPnpReadDataPort = 'pdRI'
} ISAPNP_SIGNATURE;
typedef struct _ISAPNP_COMMON_EXTENSION typedef struct _ISAPNP_COMMON_EXTENSION
{ {
ISAPNP_SIGNATURE Signature;
PDEVICE_OBJECT Self; PDEVICE_OBJECT Self;
BOOLEAN IsFdo;
ISAPNP_DEVICE_STATE State; ISAPNP_DEVICE_STATE State;
} ISAPNP_COMMON_EXTENSION, *PISAPNP_COMMON_EXTENSION; } ISAPNP_COMMON_EXTENSION, *PISAPNP_COMMON_EXTENSION;
@ -75,13 +86,19 @@ typedef struct _ISAPNP_FDO_EXTENSION
ISAPNP_COMMON_EXTENSION Common; ISAPNP_COMMON_EXTENSION Common;
PDEVICE_OBJECT Ldo; PDEVICE_OBJECT Ldo;
PDEVICE_OBJECT Pdo; PDEVICE_OBJECT Pdo;
PDEVICE_OBJECT ReadPortPdo; PDEVICE_OBJECT ReadPortPdo; /**< @remarks The pointer is NULL for all inactive FDOs. */
ULONG BusNumber; ULONG BusNumber;
KEVENT DeviceSyncEvent; KEVENT DeviceSyncEvent;
_Guarded_by_(DeviceSyncEvent)
LIST_ENTRY DeviceListHead; LIST_ENTRY DeviceListHead;
_Guarded_by_(DeviceSyncEvent)
ULONG DeviceCount; ULONG DeviceCount;
PDRIVER_OBJECT DriverObject; PDRIVER_OBJECT DriverObject;
PUCHAR ReadDataPort; PUCHAR ReadDataPort;
LIST_ENTRY BusLink;
} ISAPNP_FDO_EXTENSION, *PISAPNP_FDO_EXTENSION; } ISAPNP_FDO_EXTENSION, *PISAPNP_FDO_EXTENSION;
typedef struct _ISAPNP_PDO_EXTENSION typedef struct _ISAPNP_PDO_EXTENSION
@ -90,10 +107,44 @@ typedef struct _ISAPNP_PDO_EXTENSION
PISAPNP_LOGICAL_DEVICE IsaPnpDevice; PISAPNP_LOGICAL_DEVICE IsaPnpDevice;
PISAPNP_FDO_EXTENSION FdoExt; PISAPNP_FDO_EXTENSION FdoExt;
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
PCM_RESOURCE_LIST ResourceList; PCM_RESOURCE_LIST ResourceList;
ULONG ResourceListSize; ULONG ResourceListSize;
ULONG Flags;
#define ISAPNP_ENUMERATED 0x00000001 /**< @brief Whether the device has been reported to the PnP manager. */
#define ISAPNP_SCANNED_BY_READ_PORT 0x00000002 /**< @brief The bus has been scanned by Read Port PDO. */
#define ISAPNP_READ_PORT_ALLOW_FDO_SCAN 0x00000004 /**< @brief Allows the active FDO to scan the bus. */
_Write_guarded_by_(_Global_interlock_)
volatile LONG SpecialFiles;
} ISAPNP_PDO_EXTENSION, *PISAPNP_PDO_EXTENSION; } ISAPNP_PDO_EXTENSION, *PISAPNP_PDO_EXTENSION;
extern KEVENT BusSyncEvent;
_Guarded_by_(BusSyncEvent)
extern BOOLEAN ReadPortCreated;
_Guarded_by_(BusSyncEvent)
extern LIST_ENTRY BusListHead;
_Requires_lock_not_held_(BusSyncEvent)
_Acquires_lock_(BusSyncEvent)
FORCEINLINE
VOID
IsaPnpAcquireBusDataLock(VOID)
{
KeWaitForSingleObject(&BusSyncEvent, Executive, KernelMode, FALSE, NULL);
}
_Releases_lock_(BusSyncEvent)
FORCEINLINE
VOID
IsaPnpReleaseBusDataLock(VOID)
{
KeSetEvent(&BusSyncEvent, IO_NO_INCREMENT, FALSE);
}
_Requires_lock_not_held_(FdoExt->DeviceSyncEvent) _Requires_lock_not_held_(FdoExt->DeviceSyncEvent)
_Acquires_lock_(FdoExt->DeviceSyncEvent) _Acquires_lock_(FdoExt->DeviceSyncEvent)
FORCEINLINE FORCEINLINE
@ -115,6 +166,11 @@ IsaPnpReleaseDeviceDataLock(
/* isapnp.c */ /* isapnp.c */
CODE_SEG("PAGE")
VOID
IsaPnpRemoveReadPortDO(
_In_ PDEVICE_OBJECT Pdo);
CODE_SEG("PAGE") CODE_SEG("PAGE")
NTSTATUS NTSTATUS
IsaPnpFillDeviceRelations( IsaPnpFillDeviceRelations(
@ -125,12 +181,6 @@ IsaPnpFillDeviceRelations(
CODE_SEG("INIT") CODE_SEG("INIT")
DRIVER_INITIALIZE DriverEntry; DRIVER_INITIALIZE DriverEntry;
NTSTATUS
NTAPI
IsaForwardIrpSynchronous(
_In_ PISAPNP_FDO_EXTENSION FdoExt,
_Inout_ PIRP Irp);
/* fdo.c */ /* fdo.c */
CODE_SEG("PAGE") CODE_SEG("PAGE")
NTSTATUS NTSTATUS
@ -139,6 +189,13 @@ IsaFdoPnp(
_Inout_ PIRP Irp, _Inout_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp); _In_ PIO_STACK_LOCATION IrpSp);
/* interface.c */
CODE_SEG("PAGE")
NTSTATUS
IsaFdoQueryInterface(
_In_ PISAPNP_FDO_EXTENSION FdoExt,
_In_ PIO_STACK_LOCATION IrpSp);
/* pdo.c */ /* pdo.c */
CODE_SEG("PAGE") CODE_SEG("PAGE")
NTSTATUS NTSTATUS
@ -147,6 +204,11 @@ IsaPdoPnp(
_Inout_ PIRP Irp, _Inout_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp); _In_ PIO_STACK_LOCATION IrpSp);
CODE_SEG("PAGE")
VOID
IsaPnpRemoveLogicalDeviceDO(
_In_ PDEVICE_OBJECT Pdo);
/* hardware.c */ /* hardware.c */
CODE_SEG("PAGE") CODE_SEG("PAGE")
NTSTATUS NTSTATUS

View file

@ -4,6 +4,7 @@
* PURPOSE: PDO-specific code * PURPOSE: PDO-specific code
* COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org> * COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
* Copyright 2020 Hervé Poussineau <hpoussin@reactos.org> * Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
* Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
*/ */
#include "isapnp.h" #include "isapnp.h"
@ -24,7 +25,7 @@ IsaPdoQueryDeviceRelations(
PAGED_CODE(); PAGED_CODE();
if (IrpSp->Parameters.QueryDeviceRelations.Type == RemovalRelations && if (IrpSp->Parameters.QueryDeviceRelations.Type == RemovalRelations &&
PdoExt->Common.Self == PdoExt->FdoExt->ReadPortPdo) PdoExt->Common.Signature == IsaPnpReadDataPort)
{ {
return IsaPnpFillDeviceRelations(PdoExt->FdoExt, Irp, FALSE); return IsaPnpFillDeviceRelations(PdoExt->FdoExt, Irp, FALSE);
} }
@ -70,8 +71,7 @@ IsaPdoQueryCapabilities(
DeviceCapabilities->UniqueID = TRUE; DeviceCapabilities->UniqueID = TRUE;
if (PdoExt->FdoExt->ReadPortPdo && if (PdoExt->Common.Signature == IsaPnpReadDataPort)
PdoExt->Common.Self == PdoExt->FdoExt->ReadPortPdo)
{ {
DeviceCapabilities->RawDeviceOK = TRUE; DeviceCapabilities->RawDeviceOK = TRUE;
DeviceCapabilities->SilentInstall = TRUE; DeviceCapabilities->SilentInstall = TRUE;
@ -89,13 +89,17 @@ CODE_SEG("PAGE")
NTSTATUS NTSTATUS
IsaPdoQueryPnpDeviceState( IsaPdoQueryPnpDeviceState(
_In_ PISAPNP_PDO_EXTENSION PdoExt, _In_ PISAPNP_PDO_EXTENSION PdoExt,
_Inout_ PIRP Irp, _Inout_ PIRP Irp)
_In_ PIO_STACK_LOCATION IrpSp)
{ {
PAGED_CODE(); PAGED_CODE();
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; if (PdoExt->SpecialFiles > 0)
return STATUS_SUCCESS; {
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
return STATUS_SUCCESS;
}
return Irp->IoStatus.Status;
} }
static static
@ -319,6 +323,8 @@ IsaPdoQueryResources(
ULONG ListSize; ULONG ListSize;
PCM_RESOURCE_LIST ResourceList; PCM_RESOURCE_LIST ResourceList;
UNREFERENCED_PARAMETER(IrpSp);
PAGED_CODE(); PAGED_CODE();
if (!PdoExt->ResourceList) if (!PdoExt->ResourceList)
@ -345,6 +351,8 @@ IsaPdoQueryResourceRequirements(
ULONG ListSize; ULONG ListSize;
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
UNREFERENCED_PARAMETER(IrpSp);
PAGED_CODE(); PAGED_CODE();
if (!PdoExt->RequirementsList) if (!PdoExt->RequirementsList)
@ -367,6 +375,7 @@ IsaPdoStartReadPort(
_In_ PISAPNP_FDO_EXTENSION FdoExt, _In_ PISAPNP_FDO_EXTENSION FdoExt,
_In_ PIO_STACK_LOCATION IrpSp) _In_ PIO_STACK_LOCATION IrpSp)
{ {
PISAPNP_PDO_EXTENSION PdoExt = FdoExt->ReadPortPdo->DeviceExtension;
PCM_RESOURCE_LIST ResourceList = IrpSp->Parameters.StartDevice.AllocatedResources; PCM_RESOURCE_LIST ResourceList = IrpSp->Parameters.StartDevice.AllocatedResources;
NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
ULONG i; ULONG i;
@ -410,6 +419,9 @@ IsaPdoStartReadPort(
if (FdoExt->DeviceCount > 0) if (FdoExt->DeviceCount > 0)
{ {
PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN |
ISAPNP_SCANNED_BY_READ_PORT;
IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations); IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations);
IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations); IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations);
} }
@ -426,61 +438,19 @@ IsaPdoStartReadPort(
} }
static static
CODE_SEG("PAGE")
NTSTATUS NTSTATUS
NTAPI IsaPdoFilterResourceRequirements(
IsaPdoOnRepeaterComplete(
PDEVICE_OBJECT Tdo,
PIRP SubIrp,
PVOID NeedsVote)
{
PIO_STACK_LOCATION SubStack = IoGetCurrentIrpStackLocation(SubIrp);
PIRP Irp = (PIRP)SubStack->Parameters.Others.Argument1;
ObDereferenceObject(Tdo);
if (SubIrp->IoStatus.Status == STATUS_NOT_SUPPORTED)
{
if (NeedsVote)
{
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
}
}
else
{
Irp->IoStatus = SubIrp->IoStatus;
}
IoFreeIrp(SubIrp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
NTAPI
IsaPdoRepeatRequest(
_In_ PISAPNP_PDO_EXTENSION PdoExt, _In_ PISAPNP_PDO_EXTENSION PdoExt,
_In_ PIRP Irp, _Inout_ PIRP Irp,
_In_ BOOLEAN NeedsVote) _In_ PIO_STACK_LOCATION IrpSp)
{ {
PDEVICE_OBJECT Fdo = PdoExt->FdoExt->Common.Self; PAGED_CODE();
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_OBJECT Tdo = IoGetAttachedDeviceReference(Fdo);
PIRP SubIrp = IoAllocateIrp(Tdo->StackSize + 1, FALSE);
PIO_STACK_LOCATION SubStack = IoGetNextIrpStackLocation(SubIrp);
SubStack->DeviceObject = Tdo; /* TODO: Handle */
SubStack->Parameters.Others.Argument1 = (PVOID)Irp; UNREFERENCED_PARAMETER(PdoExt);
UNREFERENCED_PARAMETER(IrpSp);
IoSetNextIrpStackLocation(SubIrp); return Irp->IoStatus.Status;
SubStack = IoGetNextIrpStackLocation(SubIrp);
RtlCopyMemory(SubStack, Stack, FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine));
SubStack->Control = 0;
IoSetCompletionRoutine(SubIrp, IsaPdoOnRepeaterComplete, (PVOID)(ULONG_PTR)NeedsVote, TRUE, TRUE, TRUE);
SubIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoMarkIrpPending(Irp);
IoCallDriver(Tdo, SubIrp);
return STATUS_PENDING;
} }
static static
@ -508,6 +478,124 @@ IsaPdoQueryBusInformation(
return STATUS_SUCCESS; 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") CODE_SEG("PAGE")
NTSTATUS NTSTATUS
IsaPdoPnp( IsaPdoPnp(
@ -519,10 +607,29 @@ IsaPdoPnp(
PAGED_CODE(); 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) switch (IrpSp->MinorFunction)
{ {
case IRP_MN_START_DEVICE: case IRP_MN_START_DEVICE:
if (PdoExt->IsaPnpDevice) if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
Status = IsaHwActivateDevice(PdoExt->IsaPnpDevice); Status = IsaHwActivateDevice(PdoExt->IsaPnpDevice);
else else
Status = IsaPdoStartReadPort(PdoExt->FdoExt, IrpSp); Status = IsaPdoStartReadPort(PdoExt->FdoExt, IrpSp);
@ -532,15 +639,36 @@ IsaPdoPnp(
break; break;
case IRP_MN_STOP_DEVICE: case IRP_MN_STOP_DEVICE:
if (PdoExt->IsaPnpDevice) if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
Status = IsaHwDeactivateDevice(PdoExt->IsaPnpDevice); Status = IsaHwDeactivateDevice(PdoExt->IsaPnpDevice);
else else
{
PdoExt->Flags &= ~ISAPNP_READ_PORT_ALLOW_FDO_SCAN;
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
}
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
PdoExt->Common.State = dsStopped; PdoExt->Common.State = dsStopped;
break; break;
case IRP_MN_QUERY_STOP_DEVICE:
{
if (PdoExt->SpecialFiles > 0)
Status = STATUS_DEVICE_BUSY;
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: case IRP_MN_QUERY_DEVICE_RELATIONS:
Status = IsaPdoQueryDeviceRelations(PdoExt, Irp, IrpSp); Status = IsaPdoQueryDeviceRelations(PdoExt, Irp, IrpSp);
break; break;
@ -549,9 +677,22 @@ IsaPdoPnp(
Status = IsaPdoQueryCapabilities(PdoExt, Irp, IrpSp); Status = IsaPdoQueryCapabilities(PdoExt, Irp, IrpSp);
break; 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: case IRP_MN_QUERY_PNP_DEVICE_STATE:
if (PdoExt->Common.Self == PdoExt->FdoExt->ReadPortPdo) Status = IsaPdoQueryPnpDeviceState(PdoExt, Irp);
Status = IsaPdoQueryPnpDeviceState(PdoExt, Irp, IrpSp);
break; break;
case IRP_MN_QUERY_RESOURCES: case IRP_MN_QUERY_RESOURCES:
@ -563,36 +704,31 @@ IsaPdoPnp(
break; break;
case IRP_MN_QUERY_ID: case IRP_MN_QUERY_ID:
if (PdoExt->IsaPnpDevice) if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
Status = IsaPdoQueryId(PdoExt, Irp, IrpSp); Status = IsaPdoQueryId(PdoExt, Irp, IrpSp);
else else
Status = IsaReadPortQueryId(Irp, IrpSp); Status = IsaReadPortQueryId(Irp, IrpSp);
break; break;
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
Status = IsaPdoFilterResourceRequirements(PdoExt, Irp, IrpSp);
break;
case IRP_MN_QUERY_BUS_INFORMATION: case IRP_MN_QUERY_BUS_INFORMATION:
Status = IsaPdoQueryBusInformation(PdoExt, Irp); Status = IsaPdoQueryBusInformation(PdoExt, Irp);
break; break;
case IRP_MN_QUERY_REMOVE_DEVICE: case IRP_MN_DEVICE_USAGE_NOTIFICATION:
case IRP_MN_REMOVE_DEVICE: Status = IsaPdoQueryDeviceUsageNotification(PdoExt, Irp, IrpSp);
break;
case IRP_MN_CANCEL_REMOVE_DEVICE: case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE: case IRP_MN_CANCEL_STOP_DEVICE:
case IRP_MN_QUERY_DEVICE_TEXT:
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
case IRP_MN_SURPRISE_REMOVAL:
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
break; break;
case IRP_MN_READ_CONFIG:
case IRP_MN_WRITE_CONFIG:
case IRP_MN_EJECT:
case IRP_MN_SET_LOCK:
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
return IsaPdoRepeatRequest(PdoExt, Irp, TRUE);
default: default:
DPRINT1("Unknown PnP code: %x\n", IrpSp->MinorFunction); DPRINT("Unknown PnP code: %X\n", IrpSp->MinorFunction);
break; break;
} }