From 70ba96f1649d10f43563287161e6276f6d9d47a8 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 4 Mar 2021 18:43:44 +0600 Subject: [PATCH] [ISAPNP] Make the driver pageable --- drivers/bus/isapnp/fdo.c | 14 ++++++++--- drivers/bus/isapnp/hardware.c | 31 ++++++++++++++++++++--- drivers/bus/isapnp/isapnp.c | 45 ++++++++++++++++++++++++++-------- drivers/bus/isapnp/isapnp.h | 37 ++++++++++++++++++++++------ drivers/bus/isapnp/pdo.c | 46 ++++++++++++++++++++++++++--------- 5 files changed, 137 insertions(+), 36 deletions(-) diff --git a/drivers/bus/isapnp/fdo.c b/drivers/bus/isapnp/fdo.c index b1d5781ea48..7b32e790246 100644 --- a/drivers/bus/isapnp/fdo.c +++ b/drivers/bus/isapnp/fdo.c @@ -11,8 +11,9 @@ #define NDEBUG #include +static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaFdoStartDevice( _In_ PISAPNP_FDO_EXTENSION FdoExt, _Inout_ PIRP Irp, @@ -21,26 +22,31 @@ IsaFdoStartDevice( UNREFERENCED_PARAMETER(Irp); UNREFERENCED_PARAMETER(IrpSp); + PAGED_CODE(); + FdoExt->Common.State = dsStarted; return STATUS_SUCCESS; } +static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaFdoQueryDeviceRelations( _In_ PISAPNP_FDO_EXTENSION FdoExt, _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IrpSp) { + PAGED_CODE(); + if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations) return Irp->IoStatus.Status; return IsaPnpFillDeviceRelations(FdoExt, Irp, TRUE); } +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaFdoPnp( _In_ PISAPNP_FDO_EXTENSION FdoExt, _Inout_ PIRP Irp, @@ -48,6 +54,8 @@ IsaFdoPnp( { NTSTATUS Status = Irp->IoStatus.Status; + PAGED_CODE(); + switch (IrpSp->MinorFunction) { case IRP_MN_START_DEVICE: diff --git a/drivers/bus/isapnp/hardware.c b/drivers/bus/isapnp/hardware.c index d9146f15754..5922049864f 100644 --- a/drivers/bus/isapnp/hardware.c +++ b/drivers/bus/isapnp/hardware.c @@ -250,12 +250,15 @@ SendKey(VOID) } static +CODE_SEG("PAGE") USHORT PeekByte( _In_ PUCHAR ReadDataPort) { USHORT i; + PAGED_CODE(); + for (i = 0; i < 20; i++) { if (ReadStatus(ReadDataPort) & 0x01) @@ -268,6 +271,7 @@ PeekByte( } static +CODE_SEG("PAGE") VOID Peek( _In_ PUCHAR ReadDataPort, @@ -276,6 +280,8 @@ Peek( { USHORT i, Byte; + PAGED_CODE(); + for (i = 0; i < Length; i++) { Byte = PeekByte(ReadDataPort); @@ -285,12 +291,15 @@ Peek( } static +CODE_SEG("PAGE") USHORT IsaPnpChecksum( _In_ PISAPNP_IDENTIFIER Identifier) { UCHAR i, j, Lfsr; + PAGED_CODE(); + Lfsr = ISAPNP_LFSR_SEED; for (i = 0; i < FIELD_OFFSET(ISAPNP_IDENTIFIER, Checksum); i++) { @@ -307,6 +316,7 @@ IsaPnpChecksum( } static +CODE_SEG("PAGE") BOOLEAN ReadTags( _In_ PUCHAR ReadDataPort, @@ -318,6 +328,8 @@ ReadTags( USHORT Tag, TagLen, MaxLen; ULONG NumberOfIo = 0, NumberOfIrq = 0, NumberOfDma = 0; + PAGED_CODE(); + LogDev += 1; while (TRUE) @@ -391,6 +403,7 @@ ReadTags( } static +CODE_SEG("PAGE") INT TryIsolate( _In_ PUCHAR ReadDataPort) @@ -401,6 +414,8 @@ TryIsolate( INT Csn = 0; USHORT Byte, Data; + PAGED_CODE(); + DPRINT("Setting read data port: 0x%p\n", ReadDataPort); WaitForKey(); @@ -496,6 +511,7 @@ TryIsolate( return Csn; } +static VOID DeviceActivation( _In_ PISAPNP_LOGICAL_DEVICE IsaDevice, @@ -515,6 +531,8 @@ DeviceActivation( WaitForKey(); } +static +CODE_SEG("PAGE") NTSTATUS ProbeIsaPnpBus( _In_ PISAPNP_FDO_EXTENSION FdoExt) @@ -525,6 +543,7 @@ ProbeIsaPnpBus( USHORT LogDev; ULONG i; + PAGED_CODE(); ASSERT(FdoExt->ReadDataPort); for (Csn = 1; Csn <= 0xFF; Csn++) @@ -585,16 +604,18 @@ ProbeIsaPnpBus( return STATUS_SUCCESS; } +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaHwTryReadDataPort( _In_ PUCHAR ReadDataPort) { + PAGED_CODE(); + return TryIsolate(ReadDataPort) > 0 ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; } +_IRQL_requires_max_(DISPATCH_LEVEL) NTSTATUS -NTAPI IsaHwActivateDevice( _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice) { @@ -604,8 +625,8 @@ IsaHwActivateDevice( return STATUS_SUCCESS; } +_IRQL_requires_max_(DISPATCH_LEVEL) NTSTATUS -NTAPI IsaHwDeactivateDevice( _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice) { @@ -615,10 +636,12 @@ IsaHwDeactivateDevice( return STATUS_SUCCESS; } +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaHwFillDeviceList( _In_ PISAPNP_FDO_EXTENSION FdoExt) { + PAGED_CODE(); + return ProbeIsaPnpBus(FdoExt); } diff --git a/drivers/bus/isapnp/isapnp.c b/drivers/bus/isapnp/isapnp.c index 56ea50d379d..8342e191d69 100644 --- a/drivers/bus/isapnp/isapnp.c +++ b/drivers/bus/isapnp/isapnp.c @@ -138,8 +138,8 @@ IsaFdoCreateDeviceIDs( } static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPnpCreateLogicalDeviceRequirements( _In_ PISAPNP_PDO_EXTENSION PdoExt) { @@ -154,6 +154,8 @@ IsaPnpCreateLogicalDeviceRequirements( PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; PIO_RESOURCE_DESCRIPTOR Descriptor; + PAGED_CODE(); + /* Count number of requirements */ for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) { @@ -307,8 +309,8 @@ IsaPnpCreateLogicalDeviceRequirements( } static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPnpCreateLogicalDeviceResources( _In_ PISAPNP_PDO_EXTENSION PdoExt) { @@ -318,6 +320,8 @@ IsaPnpCreateLogicalDeviceResources( PCM_RESOURCE_LIST ResourceList; PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; + PAGED_CODE(); + /* Count number of required resources */ for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) { @@ -421,8 +425,8 @@ IsaPnpCreateLogicalDeviceResources( return STATUS_SUCCESS; } +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPnpFillDeviceRelations( _In_ PISAPNP_FDO_EXTENSION FdoExt, _Inout_ PIRP Irp, @@ -435,6 +439,8 @@ IsaPnpFillDeviceRelations( PDEVICE_RELATIONS DeviceRelations; ULONG i = 0; + PAGED_CODE(); + DeviceRelations = ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS) + sizeof(DEVICE_OBJECT) * FdoExt->DeviceCount); if (!DeviceRelations) @@ -555,15 +561,18 @@ IsaForwardIrpSynchronous( _Dispatch_type_(IRP_MJ_CREATE) _Dispatch_type_(IRP_MJ_CLOSE) -static DRIVER_DISPATCH IsaCreateClose; +static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaCreateClose; static +CODE_SEG("PAGE") NTSTATUS NTAPI IsaCreateClose( _In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp) { + PAGED_CODE(); + Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = FILE_OPENED; @@ -622,8 +631,8 @@ IsaReadWrite( } static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPnpCreateReadPortDORequirements( _In_ PISAPNP_PDO_EXTENSION PdoExt) { @@ -633,6 +642,8 @@ IsaPnpCreateReadPortDORequirements( const ULONG Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS, 0x274, 0x3E4, 0x204, 0x2E4, 0x354, 0x2F4 }; + PAGED_CODE(); + ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + 2 * RTL_NUMBER_OF(Ports) * sizeof(IO_RESOURCE_DESCRIPTOR); RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); @@ -672,8 +683,8 @@ IsaPnpCreateReadPortDORequirements( } static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPnpCreateReadPortDOResources( _In_ PISAPNP_PDO_EXTENSION PdoExt) { @@ -682,6 +693,8 @@ IsaPnpCreateReadPortDOResources( PCM_RESOURCE_LIST ResourceList; PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; + PAGED_CODE(); + ListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (RTL_NUMBER_OF(Ports) - 1); ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); @@ -710,8 +723,8 @@ IsaPnpCreateReadPortDOResources( } static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPnpCreateReadPortDO( _In_ PISAPNP_FDO_EXTENSION FdoExt) { @@ -722,6 +735,8 @@ IsaPnpCreateReadPortDO( PISAPNP_PDO_EXTENSION PdoExt; NTSTATUS Status; + PAGED_CODE(); + Status = IoCreateDevice(FdoExt->DriverObject, sizeof(ISAPNP_PDO_EXTENSION), NULL, @@ -774,7 +789,10 @@ IsaPnpCreateReadPortDO( return Status; } +static CODE_SEG("PAGE") DRIVER_ADD_DEVICE IsaAddDevice; + static +CODE_SEG("PAGE") NTSTATUS NTAPI IsaAddDevice( @@ -785,6 +803,8 @@ IsaAddDevice( PISAPNP_FDO_EXTENSION FdoExt; NTSTATUS Status; + PAGED_CODE(); + DPRINT("%s(%p, %p)\n", __FUNCTION__, DriverObject, PhysicalDeviceObject); Status = IoCreateDevice(DriverObject, @@ -812,7 +832,7 @@ IsaAddDevice( PhysicalDeviceObject); InitializeListHead(&FdoExt->DeviceListHead); - KeInitializeSpinLock(&FdoExt->Lock); + KeInitializeEvent(&FdoExt->DeviceSyncEvent, SynchronizationEvent, TRUE); Status = IsaPnpCreateReadPortDO(FdoExt); if (!NT_SUCCESS(Status)) @@ -825,8 +845,9 @@ IsaAddDevice( } _Dispatch_type_(IRP_MJ_POWER) -DRIVER_DISPATCH IsaPower; +static DRIVER_DISPATCH_RAISED IsaPower; +static NTSTATUS NTAPI IsaPower( @@ -849,9 +870,10 @@ IsaPower( } _Dispatch_type_(IRP_MJ_PNP) -static DRIVER_DISPATCH IsaPnp; +static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaPnp; static +CODE_SEG("PAGE") NTSTATUS NTAPI IsaPnp( @@ -861,6 +883,8 @@ IsaPnp( PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension; + PAGED_CODE(); + DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); if (DevExt->IsFdo) @@ -869,6 +893,7 @@ IsaPnp( return IsaPdoPnp((PISAPNP_PDO_EXTENSION)DevExt, Irp, IrpSp); } +CODE_SEG("INIT") NTSTATUS NTAPI DriverEntry( diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index e9b003b325b..8e872a0e506 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -11,6 +11,7 @@ #include #include +#include #include "isapnphw.h" #ifdef __cplusplus @@ -72,11 +73,11 @@ typedef struct _ISAPNP_FDO_EXTENSION PDEVICE_OBJECT Ldo; PDEVICE_OBJECT Pdo; PDEVICE_OBJECT ReadPortPdo; + KEVENT DeviceSyncEvent; LIST_ENTRY DeviceListHead; ULONG DeviceCount; PDRIVER_OBJECT DriverObject; PUCHAR ReadDataPort; - KSPIN_LOCK Lock; } ISAPNP_FDO_EXTENSION, *PISAPNP_FDO_EXTENSION; typedef struct _ISAPNP_PDO_EXTENSION @@ -93,6 +94,25 @@ typedef struct _ISAPNP_PDO_EXTENSION ULONG ResourceListSize; } ISAPNP_PDO_EXTENSION, *PISAPNP_PDO_EXTENSION; +_Requires_lock_not_held_(FdoExt->DeviceSyncEvent) +_Acquires_lock_(FdoExt->DeviceSyncEvent) +FORCEINLINE +VOID +IsaPnpAcquireDeviceDataLock( + _In_ PISAPNP_FDO_EXTENSION FdoExt) +{ + KeWaitForSingleObject(&FdoExt->DeviceSyncEvent, Executive, KernelMode, FALSE, NULL); +} + +_Releases_lock_(FdoExt->DeviceSyncEvent) +FORCEINLINE +VOID +IsaPnpReleaseDeviceDataLock( + _In_ PISAPNP_FDO_EXTENSION FdoExt) +{ + KeSetEvent(&FdoExt->DeviceSyncEvent, IO_NO_INCREMENT, FALSE); +} + /* isapnp.c */ #define RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE 1 @@ -105,13 +125,14 @@ IsaPnpDuplicateUnicodeString( IN PCUNICODE_STRING SourceString, OUT PUNICODE_STRING DestinationString); +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPnpFillDeviceRelations( _In_ PISAPNP_FDO_EXTENSION FdoExt, _Inout_ PIRP Irp, _In_ BOOLEAN IncludeDataPort); +CODE_SEG("INIT") DRIVER_INITIALIZE DriverEntry; NTSTATUS @@ -121,39 +142,39 @@ IsaForwardIrpSynchronous( _Inout_ PIRP Irp); /* fdo.c */ +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaFdoPnp( _In_ PISAPNP_FDO_EXTENSION FdoExt, _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IrpSp); /* pdo.c */ +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPdoPnp( _In_ PISAPNP_PDO_EXTENSION PdoDeviceExtension, _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IrpSp); /* hardware.c */ +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaHwTryReadDataPort( _In_ PUCHAR ReadDataPort); +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaHwFillDeviceList( _In_ PISAPNP_FDO_EXTENSION FdoExt); +_IRQL_requires_max_(DISPATCH_LEVEL) NTSTATUS -NTAPI IsaHwDeactivateDevice( _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice); +_IRQL_requires_max_(DISPATCH_LEVEL) NTSTATUS -NTAPI IsaHwActivateDevice( _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice); diff --git a/drivers/bus/isapnp/pdo.c b/drivers/bus/isapnp/pdo.c index 57c217f200e..402f62609cd 100644 --- a/drivers/bus/isapnp/pdo.c +++ b/drivers/bus/isapnp/pdo.c @@ -11,8 +11,9 @@ #define NDEBUG #include +static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPdoQueryDeviceRelations( _In_ PISAPNP_PDO_EXTENSION PdoExt, _Inout_ PIRP Irp, @@ -20,6 +21,8 @@ IsaPdoQueryDeviceRelations( { PDEVICE_RELATIONS DeviceRelations; + PAGED_CODE(); + if (IrpSp->Parameters.QueryDeviceRelations.Type == RemovalRelations && PdoExt->Common.Self == PdoExt->FdoExt->ReadPortPdo) { @@ -41,8 +44,9 @@ IsaPdoQueryDeviceRelations( return STATUS_SUCCESS; } +static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPdoQueryCapabilities( _In_ PISAPNP_PDO_EXTENSION PdoExt, _Inout_ PIRP Irp, @@ -52,6 +56,8 @@ IsaPdoQueryCapabilities( PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; ULONG i; + PAGED_CODE(); + DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities; if (DeviceCapabilities->Version != 1) return STATUS_REVISION_MISMATCH; @@ -75,19 +81,23 @@ IsaPdoQueryCapabilities( return STATUS_SUCCESS; } +static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPdoQueryPnpDeviceState( _In_ PISAPNP_PDO_EXTENSION PdoExt, _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IrpSp) { + PAGED_CODE(); + Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; return STATUS_SUCCESS; } +static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPdoQueryId( _In_ PISAPNP_PDO_EXTENSION PdoExt, _Inout_ PIRP Irp, @@ -96,6 +106,8 @@ IsaPdoQueryId( PUNICODE_STRING Source; PWCHAR Buffer; + PAGED_CODE(); + switch (IrpSp->Parameters.QueryId.IdType) { case BusQueryDeviceID: @@ -136,8 +148,9 @@ IsaPdoQueryId( return STATUS_SUCCESS; } +static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPdoQueryResources( _In_ PISAPNP_PDO_EXTENSION PdoExt, _Inout_ PIRP Irp, @@ -146,6 +159,8 @@ IsaPdoQueryResources( ULONG ListSize; PCM_RESOURCE_LIST ResourceList; + PAGED_CODE(); + if (!PdoExt->ResourceList) return Irp->IoStatus.Status; @@ -159,8 +174,9 @@ IsaPdoQueryResources( return STATUS_SUCCESS; } +static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPdoQueryResourceRequirements( _In_ PISAPNP_PDO_EXTENSION PdoExt, _Inout_ PIRP Irp, @@ -169,6 +185,8 @@ IsaPdoQueryResourceRequirements( ULONG ListSize; PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; + PAGED_CODE(); + if (!PdoExt->RequirementsList) return Irp->IoStatus.Status; @@ -183,17 +201,18 @@ IsaPdoQueryResourceRequirements( } static +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPdoStartReadPort( _In_ PISAPNP_FDO_EXTENSION FdoExt, _In_ PIO_STACK_LOCATION IrpSp) { PCM_RESOURCE_LIST ResourceList = IrpSp->Parameters.StartDevice.AllocatedResources; NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; - KIRQL OldIrql; ULONG i; + PAGED_CODE(); + if (!ResourceList || ResourceList->Count != 1) { DPRINT1("No resource list (%p) or bad count (%d)\n", @@ -222,10 +241,13 @@ IsaPdoStartReadPort( if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort))) { /* We detected some ISAPNP cards */ + FdoExt->ReadDataPort = ReadDataPort; - KeAcquireSpinLock(&FdoExt->Lock, &OldIrql); + + IsaPnpAcquireDeviceDataLock(FdoExt); Status = IsaHwFillDeviceList(FdoExt); - KeReleaseSpinLock(&FdoExt->Lock, OldIrql); + IsaPnpReleaseDeviceDataLock(FdoExt); + if (FdoExt->DeviceCount > 0) { IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations); @@ -301,8 +323,8 @@ IsaPdoRepeatRequest( return STATUS_PENDING; } +CODE_SEG("PAGE") NTSTATUS -NTAPI IsaPdoPnp( _In_ PISAPNP_PDO_EXTENSION PdoExt, _Inout_ PIRP Irp, @@ -310,6 +332,8 @@ IsaPdoPnp( { NTSTATUS Status = Irp->IoStatus.Status; + PAGED_CODE(); + switch (IrpSp->MinorFunction) { case IRP_MN_START_DEVICE: