https://git.reactos.org/?p=reactos.git;a=commitdiff;h=367f4b1581c0ebdc41edeā¦
commit 367f4b1581c0ebdc41ede579bbd7b6efc285d477
Author:     Dmitry Borisov <di.sean(a)protonmail.com>
AuthorDate: Sat Mar 20 20:52:40 2021 +0600
Commit:     Dmitry Borisov <di.sean(a)protonmail.com>
CommitDate: Sun Jun 20 19:24:31 2021 +0600
    [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 | 152 ++++++++++++++++--------------------------
 drivers/bus/isapnp/isapnp.c   |   2 +
 drivers/bus/isapnp/isapnp.h   |  15 ++++-
 drivers/bus/isapnp/pdo.c      |  44 ++++++++++--
 4 files changed, 112 insertions(+), 101 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;
         }
-        if (!Seen55aa)
+        ++NumberOfRead;
+
+        if (Identifier.Checksum != 0x00 &&
+            Identifier.Checksum != IsaPnpChecksum(&Identifier))
         {
-            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");
-                }
-            }
+            DPRINT("Bad checksum\n");
             break;
         }
-        if (Identifier.Checksum != IsaPnpChecksum(&Identifier))
+        if (!Seen55aa)
         {
-            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);
+    DeactivateDevice(LogicalDevice->LDN);
+}
-    return STATUS_SUCCESS;
+_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:
         {