mirror of
https://github.com/reactos/reactos.git
synced 2024-11-24 03:53:31 +08:00
[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:
parent
e19595572a
commit
f15de15554
@ -4,6 +4,7 @@ list(APPEND SOURCE
|
||||
pdo.c
|
||||
fdo.c
|
||||
hardware.c
|
||||
interface.c
|
||||
isapnp.h)
|
||||
|
||||
add_library(isapnp MODULE ${SOURCE} isapnp.rc)
|
||||
|
@ -4,6 +4,7 @@
|
||||
* PURPOSE: FDO-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"
|
||||
@ -16,14 +17,22 @@ CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
IsaFdoStartDevice(
|
||||
_In_ PISAPNP_FDO_EXTENSION FdoExt,
|
||||
_Inout_ PIRP Irp,
|
||||
_In_ PIO_STACK_LOCATION IrpSp)
|
||||
_Inout_ PIRP Irp)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Irp);
|
||||
UNREFERENCED_PARAMETER(IrpSp);
|
||||
NTSTATUS Status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
if (!IoForwardIrpSynchronously(FdoExt->Ldo, Irp))
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
Status = Irp->IoStatus.Status;
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
FdoExt->Common.State = dsStarted;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
@ -32,19 +41,83 @@ IsaFdoStartDevice(
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
IsaFdoQueryDeviceRelations(
|
||||
IsaFdoQueryBusRelations(
|
||||
_In_ PISAPNP_FDO_EXTENSION FdoExt,
|
||||
_Inout_ PIRP Irp,
|
||||
_In_ PIO_STACK_LOCATION IrpSp)
|
||||
_Inout_ PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
|
||||
return Irp->IoStatus.Status;
|
||||
|
||||
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")
|
||||
NTSTATUS
|
||||
IsaFdoPnp(
|
||||
@ -52,43 +125,82 @@ IsaFdoPnp(
|
||||
_Inout_ PIRP Irp,
|
||||
_In_ PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
NTSTATUS Status = Irp->IoStatus.Status;
|
||||
NTSTATUS Status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("%s(%p, %p) FDO %lu, Minor - %X\n",
|
||||
__FUNCTION__,
|
||||
FdoExt,
|
||||
Irp,
|
||||
FdoExt->BusNumber,
|
||||
IrpSp->MinorFunction);
|
||||
|
||||
switch (IrpSp->MinorFunction)
|
||||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
Status = IsaForwardIrpSynchronous(FdoExt, Irp);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
Status = IsaFdoStartDevice(FdoExt, Irp, IrpSp);
|
||||
Status = IsaFdoStartDevice(FdoExt, Irp);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
|
||||
case IRP_MN_STOP_DEVICE:
|
||||
FdoExt->Common.State = dsStopped;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
return IsaFdoRemoveDevice(FdoExt, Irp);
|
||||
|
||||
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
|
||||
DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
|
||||
case IRP_MN_QUERY_PNP_DEVICE_STATE:
|
||||
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;
|
||||
|
||||
default:
|
||||
DPRINT1("Unknown PnP code: %x\n", IrpSp->MinorFunction);
|
||||
DPRINT("Unknown PnP code: %X\n", IrpSp->MinorFunction);
|
||||
break;
|
||||
}
|
||||
|
||||
|
73
drivers/bus/isapnp/interface.c
Normal file
73
drivers/bus/isapnp/interface.c
Normal 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;
|
||||
}
|
@ -4,15 +4,28 @@
|
||||
* PURPOSE: Driver entry
|
||||
* COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
|
||||
* Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
|
||||
* Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "isapnp.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
KEVENT BusSyncEvent;
|
||||
|
||||
_Guarded_by_(BusSyncEvent)
|
||||
BOOLEAN ReadPortCreated = FALSE;
|
||||
|
||||
_Guarded_by_(BusSyncEvent)
|
||||
LIST_ENTRY BusListHead;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
@ -301,49 +314,6 @@ IsaPnpCreateLogicalDeviceResources(
|
||||
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_CLOSE)
|
||||
static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaCreateClose;
|
||||
@ -359,7 +329,6 @@ IsaCreateClose(
|
||||
PAGED_CODE();
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = FILE_OPENED;
|
||||
|
||||
DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp);
|
||||
|
||||
@ -368,51 +337,37 @@ IsaCreateClose(
|
||||
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
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IsaIoctl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
IsaForwardOrIgnore(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_Inout_ PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
NTSTATUS Status;
|
||||
PISAPNP_COMMON_EXTENSION CommonExt = DeviceObject->DeviceExtension;
|
||||
|
||||
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:
|
||||
DPRINT1("Unknown ioctl code: %x\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
|
||||
Status = STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(((PISAPNP_FDO_EXTENSION)CommonExt)->Ldo, Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
NTSTATUS Status = Irp->IoStatus.Status;
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
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;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
@ -533,7 +488,7 @@ IsaPnpCreateReadPortDO(
|
||||
|
||||
PdoExt = FdoExt->ReadPortPdo->DeviceExtension;
|
||||
RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION));
|
||||
PdoExt->Common.IsFdo = FALSE;
|
||||
PdoExt->Common.Signature = IsaPnpReadDataPort;
|
||||
PdoExt->Common.Self = FdoExt->ReadPortPdo;
|
||||
PdoExt->Common.State = dsStopped;
|
||||
PdoExt->FdoExt = FdoExt;
|
||||
@ -551,17 +506,33 @@ IsaPnpCreateReadPortDO(
|
||||
return Status;
|
||||
|
||||
Failure:
|
||||
if (PdoExt->RequirementsList)
|
||||
ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP);
|
||||
IsaPnpRemoveReadPortDO(FdoExt->ReadPortPdo);
|
||||
|
||||
if (PdoExt->ResourceList)
|
||||
ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP);
|
||||
|
||||
IoDeleteDevice(FdoExt->ReadPortPdo);
|
||||
FdoExt->ReadPortPdo = NULL;
|
||||
|
||||
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")
|
||||
NTSTATUS
|
||||
IsaPnpFillDeviceRelations(
|
||||
@ -577,6 +548,8 @@ IsaPnpFillDeviceRelations(
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
IsaPnpAcquireBusDataLock();
|
||||
|
||||
/* Try to claim the Read Port for our FDO */
|
||||
if (!ReadPortCreated)
|
||||
{
|
||||
@ -587,26 +560,68 @@ IsaPnpFillDeviceRelations(
|
||||
ReadPortCreated = TRUE;
|
||||
}
|
||||
|
||||
IsaPnpReleaseBusDataLock();
|
||||
|
||||
/* Inactive ISA bus */
|
||||
if (!FdoExt->ReadPortPdo)
|
||||
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;
|
||||
if (IncludeDataPort)
|
||||
++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,
|
||||
FIELD_OFFSET(DEVICE_RELATIONS, Objects[PdoCount]),
|
||||
TAG_ISAPNP);
|
||||
if (!DeviceRelations)
|
||||
{
|
||||
IsaPnpReleaseDeviceDataLock(FdoExt);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (IncludeDataPort)
|
||||
{
|
||||
PISAPNP_PDO_EXTENSION ReadPortExt = FdoExt->ReadPortPdo->DeviceExtension;
|
||||
|
||||
DeviceRelations->Objects[i++] = FdoExt->ReadPortPdo;
|
||||
ObReferenceObject(FdoExt->ReadPortPdo);
|
||||
|
||||
/* The Read Port PDO can only be removed by FDO */
|
||||
ReadPortExt->Flags |= ISAPNP_ENUMERATED;
|
||||
}
|
||||
|
||||
CurrentEntry = FdoExt->DeviceListHead.Flink;
|
||||
@ -616,6 +631,9 @@ IsaPnpFillDeviceRelations(
|
||||
|
||||
IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink);
|
||||
|
||||
if (!(IsaDevice->Flags & ISAPNP_PRESENT))
|
||||
goto SkipPdo;
|
||||
|
||||
if (!IsaDevice->Pdo)
|
||||
{
|
||||
Status = IoCreateDevice(FdoExt->DriverObject,
|
||||
@ -626,43 +644,66 @@ IsaPnpFillDeviceRelations(
|
||||
FALSE,
|
||||
&IsaDevice->Pdo);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
break;
|
||||
}
|
||||
goto SkipPdo;
|
||||
|
||||
IsaDevice->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
//Device->Pdo->Flags |= DO_POWER_PAGABLE;
|
||||
/* The power pagable flag is always unset */
|
||||
|
||||
PdoExt = IsaDevice->Pdo->DeviceExtension;
|
||||
|
||||
RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION));
|
||||
|
||||
PdoExt->Common.IsFdo = FALSE;
|
||||
PdoExt->Common.Signature = IsaPnpLogicalDevice;
|
||||
PdoExt->Common.Self = IsaDevice->Pdo;
|
||||
PdoExt->Common.State = dsStopped;
|
||||
PdoExt->IsaPnpDevice = IsaDevice;
|
||||
PdoExt->FdoExt = FdoExt;
|
||||
|
||||
Status = IsaPnpCreateLogicalDeviceRequirements(PdoExt);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
Status = IsaPnpCreateLogicalDeviceResources(PdoExt);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
if (!NT_SUCCESS(IsaPnpCreateLogicalDeviceRequirements(PdoExt)) ||
|
||||
!NT_SUCCESS(IsaPnpCreateLogicalDeviceResources(PdoExt)))
|
||||
{
|
||||
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);
|
||||
IsaDevice->Pdo = NULL;
|
||||
break;
|
||||
goto SkipPdo;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PdoExt = IsaDevice->Pdo->DeviceExtension;
|
||||
}
|
||||
DeviceRelations->Objects[i++] = 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;
|
||||
}
|
||||
|
||||
IsaPnpReleaseDeviceDataLock(FdoExt);
|
||||
|
||||
DeviceRelations->Count = i;
|
||||
|
||||
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
|
||||
@ -694,7 +735,7 @@ IsaAddDevice(
|
||||
NULL,
|
||||
FILE_DEVICE_BUS_EXTENDER,
|
||||
FILE_DEVICE_SECURE_OPEN,
|
||||
TRUE,
|
||||
FALSE,
|
||||
&Fdo);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
@ -706,17 +747,26 @@ IsaAddDevice(
|
||||
RtlZeroMemory(FdoExt, sizeof(*FdoExt));
|
||||
|
||||
FdoExt->Common.Self = Fdo;
|
||||
FdoExt->Common.IsFdo = TRUE;
|
||||
FdoExt->Common.Signature = IsaPnpBus;
|
||||
FdoExt->Common.State = dsStopped;
|
||||
FdoExt->DriverObject = DriverObject;
|
||||
FdoExt->BusNumber = BusNumber++;
|
||||
FdoExt->Pdo = PhysicalDeviceObject;
|
||||
FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo,
|
||||
PhysicalDeviceObject);
|
||||
if (!FdoExt->Ldo)
|
||||
{
|
||||
IoDeleteDevice(Fdo);
|
||||
return STATUS_DEVICE_REMOVED;
|
||||
}
|
||||
|
||||
InitializeListHead(&FdoExt->DeviceListHead);
|
||||
KeInitializeEvent(&FdoExt->DeviceSyncEvent, SynchronizationEvent, TRUE);
|
||||
|
||||
IsaPnpAcquireBusDataLock();
|
||||
InsertTailList(&BusListHead, &FdoExt->BusLink);
|
||||
IsaPnpReleaseBusDataLock();
|
||||
|
||||
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
@ -735,9 +785,22 @@ IsaPower(
|
||||
PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension;
|
||||
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);
|
||||
return Status;
|
||||
}
|
||||
@ -763,9 +826,7 @@ IsaPnp(
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp);
|
||||
|
||||
if (DevExt->IsFdo)
|
||||
if (DevExt->Signature == IsaPnpBus)
|
||||
return IsaFdoPnp((PISAPNP_FDO_EXTENSION)DevExt, Irp, IrpSp);
|
||||
else
|
||||
return IsaPdoPnp((PISAPNP_PDO_EXTENSION)DevExt, Irp, IrpSp);
|
||||
@ -782,13 +843,25 @@ DriverEntry(
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = IsaCreateClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = IsaCreateClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = IsaReadWrite;
|
||||
DriverObject->MajorFunction[IRP_MJ_WRITE] = IsaReadWrite;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IsaIoctl;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IsaForwardOrIgnore;
|
||||
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IsaForwardOrIgnore;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = IsaPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = IsaPower;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#ifndef _ISAPNP_PCH_
|
||||
#define _ISAPNP_PCH_
|
||||
|
||||
#include <wdm.h>
|
||||
#include <ntddk.h>
|
||||
#include <ntstrsafe.h>
|
||||
#include <section_attribs.h>
|
||||
#include "isapnphw.h"
|
||||
@ -60,13 +60,24 @@ typedef struct _ISAPNP_LOGICAL_DEVICE
|
||||
ISAPNP_DMA Dma[2];
|
||||
UCHAR CSN;
|
||||
UCHAR LDN;
|
||||
|
||||
ULONG Flags;
|
||||
#define ISAPNP_PRESENT 0x00000001 /**< @brief Cleared when the device is physically removed. */
|
||||
|
||||
LIST_ENTRY DeviceLink;
|
||||
} ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE;
|
||||
|
||||
typedef enum _ISAPNP_SIGNATURE
|
||||
{
|
||||
IsaPnpBus = 'odFI',
|
||||
IsaPnpLogicalDevice = 'veDI',
|
||||
IsaPnpReadDataPort = 'pdRI'
|
||||
} ISAPNP_SIGNATURE;
|
||||
|
||||
typedef struct _ISAPNP_COMMON_EXTENSION
|
||||
{
|
||||
ISAPNP_SIGNATURE Signature;
|
||||
PDEVICE_OBJECT Self;
|
||||
BOOLEAN IsFdo;
|
||||
ISAPNP_DEVICE_STATE State;
|
||||
} ISAPNP_COMMON_EXTENSION, *PISAPNP_COMMON_EXTENSION;
|
||||
|
||||
@ -75,13 +86,19 @@ typedef struct _ISAPNP_FDO_EXTENSION
|
||||
ISAPNP_COMMON_EXTENSION Common;
|
||||
PDEVICE_OBJECT Ldo;
|
||||
PDEVICE_OBJECT Pdo;
|
||||
PDEVICE_OBJECT ReadPortPdo;
|
||||
PDEVICE_OBJECT ReadPortPdo; /**< @remarks The pointer is NULL for all inactive FDOs. */
|
||||
ULONG BusNumber;
|
||||
KEVENT DeviceSyncEvent;
|
||||
|
||||
_Guarded_by_(DeviceSyncEvent)
|
||||
LIST_ENTRY DeviceListHead;
|
||||
|
||||
_Guarded_by_(DeviceSyncEvent)
|
||||
ULONG DeviceCount;
|
||||
|
||||
PDRIVER_OBJECT DriverObject;
|
||||
PUCHAR ReadDataPort;
|
||||
LIST_ENTRY BusLink;
|
||||
} ISAPNP_FDO_EXTENSION, *PISAPNP_FDO_EXTENSION;
|
||||
|
||||
typedef struct _ISAPNP_PDO_EXTENSION
|
||||
@ -90,10 +107,44 @@ typedef struct _ISAPNP_PDO_EXTENSION
|
||||
PISAPNP_LOGICAL_DEVICE IsaPnpDevice;
|
||||
PISAPNP_FDO_EXTENSION FdoExt;
|
||||
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
|
||||
|
||||
PCM_RESOURCE_LIST ResourceList;
|
||||
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;
|
||||
|
||||
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)
|
||||
_Acquires_lock_(FdoExt->DeviceSyncEvent)
|
||||
FORCEINLINE
|
||||
@ -115,6 +166,11 @@ IsaPnpReleaseDeviceDataLock(
|
||||
|
||||
/* isapnp.c */
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
IsaPnpRemoveReadPortDO(
|
||||
_In_ PDEVICE_OBJECT Pdo);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
IsaPnpFillDeviceRelations(
|
||||
@ -125,12 +181,6 @@ IsaPnpFillDeviceRelations(
|
||||
CODE_SEG("INIT")
|
||||
DRIVER_INITIALIZE DriverEntry;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IsaForwardIrpSynchronous(
|
||||
_In_ PISAPNP_FDO_EXTENSION FdoExt,
|
||||
_Inout_ PIRP Irp);
|
||||
|
||||
/* fdo.c */
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
@ -139,6 +189,13 @@ IsaFdoPnp(
|
||||
_Inout_ PIRP Irp,
|
||||
_In_ PIO_STACK_LOCATION IrpSp);
|
||||
|
||||
/* interface.c */
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
IsaFdoQueryInterface(
|
||||
_In_ PISAPNP_FDO_EXTENSION FdoExt,
|
||||
_In_ PIO_STACK_LOCATION IrpSp);
|
||||
|
||||
/* pdo.c */
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
@ -147,6 +204,11 @@ IsaPdoPnp(
|
||||
_Inout_ PIRP Irp,
|
||||
_In_ PIO_STACK_LOCATION IrpSp);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
IsaPnpRemoveLogicalDeviceDO(
|
||||
_In_ PDEVICE_OBJECT Pdo);
|
||||
|
||||
/* hardware.c */
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
|
@ -4,6 +4,7 @@
|
||||
* 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"
|
||||
@ -24,7 +25,7 @@ IsaPdoQueryDeviceRelations(
|
||||
PAGED_CODE();
|
||||
|
||||
if (IrpSp->Parameters.QueryDeviceRelations.Type == RemovalRelations &&
|
||||
PdoExt->Common.Self == PdoExt->FdoExt->ReadPortPdo)
|
||||
PdoExt->Common.Signature == IsaPnpReadDataPort)
|
||||
{
|
||||
return IsaPnpFillDeviceRelations(PdoExt->FdoExt, Irp, FALSE);
|
||||
}
|
||||
@ -70,8 +71,7 @@ IsaPdoQueryCapabilities(
|
||||
|
||||
DeviceCapabilities->UniqueID = TRUE;
|
||||
|
||||
if (PdoExt->FdoExt->ReadPortPdo &&
|
||||
PdoExt->Common.Self == PdoExt->FdoExt->ReadPortPdo)
|
||||
if (PdoExt->Common.Signature == IsaPnpReadDataPort)
|
||||
{
|
||||
DeviceCapabilities->RawDeviceOK = TRUE;
|
||||
DeviceCapabilities->SilentInstall = TRUE;
|
||||
@ -89,13 +89,17 @@ CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
IsaPdoQueryPnpDeviceState(
|
||||
_In_ PISAPNP_PDO_EXTENSION PdoExt,
|
||||
_Inout_ PIRP Irp,
|
||||
_In_ PIO_STACK_LOCATION IrpSp)
|
||||
_Inout_ PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
|
||||
return STATUS_SUCCESS;
|
||||
if (PdoExt->SpecialFiles > 0)
|
||||
{
|
||||
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
static
|
||||
@ -319,6 +323,8 @@ IsaPdoQueryResources(
|
||||
ULONG ListSize;
|
||||
PCM_RESOURCE_LIST ResourceList;
|
||||
|
||||
UNREFERENCED_PARAMETER(IrpSp);
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
if (!PdoExt->ResourceList)
|
||||
@ -345,6 +351,8 @@ IsaPdoQueryResourceRequirements(
|
||||
ULONG ListSize;
|
||||
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
|
||||
|
||||
UNREFERENCED_PARAMETER(IrpSp);
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
if (!PdoExt->RequirementsList)
|
||||
@ -367,6 +375,7 @@ IsaPdoStartReadPort(
|
||||
_In_ PISAPNP_FDO_EXTENSION FdoExt,
|
||||
_In_ PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PISAPNP_PDO_EXTENSION PdoExt = FdoExt->ReadPortPdo->DeviceExtension;
|
||||
PCM_RESOURCE_LIST ResourceList = IrpSp->Parameters.StartDevice.AllocatedResources;
|
||||
NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
ULONG i;
|
||||
@ -410,6 +419,9 @@ IsaPdoStartReadPort(
|
||||
|
||||
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);
|
||||
}
|
||||
@ -426,61 +438,19 @@ IsaPdoStartReadPort(
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
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(
|
||||
IsaPdoFilterResourceRequirements(
|
||||
_In_ PISAPNP_PDO_EXTENSION PdoExt,
|
||||
_In_ PIRP Irp,
|
||||
_In_ BOOLEAN NeedsVote)
|
||||
_Inout_ PIRP Irp,
|
||||
_In_ PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PDEVICE_OBJECT Fdo = PdoExt->FdoExt->Common.Self;
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PDEVICE_OBJECT Tdo = IoGetAttachedDeviceReference(Fdo);
|
||||
PIRP SubIrp = IoAllocateIrp(Tdo->StackSize + 1, FALSE);
|
||||
PIO_STACK_LOCATION SubStack = IoGetNextIrpStackLocation(SubIrp);
|
||||
PAGED_CODE();
|
||||
|
||||
SubStack->DeviceObject = Tdo;
|
||||
SubStack->Parameters.Others.Argument1 = (PVOID)Irp;
|
||||
|
||||
IoSetNextIrpStackLocation(SubIrp);
|
||||
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;
|
||||
/* TODO: Handle */
|
||||
UNREFERENCED_PARAMETER(PdoExt);
|
||||
UNREFERENCED_PARAMETER(IrpSp);
|
||||
return Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
static
|
||||
@ -508,6 +478,124 @@ IsaPdoQueryBusInformation(
|
||||
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(
|
||||
@ -519,10 +607,29 @@ IsaPdoPnp(
|
||||
|
||||
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->IsaPnpDevice)
|
||||
if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
|
||||
Status = IsaHwActivateDevice(PdoExt->IsaPnpDevice);
|
||||
else
|
||||
Status = IsaPdoStartReadPort(PdoExt->FdoExt, IrpSp);
|
||||
@ -532,15 +639,36 @@ IsaPdoPnp(
|
||||
break;
|
||||
|
||||
case IRP_MN_STOP_DEVICE:
|
||||
if (PdoExt->IsaPnpDevice)
|
||||
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
|
||||
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;
|
||||
@ -549,9 +677,22 @@ IsaPdoPnp(
|
||||
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:
|
||||
if (PdoExt->Common.Self == PdoExt->FdoExt->ReadPortPdo)
|
||||
Status = IsaPdoQueryPnpDeviceState(PdoExt, Irp, IrpSp);
|
||||
Status = IsaPdoQueryPnpDeviceState(PdoExt, Irp);
|
||||
break;
|
||||
|
||||
case IRP_MN_QUERY_RESOURCES:
|
||||
@ -563,36 +704,31 @@ IsaPdoPnp(
|
||||
break;
|
||||
|
||||
case IRP_MN_QUERY_ID:
|
||||
if (PdoExt->IsaPnpDevice)
|
||||
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_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
|
||||
Status = IsaPdoQueryDeviceUsageNotification(PdoExt, Irp, IrpSp);
|
||||
break;
|
||||
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
case IRP_MN_QUERY_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;
|
||||
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:
|
||||
DPRINT1("Unknown PnP code: %x\n", IrpSp->MinorFunction);
|
||||
DPRINT("Unknown PnP code: %X\n", IrpSp->MinorFunction);
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user