[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); WriteByte(ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_WAIT_FOR_KEY);
} }
static
inline
VOID
ResetCsn(VOID)
{
WriteByte(ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_RESET_CSN);
}
static static
inline inline
VOID VOID
@ -1167,92 +1159,81 @@ ReadCurrentResources(
return TRUE; return TRUE;
} }
static
CODE_SEG("PAGE") CODE_SEG("PAGE")
INT UCHAR
TryIsolate( IsaHwTryReadDataPort(
_In_ PUCHAR ReadDataPort) _In_ PUCHAR ReadDataPort)
{ {
ISAPNP_IDENTIFIER Identifier; ULONG NumberOfRead = 0;
USHORT i, j; UCHAR Csn = 0;
BOOLEAN Seen55aa, SeenLife;
INT Csn = 0;
USHORT Byte, Data;
PAGED_CODE(); PAGED_CODE();
DPRINT("Setting read data port: 0x%p\n", ReadDataPort); DPRINT("Setting read data port: 0x%p\n", ReadDataPort);
WaitForKey();
SendKey(); SendKey();
ResetCsn(); WriteByte(ISAPNP_CONFIGCONTROL,
ISAPNP_CONFIG_RESET_CSN | ISAPNP_CONFIG_WAIT_FOR_KEY);
KeStallExecutionProcessor(2000); KeStallExecutionProcessor(2000);
WaitForKey();
SendKey(); SendKey();
Wake(0x00); Wake(0x00);
KeStallExecutionProcessor(1000); KeStallExecutionProcessor(1000);
SetReadDataPort(ReadDataPort); SetReadDataPort(ReadDataPort);
Wake(0x00);
while (TRUE) while (TRUE)
{ {
ISAPNP_IDENTIFIER Identifier;
UCHAR i, j;
BOOLEAN Seen55aa = FALSE;
EnterIsolationState(); EnterIsolationState();
KeStallExecutionProcessor(1000); KeStallExecutionProcessor(1000);
RtlZeroMemory(&Identifier, sizeof(Identifier)); RtlZeroMemory(&Identifier, sizeof(Identifier));
Seen55aa = SeenLife = FALSE; for (i = 0; i < sizeof(Identifier); i++)
for (i = 0; i < 9; i++)
{ {
Byte = 0; UCHAR Byte = 0;
for (j = 0; j < 8; j++)
for (j = 0; j < RTL_BITS_OF(Byte); j++)
{ {
Data = ReadData(ReadDataPort); USHORT Data;
Data = ReadData(ReadDataPort) << 8;
KeStallExecutionProcessor(250); KeStallExecutionProcessor(250);
Data = ((Data << 8) | ReadData(ReadDataPort)); Data |= ReadData(ReadDataPort);
KeStallExecutionProcessor(250); KeStallExecutionProcessor(250);
Byte >>= 1; Byte >>= 1;
if (Data != 0xFFFF) if (Data == 0x55AA)
{ {
SeenLife = TRUE; Byte |= 0x80;
if (Data == 0x55AA) 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 (!Seen55aa)
{ {
if (Csn) DPRINT("Saw no sign of life\n");
{
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;
break; break;
} }
@ -1264,32 +1245,18 @@ TryIsolate(
Wake(0x00); 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 else
DeactivateDevice(IsaDevice->LDN); {
DPRINT("Found %u cards at read port 0x%p\n", Csn, ReadDataPort);
WaitForKey(); return Csn;
}
} }
_Requires_lock_held_(FdoExt->DeviceSyncEvent) _Requires_lock_held_(FdoExt->DeviceSyncEvent)
@ -1324,9 +1291,6 @@ IsaHwFillDeviceList(
LogDevice->Flags &= ~ISAPNP_PRESENT; LogDevice->Flags &= ~ISAPNP_PRESENT;
} }
WaitForKey();
SendKey();
for (Csn = 1; Csn <= FdoExt->Cards; Csn++) for (Csn = 1; Csn <= FdoExt->Cards; Csn++)
{ {
NTSTATUS Status; NTSTATUS Status;
@ -1436,34 +1400,34 @@ Deactivate:
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
CODE_SEG("PAGE") _IRQL_requires_max_(DISPATCH_LEVEL)
ULONG VOID
IsaHwTryReadDataPort( IsaHwWakeDevice(
_In_ PUCHAR ReadDataPort) _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice)
{ {
PAGED_CODE(); SendKey();
Wake(LogicalDevice->CSN);
return TryIsolate(ReadDataPort);
} }
_IRQL_requires_max_(DISPATCH_LEVEL) _IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS VOID
IsaHwActivateDevice( IsaHwActivateDevice(
_In_ PISAPNP_LOGICAL_DEVICE LogicalDevice) _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice)
{ {
DeviceActivation(LogicalDevice, ActivateDevice(LogicalDevice->LDN);
TRUE);
return STATUS_SUCCESS;
} }
_IRQL_requires_max_(DISPATCH_LEVEL) _IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS VOID
IsaHwDeactivateDevice( IsaHwDeactivateDevice(
_In_ PISAPNP_LOGICAL_DEVICE LogicalDevice) _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice)
{ {
DeviceActivation(LogicalDevice, DeactivateDevice(LogicalDevice->LDN);
FALSE); }
return STATUS_SUCCESS; _IRQL_requires_max_(DISPATCH_LEVEL)
VOID
IsaHwWaitForKey(VOID)
{
WaitForKey();
} }

View file

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

View file

@ -365,7 +365,7 @@ IsaPnpRemoveLogicalDeviceDO(
/* hardware.c */ /* hardware.c */
CODE_SEG("PAGE") CODE_SEG("PAGE")
ULONG UCHAR
IsaHwTryReadDataPort( IsaHwTryReadDataPort(
_In_ PUCHAR ReadDataPort); _In_ PUCHAR ReadDataPort);
@ -376,15 +376,24 @@ IsaHwFillDeviceList(
_In_ PISAPNP_FDO_EXTENSION FdoExt); _In_ PISAPNP_FDO_EXTENSION FdoExt);
_IRQL_requires_max_(DISPATCH_LEVEL) _IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS VOID
IsaHwWakeDevice(
_In_ PISAPNP_LOGICAL_DEVICE LogicalDevice);
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
IsaHwDeactivateDevice( IsaHwDeactivateDevice(
_In_ PISAPNP_LOGICAL_DEVICE LogicalDevice); _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice);
_IRQL_requires_max_(DISPATCH_LEVEL) _IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS VOID
IsaHwActivateDevice( IsaHwActivateDevice(
_In_ PISAPNP_LOGICAL_DEVICE LogicalDevice); _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice);
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
IsaHwWaitForKey(VOID);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -570,6 +570,7 @@ IsaPdoStartReadPort(
if (IS_READ_PORT(PartialDescriptor)) if (IS_READ_PORT(PartialDescriptor))
{ {
PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3); PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3);
ULONG Cards;
/* /*
* Remember the first Read Port in the resource list. * Remember the first Read Port in the resource list.
@ -578,8 +579,11 @@ IsaPdoStartReadPort(
if (!SelectedPort) if (!SelectedPort)
SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart; SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart;
Cards = IsaHwTryReadDataPort(ReadDataPort);
IsaHwWaitForKey();
/* We detected some ISAPNP cards */ /* We detected some ISAPNP cards */
if (IsaHwTryReadDataPort(ReadDataPort) > 0) if (Cards > 0)
{ {
SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart; SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart;
break; break;
@ -634,6 +638,7 @@ IsaPdoStartReadPort(
/* Card identification */ /* Card identification */
Status = IsaHwFillDeviceList(FdoExt); Status = IsaHwFillDeviceList(FdoExt);
IsaHwWaitForKey();
IsaPnpReleaseDeviceDataLock(FdoExt); IsaPnpReleaseDeviceDataLock(FdoExt);
@ -647,7 +652,10 @@ IsaPdoStartReadPort(
} }
else else
{ {
IsaHwWaitForKey();
#if 0 /* See the 'if 0' above */
break; break;
#endif
} }
} }
} }
@ -742,6 +750,17 @@ IsaPdoRemoveDevice(
PAGED_CODE(); 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)) if (FinalRemove && !(PdoExt->Flags & ISAPNP_ENUMERATED))
{ {
IsaPnpAcquireDeviceDataLock(FdoExt); IsaPnpAcquireDeviceDataLock(FdoExt);
@ -873,8 +892,16 @@ IsaPdoPnp(
switch (IrpSp->MinorFunction) switch (IrpSp->MinorFunction)
{ {
case IRP_MN_START_DEVICE: case IRP_MN_START_DEVICE:
{
if (PdoExt->Common.Signature == IsaPnpLogicalDevice) if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
Status = IsaHwActivateDevice(PdoExt->IsaPnpDevice); {
IsaHwWakeDevice(PdoExt->IsaPnpDevice);
Status = STATUS_SUCCESS;
IsaHwActivateDevice(PdoExt->IsaPnpDevice);
IsaHwWaitForKey();
}
else else
{ {
Status = IsaPdoStartReadPort(PdoExt, Status = IsaPdoStartReadPort(PdoExt,
@ -884,19 +911,28 @@ IsaPdoPnp(
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
PdoExt->Common.State = dsStarted; PdoExt->Common.State = dsStarted;
break; break;
}
case IRP_MN_STOP_DEVICE: case IRP_MN_STOP_DEVICE:
{
if (PdoExt->Common.Signature == IsaPnpLogicalDevice) if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
Status = IsaHwDeactivateDevice(PdoExt->IsaPnpDevice); {
IsaHwWakeDevice(PdoExt->IsaPnpDevice);
IsaHwDeactivateDevice(PdoExt->IsaPnpDevice);
IsaHwWaitForKey();
}
else else
{ {
PdoExt->Flags &= ~ISAPNP_READ_PORT_ALLOW_FDO_SCAN; PdoExt->Flags &= ~ISAPNP_READ_PORT_ALLOW_FDO_SCAN;
Status = STATUS_SUCCESS;
} }
Status = STATUS_SUCCESS;
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
PdoExt->Common.State = dsStopped; PdoExt->Common.State = dsStopped;
break; break;
}
case IRP_MN_QUERY_STOP_DEVICE: case IRP_MN_QUERY_STOP_DEVICE:
{ {