[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.
This commit is contained in:
Dmitry Borisov 2021-03-20 20:52:40 +06:00
parent d6dca83baf
commit 367f4b1581
4 changed files with 116 additions and 105 deletions

View file

@ -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)
{
SeenLife = TRUE;
if (Data == 0x55AA)
{
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();
}

View file

@ -1350,6 +1350,8 @@ IsaPnpFillDeviceRelations(
/* Card identification */
if (FdoExt->Cards > 0)
(VOID)IsaHwFillDeviceList(FdoExt);
IsaHwWaitForKey();
}
ReadPortExt->Flags &= ~ISAPNP_SCANNED_BY_READ_PORT;

View file

@ -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

View file

@ -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:
{