From 367f4b1581c0ebdc41ede579bbd7b6efc285d477 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Sat, 20 Mar 2021 20:52:40 +0600 Subject: [PATCH] [ISAPNP] Map configuration states to PnP states Rework the hardware support code to avoid unneeded transitions between configuration states. - Only call WaitForKey when needed. - Each PnP state transition causes the bus to move to WaitForKey state. Besides, deactivate logical device during processing remove request. --- drivers/bus/isapnp/hardware.c | 160 +++++++++++++--------------------- drivers/bus/isapnp/isapnp.c | 2 + drivers/bus/isapnp/isapnp.h | 15 +++- drivers/bus/isapnp/pdo.c | 44 +++++++++- 4 files changed, 116 insertions(+), 105 deletions(-) diff --git a/drivers/bus/isapnp/hardware.c b/drivers/bus/isapnp/hardware.c index 671a198baf6..62e538a49d4 100644 --- a/drivers/bus/isapnp/hardware.c +++ b/drivers/bus/isapnp/hardware.c @@ -119,14 +119,6 @@ WaitForKey(VOID) WriteByte(ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_WAIT_FOR_KEY); } -static -inline -VOID -ResetCsn(VOID) -{ - WriteByte(ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_RESET_CSN); -} - static inline VOID @@ -1167,92 +1159,81 @@ ReadCurrentResources( return TRUE; } -static CODE_SEG("PAGE") -INT -TryIsolate( +UCHAR +IsaHwTryReadDataPort( _In_ PUCHAR ReadDataPort) { - ISAPNP_IDENTIFIER Identifier; - USHORT i, j; - BOOLEAN Seen55aa, SeenLife; - INT Csn = 0; - USHORT Byte, Data; + ULONG NumberOfRead = 0; + UCHAR Csn = 0; PAGED_CODE(); DPRINT("Setting read data port: 0x%p\n", ReadDataPort); - WaitForKey(); SendKey(); - ResetCsn(); + WriteByte(ISAPNP_CONFIGCONTROL, + ISAPNP_CONFIG_RESET_CSN | ISAPNP_CONFIG_WAIT_FOR_KEY); KeStallExecutionProcessor(2000); - WaitForKey(); SendKey(); + Wake(0x00); KeStallExecutionProcessor(1000); SetReadDataPort(ReadDataPort); + Wake(0x00); + while (TRUE) { + ISAPNP_IDENTIFIER Identifier; + UCHAR i, j; + BOOLEAN Seen55aa = FALSE; + EnterIsolationState(); KeStallExecutionProcessor(1000); RtlZeroMemory(&Identifier, sizeof(Identifier)); - Seen55aa = SeenLife = FALSE; - for (i = 0; i < 9; i++) + for (i = 0; i < sizeof(Identifier); i++) { - Byte = 0; - for (j = 0; j < 8; j++) + UCHAR Byte = 0; + + for (j = 0; j < RTL_BITS_OF(Byte); j++) { - Data = ReadData(ReadDataPort); + USHORT Data; + + Data = ReadData(ReadDataPort) << 8; KeStallExecutionProcessor(250); - Data = ((Data << 8) | ReadData(ReadDataPort)); + Data |= ReadData(ReadDataPort); KeStallExecutionProcessor(250); + Byte >>= 1; - if (Data != 0xFFFF) + if (Data == 0x55AA) { - SeenLife = TRUE; - if (Data == 0x55AA) - { - Byte |= 0x80; - Seen55aa = TRUE; - } + Byte |= 0x80; + Seen55aa = TRUE; } } - *(((PUCHAR)&Identifier) + i) = Byte; + + ((PUCHAR)&Identifier)[i] = Byte; + } + + ++NumberOfRead; + + if (Identifier.Checksum != 0x00 && + Identifier.Checksum != IsaPnpChecksum(&Identifier)) + { + DPRINT("Bad checksum\n"); + break; } if (!Seen55aa) { - if (Csn) - { - DPRINT("Found no more cards\n"); - } - else - { - if (SeenLife) - { - DPRINT("Saw life but no cards, trying new read port\n"); - Csn = -1; - } - else - { - DPRINT("Saw no sign of life, abandoning isolation\n"); - } - } - break; - } - - if (Identifier.Checksum != IsaPnpChecksum(&Identifier)) - { - DPRINT("Bad checksum, trying next read data port\n"); - Csn = -1; + DPRINT("Saw no sign of life\n"); break; } @@ -1264,32 +1245,18 @@ TryIsolate( Wake(0x00); } - WaitForKey(); + Wake(0x00); - if (Csn > 0) + if (NumberOfRead == 1) { - DPRINT("Found %d cards at read port 0x%p\n", Csn, ReadDataPort); + DPRINT("Trying next read data port\n"); + return 0; } - - return Csn; -} - -static -VOID -DeviceActivation( - _In_ PISAPNP_LOGICAL_DEVICE IsaDevice, - _In_ BOOLEAN Activate) -{ - WaitForKey(); - SendKey(); - Wake(IsaDevice->CSN); - - if (Activate) - ActivateDevice(IsaDevice->LDN); else - DeactivateDevice(IsaDevice->LDN); - - WaitForKey(); + { + DPRINT("Found %u cards at read port 0x%p\n", Csn, ReadDataPort); + return Csn; + } } _Requires_lock_held_(FdoExt->DeviceSyncEvent) @@ -1324,9 +1291,6 @@ IsaHwFillDeviceList( LogDevice->Flags &= ~ISAPNP_PRESENT; } - WaitForKey(); - SendKey(); - for (Csn = 1; Csn <= FdoExt->Cards; Csn++) { NTSTATUS Status; @@ -1436,34 +1400,34 @@ Deactivate: return STATUS_SUCCESS; } -CODE_SEG("PAGE") -ULONG -IsaHwTryReadDataPort( - _In_ PUCHAR ReadDataPort) +_IRQL_requires_max_(DISPATCH_LEVEL) +VOID +IsaHwWakeDevice( + _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice) { - PAGED_CODE(); - - return TryIsolate(ReadDataPort); + SendKey(); + Wake(LogicalDevice->CSN); } _IRQL_requires_max_(DISPATCH_LEVEL) -NTSTATUS +VOID IsaHwActivateDevice( _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice) { - DeviceActivation(LogicalDevice, - TRUE); - - return STATUS_SUCCESS; + ActivateDevice(LogicalDevice->LDN); } _IRQL_requires_max_(DISPATCH_LEVEL) -NTSTATUS +VOID IsaHwDeactivateDevice( _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice) { - DeviceActivation(LogicalDevice, - FALSE); - - return STATUS_SUCCESS; + DeactivateDevice(LogicalDevice->LDN); +} + +_IRQL_requires_max_(DISPATCH_LEVEL) +VOID +IsaHwWaitForKey(VOID) +{ + WaitForKey(); } diff --git a/drivers/bus/isapnp/isapnp.c b/drivers/bus/isapnp/isapnp.c index 343a0ca69b3..877d69bf5a5 100644 --- a/drivers/bus/isapnp/isapnp.c +++ b/drivers/bus/isapnp/isapnp.c @@ -1350,6 +1350,8 @@ IsaPnpFillDeviceRelations( /* Card identification */ if (FdoExt->Cards > 0) (VOID)IsaHwFillDeviceList(FdoExt); + + IsaHwWaitForKey(); } ReadPortExt->Flags &= ~ISAPNP_SCANNED_BY_READ_PORT; diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index 00b82cb104b..e941020f783 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -365,7 +365,7 @@ IsaPnpRemoveLogicalDeviceDO( /* hardware.c */ CODE_SEG("PAGE") -ULONG +UCHAR IsaHwTryReadDataPort( _In_ PUCHAR ReadDataPort); @@ -376,15 +376,24 @@ IsaHwFillDeviceList( _In_ PISAPNP_FDO_EXTENSION FdoExt); _IRQL_requires_max_(DISPATCH_LEVEL) -NTSTATUS +VOID +IsaHwWakeDevice( + _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice); + +_IRQL_requires_max_(DISPATCH_LEVEL) +VOID IsaHwDeactivateDevice( _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice); _IRQL_requires_max_(DISPATCH_LEVEL) -NTSTATUS +VOID IsaHwActivateDevice( _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice); +_IRQL_requires_max_(DISPATCH_LEVEL) +VOID +IsaHwWaitForKey(VOID); + #ifdef __cplusplus } #endif diff --git a/drivers/bus/isapnp/pdo.c b/drivers/bus/isapnp/pdo.c index 8490bf9c14d..2c0a4641cb2 100644 --- a/drivers/bus/isapnp/pdo.c +++ b/drivers/bus/isapnp/pdo.c @@ -570,6 +570,7 @@ IsaPdoStartReadPort( if (IS_READ_PORT(PartialDescriptor)) { PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3); + ULONG Cards; /* * Remember the first Read Port in the resource list. @@ -578,8 +579,11 @@ IsaPdoStartReadPort( if (!SelectedPort) SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart; + Cards = IsaHwTryReadDataPort(ReadDataPort); + IsaHwWaitForKey(); + /* We detected some ISAPNP cards */ - if (IsaHwTryReadDataPort(ReadDataPort) > 0) + if (Cards > 0) { SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart; break; @@ -634,6 +638,7 @@ IsaPdoStartReadPort( /* Card identification */ Status = IsaHwFillDeviceList(FdoExt); + IsaHwWaitForKey(); IsaPnpReleaseDeviceDataLock(FdoExt); @@ -647,7 +652,10 @@ IsaPdoStartReadPort( } else { + IsaHwWaitForKey(); +#if 0 /* See the 'if 0' above */ break; +#endif } } } @@ -742,6 +750,17 @@ IsaPdoRemoveDevice( PAGED_CODE(); + /* Deactivate the device if previously activated */ + if (PdoExt->Common.State == dsStarted) + { + IsaHwWakeDevice(PdoExt->IsaPnpDevice); + IsaHwDeactivateDevice(PdoExt->IsaPnpDevice); + + IsaHwWaitForKey(); + + PdoExt->Common.State = dsStopped; + } + if (FinalRemove && !(PdoExt->Flags & ISAPNP_ENUMERATED)) { IsaPnpAcquireDeviceDataLock(FdoExt); @@ -873,8 +892,16 @@ IsaPdoPnp( switch (IrpSp->MinorFunction) { case IRP_MN_START_DEVICE: + { if (PdoExt->Common.Signature == IsaPnpLogicalDevice) - Status = IsaHwActivateDevice(PdoExt->IsaPnpDevice); + { + IsaHwWakeDevice(PdoExt->IsaPnpDevice); + + Status = STATUS_SUCCESS; + + IsaHwActivateDevice(PdoExt->IsaPnpDevice); + IsaHwWaitForKey(); + } else { Status = IsaPdoStartReadPort(PdoExt, @@ -884,19 +911,28 @@ IsaPdoPnp( if (NT_SUCCESS(Status)) PdoExt->Common.State = dsStarted; break; + } case IRP_MN_STOP_DEVICE: + { if (PdoExt->Common.Signature == IsaPnpLogicalDevice) - Status = IsaHwDeactivateDevice(PdoExt->IsaPnpDevice); + { + IsaHwWakeDevice(PdoExt->IsaPnpDevice); + IsaHwDeactivateDevice(PdoExt->IsaPnpDevice); + + IsaHwWaitForKey(); + } else { PdoExt->Flags &= ~ISAPNP_READ_PORT_ALLOW_FDO_SCAN; - Status = STATUS_SUCCESS; } + Status = STATUS_SUCCESS; + if (NT_SUCCESS(Status)) PdoExt->Common.State = dsStopped; break; + } case IRP_MN_QUERY_STOP_DEVICE: {