ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
June 2021
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
19 participants
228 discussions
Start a n
N
ew thread
[reactos] 18/20: [ISAPNP] Disable bus scan on unsupported platforms
by Dmitry Borisov
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8939abf1137cfa82a082b…
commit 8939abf1137cfa82a082bdc329dc43693bb3f49b Author: Dmitry Borisov <di.sean(a)protonmail.com> AuthorDate: Sat Mar 20 20:53:32 2021 +0600 Commit: Dmitry Borisov <di.sean(a)protonmail.com> CommitDate: Sun Jun 20 19:24:32 2021 +0600 [ISAPNP] Disable bus scan on unsupported platforms This speeds up boot a bit and also decreases binary size. - Introduce a new CMake define ISAPNP_ENABLE that defined only in x86 platform when ISA PnP is supported. --- drivers/bus/isapnp/CMakeLists.txt | 21 ++- drivers/bus/isapnp/stub.c | 284 ++++++++++++++++++++++++++++++++++++++ sdk/cmake/config.cmake | 3 + 3 files changed, 301 insertions(+), 7 deletions(-) diff --git a/drivers/bus/isapnp/CMakeLists.txt b/drivers/bus/isapnp/CMakeLists.txt index 6b8a6747546..c4be1b57da3 100644 --- a/drivers/bus/isapnp/CMakeLists.txt +++ b/drivers/bus/isapnp/CMakeLists.txt @@ -1,11 +1,18 @@ -list(APPEND SOURCE - isapnp.c - pdo.c - fdo.c - hardware.c - interface.c - isapnp.h) +if(ISAPNP_ENABLE) + list(APPEND SOURCE + fdo.c + hardware.c + interface.c + isapnp.c + isapnp.h + pdo.c) +else() + list(APPEND SOURCE + interface.c + isapnp.h + stub.c) +endif() add_library(isapnp MODULE ${SOURCE} isapnp.rc) set_module_type(isapnp kernelmodedriver) diff --git a/drivers/bus/isapnp/stub.c b/drivers/bus/isapnp/stub.c new file mode 100644 index 00000000000..7b37c887adf --- /dev/null +++ b/drivers/bus/isapnp/stub.c @@ -0,0 +1,284 @@ +/* + * PROJECT: ReactOS ISA PnP Bus driver + * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later
) + * PURPOSE: Stub driver + * COPYRIGHT: Copyright 2021 Dmitry Borisov <di.sean(a)protonmail.com> + */ + +/* + * This driver does nothing, and only used if a platform has no ISA PnP support. + * We need to keep FDO because ACPI driver depends on it. The ACPI bus filter + * attaches legacy ISA/LPC devices to this FDO. + */ + +/* INCLUDES *******************************************************************/ + +#include "isapnp.h" + +#define NDEBUG +#include <debug.h> + +/* FUNCTIONS ******************************************************************/ + +_Dispatch_type_(IRP_MJ_CREATE) +_Dispatch_type_(IRP_MJ_CLOSE) +static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaStubCreateClose; + +static +CODE_SEG("PAGE") +NTSTATUS +NTAPI +IsaStubCreateClose( + _In_ PDEVICE_OBJECT DeviceObject, + _Inout_ PIRP Irp) +{ + UNREFERENCED_PARAMETER(DeviceObject); + + PAGED_CODE(); + + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + +_Dispatch_type_(IRP_MJ_DEVICE_CONTROL) +_Dispatch_type_(IRP_MJ_SYSTEM_CONTROL) +static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaStubForward; + +static +CODE_SEG("PAGE") +NTSTATUS +NTAPI +IsaStubForward( + _In_ PDEVICE_OBJECT DeviceObject, + _Inout_ PIRP Irp) +{ + PISAPNP_FDO_EXTENSION FdoExt = DeviceObject->DeviceExtension; + + PAGED_CODE(); + + IoSkipCurrentIrpStackLocation(Irp); + return IoCallDriver(FdoExt->Ldo, Irp); +} + +_Dispatch_type_(IRP_MJ_PNP) +static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaStubPnp; + +static +CODE_SEG("PAGE") +NTSTATUS +NTAPI +IsaStubPnp( + _In_ PDEVICE_OBJECT DeviceObject, + _Inout_ PIRP Irp) +{ + PISAPNP_FDO_EXTENSION FdoExt = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS Status; + + PAGED_CODE(); + + DPRINT("%s(%p, %p) Minor - %X\n", + __FUNCTION__, + FdoExt, + Irp, + IrpSp->MinorFunction); + + switch (IrpSp->MinorFunction) + { + case IRP_MN_START_DEVICE: + { + if (IoForwardIrpSynchronously(FdoExt->Ldo, Irp)) + Status = Irp->IoStatus.Status; + else + Status = STATUS_UNSUCCESSFUL; + + goto CompleteIrp; + } + + case IRP_MN_QUERY_DEVICE_RELATIONS: + { + PDEVICE_RELATIONS DeviceRelations; + + if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations) + break; + + DeviceRelations = ExAllocatePoolWithTag(PagedPool, + FIELD_OFFSET(DEVICE_RELATIONS, Objects), + TAG_ISAPNP); + if (!DeviceRelations) + { + Status = STATUS_NO_MEMORY; + goto CompleteIrp; + } + + DeviceRelations->Count = 0; + + Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; + Irp->IoStatus.Status = STATUS_SUCCESS; + break; + } + + case IRP_MN_REMOVE_DEVICE: + { + Irp->IoStatus.Status = STATUS_SUCCESS; + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(FdoExt->Ldo, Irp); + + IoDetachDevice(FdoExt->Ldo); + IoDeleteDevice(FdoExt->Common.Self); + + return Status; + } + + case IRP_MN_QUERY_PNP_DEVICE_STATE: + { + Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; + Irp->IoStatus.Status = STATUS_SUCCESS; + break; + } + + case IRP_MN_QUERY_INTERFACE: + { + Status = IsaFdoQueryInterface(FdoExt, IrpSp); + if (Status == STATUS_NOT_SUPPORTED) + { + break; + } + else if (!NT_SUCCESS(Status)) + { + goto CompleteIrp; + } + + Irp->IoStatus.Status = Status; + break; + } + + case IRP_MN_QUERY_REMOVE_DEVICE: + case IRP_MN_CANCEL_REMOVE_DEVICE: + case IRP_MN_QUERY_STOP_DEVICE: + case IRP_MN_CANCEL_STOP_DEVICE: + case IRP_MN_STOP_DEVICE: + case IRP_MN_SURPRISE_REMOVAL: + { + Irp->IoStatus.Status = STATUS_SUCCESS; + break; + } + + default: + break; + } + + IoSkipCurrentIrpStackLocation(Irp); + return IoCallDriver(FdoExt->Ldo, Irp); + +CompleteIrp: + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +} + +_Dispatch_type_(IRP_MJ_POWER) +static DRIVER_DISPATCH_RAISED IsaStubPower; + +static +NTSTATUS +NTAPI +IsaStubPower( + _In_ PDEVICE_OBJECT DeviceObject, + _Inout_ PIRP Irp) +{ + PISAPNP_FDO_EXTENSION FdoExt = DeviceObject->DeviceExtension; + + PoStartNextPowerIrp(Irp); + IoSkipCurrentIrpStackLocation(Irp); + return PoCallDriver(FdoExt->Ldo, Irp); +} + +static CODE_SEG("PAGE") DRIVER_ADD_DEVICE IsaStubAddDevice; + +static +CODE_SEG("PAGE") +NTSTATUS +NTAPI +IsaStubAddDevice( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PDEVICE_OBJECT PhysicalDeviceObject) +{ + PDEVICE_OBJECT Fdo; + PISAPNP_FDO_EXTENSION FdoExt; + NTSTATUS Status; + + PAGED_CODE(); + + DPRINT("%s(%p, %p)\n", __FUNCTION__, DriverObject, PhysicalDeviceObject); + + Status = IoCreateDevice(DriverObject, + sizeof(ISAPNP_FDO_EXTENSION), + NULL, + FILE_DEVICE_BUS_EXTENDER, + FILE_DEVICE_SECURE_OPEN, + FALSE, + &Fdo); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to create FDO (0x%08lx)\n", Status); + return Status; + } + + FdoExt = Fdo->DeviceExtension; + + RtlZeroMemory(FdoExt, sizeof(ISAPNP_FDO_EXTENSION)); + FdoExt->Common.Self = Fdo; + FdoExt->Common.Signature = IsaPnpBus; + FdoExt->DriverObject = DriverObject; + FdoExt->Pdo = PhysicalDeviceObject; + FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject); + if (!FdoExt->Ldo) + { + IoDeleteDevice(Fdo); + return STATUS_DEVICE_REMOVED; + } + + Fdo->Flags &= ~DO_DEVICE_INITIALIZING; + + return STATUS_SUCCESS; +} + +static CODE_SEG("PAGE") DRIVER_UNLOAD IsaStubUnload; + +static +CODE_SEG("PAGE") +VOID +NTAPI +IsaStubUnload( + _In_ PDRIVER_OBJECT DriverObject) +{ + UNREFERENCED_PARAMETER(DriverObject); + + PAGED_CODE(); + + NOTHING; +} + +CODE_SEG("INIT") +NTSTATUS +NTAPI +DriverEntry( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath) +{ + DPRINT("%s(%p, %wZ)\n", __FUNCTION__, DriverObject, RegistryPath); + + DriverObject->MajorFunction[IRP_MJ_CREATE] = IsaStubCreateClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = IsaStubCreateClose; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IsaStubForward; + DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IsaStubForward; + DriverObject->MajorFunction[IRP_MJ_PNP] = IsaStubPnp; + DriverObject->MajorFunction[IRP_MJ_POWER] = IsaStubPower; + DriverObject->DriverExtension->AddDevice = IsaStubAddDevice; + DriverObject->DriverUnload = IsaStubUnload; + + return STATUS_SUCCESS; +} diff --git a/sdk/cmake/config.cmake b/sdk/cmake/config.cmake index 7bf236d08cb..84e032f045a 100644 --- a/sdk/cmake/config.cmake +++ b/sdk/cmake/config.cmake @@ -100,6 +100,9 @@ endif() cmake_dependent_option(BUILD_MP "Whether to build the multiprocessor versions of NTOSKRNL and HAL." ON "ARCH STREQUAL i386" OFF) +cmake_dependent_option(ISAPNP_ENABLE "Whether to enable the ISA PnP support." ON + "ARCH STREQUAL i386 AND NOT SARCH STREQUAL xbox" OFF) + set(GENERATE_DEPENDENCY_GRAPH FALSE CACHE BOOL "Whether to create a GraphML dependency graph of DLLs.")
3 years, 6 months
1
0
0
0
[reactos] 17/20: [ISAPNP] Disable I/O range check before activation
by Dmitry Borisov
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e318d2294058787af8371…
commit e318d2294058787af83710feb4b581ba36282d46 Author: Dmitry Borisov <di.sean(a)protonmail.com> AuthorDate: Sat Mar 20 20:53:06 2021 +0600 Commit: Dmitry Borisov <di.sean(a)protonmail.com> CommitDate: Sun Jun 20 19:24:31 2021 +0600 [ISAPNP] Disable I/O range check before activation See Table A-2 of "Plug and Play ISA Specification 1.0a" --- drivers/bus/isapnp/hardware.c | 10 ++++++++-- drivers/bus/isapnp/isapnp.h | 1 + drivers/bus/isapnp/pdo.c | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/bus/isapnp/hardware.c b/drivers/bus/isapnp/hardware.c index 62e538a49d4..188d1732447 100644 --- a/drivers/bus/isapnp/hardware.c +++ b/drivers/bus/isapnp/hardware.c @@ -168,9 +168,14 @@ static inline VOID ActivateDevice( + _In_ PUCHAR ReadDataPort, _In_ UCHAR LogDev) { WriteLogicalDeviceNumber(LogDev); + + WriteByte(ISAPNP_IORANGECHECK, + ReadByte(ReadDataPort, ISAPNP_IORANGECHECK) & ~2); + WriteByte(ISAPNP_ACTIVATE, 1); } @@ -1341,7 +1346,7 @@ IsaHwFillDeviceList( PISAPNP_PDO_EXTENSION PdoExt = LogDevice->Pdo->DeviceExtension; if (PdoExt->Common.State == dsStarted) - ActivateDevice(LogDev); + ActivateDevice(FdoExt->ReadDataPort, LogDev); } DPRINT("Skip CSN %u, LDN %u\n", LogDevice->CSN, LogDevice->LDN); @@ -1412,9 +1417,10 @@ IsaHwWakeDevice( _IRQL_requires_max_(DISPATCH_LEVEL) VOID IsaHwActivateDevice( + _In_ PISAPNP_FDO_EXTENSION FdoExt, _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice) { - ActivateDevice(LogicalDevice->LDN); + ActivateDevice(FdoExt->ReadDataPort, LogicalDevice->LDN); } _IRQL_requires_max_(DISPATCH_LEVEL) diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index e941020f783..19702f36274 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -388,6 +388,7 @@ IsaHwDeactivateDevice( _IRQL_requires_max_(DISPATCH_LEVEL) VOID IsaHwActivateDevice( + _In_ PISAPNP_FDO_EXTENSION FdoExt, _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice); _IRQL_requires_max_(DISPATCH_LEVEL) diff --git a/drivers/bus/isapnp/pdo.c b/drivers/bus/isapnp/pdo.c index 2c0a4641cb2..1ee0e51b7ea 100644 --- a/drivers/bus/isapnp/pdo.c +++ b/drivers/bus/isapnp/pdo.c @@ -899,7 +899,7 @@ IsaPdoPnp( Status = STATUS_SUCCESS; - IsaHwActivateDevice(PdoExt->IsaPnpDevice); + IsaHwActivateDevice(PdoExt->FdoExt, PdoExt->IsaPnpDevice); IsaHwWaitForKey(); } else
3 years, 6 months
1
0
0
0
[reactos] 16/20: [ISAPNP] Map configuration states to PnP states
by Dmitry Borisov
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: {
3 years, 6 months
1
0
0
0
[reactos] 15/20: [ISAPNP] Reduce software delay
by Dmitry Borisov
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d6dca83baf34e3e958be2…
commit d6dca83baf34e3e958be2effe631ac5bf3ca9990 Author: Dmitry Borisov <di.sean(a)protonmail.com> AuthorDate: Sat Mar 20 20:52:04 2021 +0600 Commit: Dmitry Borisov <di.sean(a)protonmail.com> CommitDate: Sun Jun 20 19:24:31 2021 +0600 [ISAPNP] Reduce software delay --- drivers/bus/isapnp/hardware.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/drivers/bus/isapnp/hardware.c b/drivers/bus/isapnp/hardware.c index 0b6e200478a..671a198baf6 100644 --- a/drivers/bus/isapnp/hardware.c +++ b/drivers/bus/isapnp/hardware.c @@ -292,14 +292,6 @@ ReadMemoryLimit32( return ReadDoubleWord(ReadDataPort, ISAPNP_MEMLIMIT32(Index)); } -static -inline -VOID -HwDelay(VOID) -{ - KeStallExecutionProcessor(1000); -} - static inline UCHAR @@ -320,7 +312,6 @@ SendKey(VOID) { UCHAR i, Lfsr; - HwDelay(); WriteAddress(0x00); WriteAddress(0x00); @@ -347,7 +338,7 @@ PeekByte( if (ReadStatus(ReadDataPort) & 0x01) return ReadResourceData(ReadDataPort); - HwDelay(); + KeStallExecutionProcessor(1000); } return 0xFF; @@ -1196,20 +1187,19 @@ TryIsolate( SendKey(); ResetCsn(); - HwDelay(); - HwDelay(); + KeStallExecutionProcessor(2000); WaitForKey(); SendKey(); Wake(0x00); + KeStallExecutionProcessor(1000); SetReadDataPort(ReadDataPort); - HwDelay(); while (TRUE) { EnterIsolationState(); - HwDelay(); + KeStallExecutionProcessor(1000); RtlZeroMemory(&Identifier, sizeof(Identifier)); @@ -1220,9 +1210,9 @@ TryIsolate( for (j = 0; j < 8; j++) { Data = ReadData(ReadDataPort); - HwDelay(); + KeStallExecutionProcessor(250); Data = ((Data << 8) | ReadData(ReadDataPort)); - HwDelay(); + KeStallExecutionProcessor(250); Byte >>= 1; if (Data != 0xFFFF) @@ -1269,10 +1259,9 @@ TryIsolate( Csn++; WriteCsn(Csn); - HwDelay(); + KeStallExecutionProcessor(1000); Wake(0x00); - HwDelay(); } WaitForKey(); @@ -1300,8 +1289,6 @@ DeviceActivation( else DeactivateDevice(IsaDevice->LDN); - HwDelay(); - WaitForKey(); }
3 years, 6 months
1
0
0
0
[reactos] 14/20: [ISAPNP] Fix descriptors and support alternative configurations
by Dmitry Borisov
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8ed43b69073f47c25bb1c…
commit 8ed43b69073f47c25bb1c2ff644a3dc948f017bc Author: Dmitry Borisov <di.sean(a)protonmail.com> AuthorDate: Sat Mar 20 20:51:29 2021 +0600 Commit: Dmitry Borisov <di.sean(a)protonmail.com> CommitDate: Sun Jun 20 19:24:31 2021 +0600 [ISAPNP] Fix descriptors and support alternative configurations - Fix empty resource descriptors being created. - Properly support IRQ descriptors. - Introduce four helpers made to help search descriptors in the logical device's requirements. - Implement support for memory descriptors and alternative configurations. - DMA descriptors are always DMA_8. --- drivers/bus/isapnp/isapnp.c | 887 ++++++++++++++++++++++++++++++++++++++------ drivers/bus/isapnp/isapnp.h | 35 ++ 2 files changed, 813 insertions(+), 109 deletions(-) diff --git a/drivers/bus/isapnp/isapnp.c b/drivers/bus/isapnp/isapnp.c index 842929ee0ce..343a0ca69b3 100644 --- a/drivers/bus/isapnp/isapnp.c +++ b/drivers/bus/isapnp/isapnp.c @@ -11,6 +11,8 @@ #include "isapnp.h" +#include <search.h> + #define NDEBUG #include <debug.h> @@ -24,8 +26,168 @@ BOOLEAN ReadPortCreated = FALSE; _Guarded_by_(BusSyncEvent) LIST_ENTRY BusListHead; +static PUCHAR Priority; + /* FUNCTIONS ******************************************************************/ +static +CODE_SEG("PAGE") +int +__cdecl +IsaComparePriority( + const void *A, + const void *B) +{ + PAGED_CODE(); + + return Priority[*(PUCHAR)A] - Priority[*(PUCHAR)B]; +} + +static +CODE_SEG("PAGE") +VOID +IsaDetermineBestConfig( + _Out_writes_all_(ISAPNP_MAX_ALTERNATIVES) PUCHAR BestConfig, + _In_ PISAPNP_ALTERNATIVES Alternatives) +{ + UCHAR i; + + PAGED_CODE(); + + for (i = 0; i < ISAPNP_MAX_ALTERNATIVES; i++) + { + BestConfig[i] = i; + } + + Priority = Alternatives->Priority; + qsort(BestConfig, + Alternatives->Count, + sizeof(*BestConfig), + IsaComparePriority); +} + +static +CODE_SEG("PAGE") +VOID +IsaConvertIoRequirement( + _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, + _In_ PISAPNP_IO_DESCRIPTION Description) +{ + PAGED_CODE(); + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + if (Description->Information & 0x1) + Descriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE; + else + Descriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE; + Descriptor->u.Port.Length = Description->Length; + Descriptor->u.Port.Alignment = Description->Alignment; + Descriptor->u.Port.MinimumAddress.LowPart = Description->Minimum; + Descriptor->u.Port.MaximumAddress.LowPart = Description->Maximum + + Description->Length - 1; +} + +static +CODE_SEG("PAGE") +VOID +IsaConvertIrqRequirement( + _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, + _In_ PISAPNP_IRQ_DESCRIPTION Description, + _In_ ULONG Vector, + _In_ BOOLEAN FirstDescriptor) +{ + PAGED_CODE(); + + if (!FirstDescriptor) + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + Descriptor->Type = CmResourceTypeInterrupt; + if (Description->Information & 0xC) + { + Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + Descriptor->ShareDisposition = CmResourceShareShared; + } + else + { + Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + } + Descriptor->u.Interrupt.MinimumVector = + Descriptor->u.Interrupt.MaximumVector = Vector; +} + +static +CODE_SEG("PAGE") +VOID +IsaConvertDmaRequirement( + _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, + _In_ PISAPNP_DMA_DESCRIPTION Description, + _In_ ULONG Channel, + _In_ BOOLEAN FirstDescriptor) +{ + UNREFERENCED_PARAMETER(Description); + + PAGED_CODE(); + + if (!FirstDescriptor) + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + Descriptor->Type = CmResourceTypeDma; + Descriptor->ShareDisposition = CmResourceShareUndetermined; + Descriptor->Flags = CM_RESOURCE_DMA_8; /* Ignore information byte for compatibility */ + Descriptor->u.Dma.MinimumChannel = + Descriptor->u.Dma.MaximumChannel = Channel; +} + +static +CODE_SEG("PAGE") +VOID +IsaConvertMemRangeRequirement( + _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, + _In_ PISAPNP_MEMRANGE_DESCRIPTION Description) +{ + PAGED_CODE(); + + Descriptor->Type = CmResourceTypeMemory; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_MEMORY_24; + if ((Description->Information & 0x40) || !(Description->Information & 0x01)) + Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY; + else + Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE; + Descriptor->u.Memory.Length = Description->Length << 8; + if (Description->Alignment == 0) + Descriptor->u.Memory.Alignment = 0x10000; + else + Descriptor->u.Memory.Alignment = Description->Alignment; + Descriptor->u.Memory.MinimumAddress.LowPart = Description->Minimum << 8; + Descriptor->u.Memory.MaximumAddress.LowPart = (Description->Maximum << 8) + + (Description->Length << 8) - 1; +} + +static +CODE_SEG("PAGE") +VOID +IsaConvertMemRange32Requirement( + _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, + _In_ PISAPNP_MEMRANGE32_DESCRIPTION Description) +{ + PAGED_CODE(); + + Descriptor->Type = CmResourceTypeMemory; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_MEMORY_24; + if ((Description->Information & 0x40) || !(Description->Information & 0x01)) + Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY; + else + Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE; + Descriptor->u.Memory.Length = Description->Length; + Descriptor->u.Memory.Alignment = Description->Alignment; + Descriptor->u.Memory.MinimumAddress.LowPart = Description->Minimum; + Descriptor->u.Memory.MaximumAddress.LowPart = Description->Maximum + + Description->Length - 1; +} + static CODE_SEG("PAGE") NTSTATUS @@ -33,63 +195,133 @@ IsaPnpCreateLogicalDeviceRequirements( _In_ PISAPNP_PDO_EXTENSION PdoExt) { PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; - RTL_BITMAP IrqBitmap[RTL_NUMBER_OF(LogDev->Irq)]; - RTL_BITMAP DmaBitmap[RTL_NUMBER_OF(LogDev->Dma)]; - ULONG IrqData[RTL_NUMBER_OF(LogDev->Irq)]; - ULONG DmaData[RTL_NUMBER_OF(LogDev->Dma)]; - ULONG ResourceCount = 0; + RTL_BITMAP TempBitmap; + ULONG TempBuffer; + ULONG ResourceCount = 0, AltCount = 0, AltOptionalCount = 0; ULONG ListSize, i, j; - BOOLEAN FirstIrq = TRUE, FirstDma = TRUE; + BOOLEAN FirstDescriptor; PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; PIO_RESOURCE_DESCRIPTOR Descriptor; + PISAPNP_ALTERNATIVES Alternatives = LogDev->Alternatives; PAGED_CODE(); /* Count number of requirements */ for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) { + /* + * Use the continue statement to count the number of requirements. + * We handle a possible gap because depedent function can appear at + * any position in the logical device's requirements list. + */ if (!LogDev->Io[i].Description.Length) - break; + continue; ResourceCount++; } for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) { if (!LogDev->Irq[i].Description.Mask) - break; + continue; + + TempBuffer = LogDev->Irq[i].Description.Mask; + RtlInitializeBitMap(&TempBitmap, + &TempBuffer, + RTL_BITS_OF(LogDev->Irq[i].Description.Mask)); + ResourceCount += RtlNumberOfSetBits(&TempBitmap); + } + for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) + { + if (!LogDev->Dma[i].Description.Mask) + continue; + + TempBuffer = LogDev->Dma[i].Description.Mask; + RtlInitializeBitMap(&TempBitmap, + &TempBuffer, + RTL_BITS_OF(LogDev->Dma[i].Description.Mask)); + ResourceCount += RtlNumberOfSetBits(&TempBitmap); + } + for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++) + { + if (!LogDev->MemRange[i].Description.Length) + continue; - IrqData[i] = LogDev->Irq[i].Description.Mask; - RtlInitializeBitMap(&IrqBitmap[i], &IrqData[i], 16); - ResourceCount += RtlNumberOfSetBits(&IrqBitmap[i]); + ResourceCount++; + } + for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++) + { + if (!LogDev->MemRange32[i].Description.Length) + continue; - if (LogDev->Irq[i].Description.Information & 0x4) + ResourceCount++; + } + if (Alternatives) + { + ULONG BitCount; + + if (HasIoAlternatives(Alternatives)) + AltCount++; + if (HasIrqAlternatives(Alternatives)) + AltCount++; + if (HasDmaAlternatives(Alternatives)) + AltCount++; + if (HasMemoryAlternatives(Alternatives)) + AltCount++; + if (HasMemory32Alternatives(Alternatives)) + AltCount++; + ResourceCount += AltCount; + + if (HasIrqAlternatives(Alternatives)) + { + for (i = 0; i < Alternatives->Count; i++) + { + TempBuffer = Alternatives->Irq[i].Mask; + RtlInitializeBitMap(&TempBitmap, + &TempBuffer, + RTL_BITS_OF(Alternatives->Irq[i].Mask)); + BitCount = RtlNumberOfSetBits(&TempBitmap); + + if (BitCount > 1) + AltOptionalCount += BitCount - 1; + } + } + if (HasDmaAlternatives(Alternatives)) { - /* Add room for level sensitive */ - ResourceCount += RtlNumberOfSetBits(&IrqBitmap[i]); + for (i = 0; i < Alternatives->Count; i++) + { + TempBuffer = Alternatives->Dma[i].Mask; + RtlInitializeBitMap(&TempBitmap, + &TempBuffer, + RTL_BITS_OF(Alternatives->Dma[i].Mask)); + BitCount = RtlNumberOfSetBits(&TempBitmap); + + if (BitCount > 1) + AltOptionalCount += BitCount - 1; + } } } if (ResourceCount == 0) return STATUS_SUCCESS; - for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) - { - if (!LogDev->Dma[i].Description.Mask) - break; - - DmaData[i] = LogDev->Dma[i].Description.Mask; - RtlInitializeBitMap(&DmaBitmap[i], &DmaData[i], 8); - ResourceCount += RtlNumberOfSetBits(&DmaBitmap[i]); - } /* Allocate memory to store requirements */ - ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) - + ResourceCount * sizeof(IO_RESOURCE_DESCRIPTOR); + ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST); + if (Alternatives) + { + ListSize += sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1) * Alternatives->Count + + sizeof(IO_RESOURCE_LIST) * (Alternatives->Count - 1) + + sizeof(IO_RESOURCE_DESCRIPTOR) * AltOptionalCount; + } + else + { + ListSize += sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1); + } RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); if (!RequirementsList) return STATUS_NO_MEMORY; RequirementsList->ListSize = ListSize; RequirementsList->InterfaceType = Isa; - RequirementsList->AlternativeLists = 1; + RequirementsList->AlternativeLists = Alternatives ? Alternatives->Count : 1; RequirementsList->List[0].Version = 1; RequirementsList->List[0].Revision = 1; @@ -102,94 +334,178 @@ IsaPnpCreateLogicalDeviceRequirements( if (!LogDev->Io[i].Description.Length) break; - DPRINT("Device.Io[%d].Information = 0x%02x\n", i, LogDev->Io[i].Description.Information); - DPRINT("Device.Io[%d].Minimum = 0x%02x\n", i, LogDev->Io[i].Description.Minimum); - DPRINT("Device.Io[%d].Maximum = 0x%02x\n", i, LogDev->Io[i].Description.Maximum); - DPRINT("Device.Io[%d].Alignment = 0x%02x\n", i, LogDev->Io[i].Description.Alignment); - DPRINT("Device.Io[%d].Length = 0x%02x\n", i, LogDev->Io[i].Description.Length); - - Descriptor->Type = CmResourceTypePort; - Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; - if (LogDev->Io[i].Description.Information & 0x1) - Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; - else - Descriptor->Flags = CM_RESOURCE_PORT_10_BIT_DECODE; - Descriptor->u.Port.Length = LogDev->Io[i].Description.Length; - Descriptor->u.Port.Alignment = LogDev->Io[i].Description.Alignment; - Descriptor->u.Port.MinimumAddress.LowPart = LogDev->Io[i].Description.Minimum; - Descriptor->u.Port.MaximumAddress.LowPart = - LogDev->Io[i].Description.Maximum + LogDev->Io[i].Description.Length - 1; - Descriptor++; + IsaConvertIoRequirement(Descriptor++, &LogDev->Io[i].Description); } for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) { if (!LogDev->Irq[i].Description.Mask) - break; + continue; - DPRINT("Device.Irq[%d].Mask = 0x%02x\n", i, LogDev->Irq[i].Description.Mask); - DPRINT("Device.Irq[%d].Information = 0x%02x\n", i, LogDev->Irq[i].Description.Information); + FirstDescriptor = TRUE; - for (j = 0; j < 15; j++) + for (j = 0; j < RTL_BITS_OF(LogDev->Irq[i].Description.Mask); j++) { - if (!RtlCheckBit(&IrqBitmap[i], j)) + if (!(LogDev->Irq[i].Description.Mask & (1 << j))) continue; - if (FirstIrq) - FirstIrq = FALSE; - else - Descriptor->Option = IO_RESOURCE_ALTERNATIVE; - Descriptor->Type = CmResourceTypeInterrupt; - Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; - Descriptor->u.Interrupt.MinimumVector = Descriptor->u.Interrupt.MaximumVector = j; - Descriptor++; + IsaConvertIrqRequirement(Descriptor++, + &LogDev->Irq[i].Description, + j, + FirstDescriptor); - if (LogDev->Irq[i].Description.Information & 0x4) - { - /* Level interrupt */ - Descriptor->Option = IO_RESOURCE_ALTERNATIVE; - Descriptor->Type = CmResourceTypeInterrupt; - Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; - Descriptor->u.Interrupt.MinimumVector = Descriptor->u.Interrupt.MaximumVector = j; - Descriptor++; - } + if (FirstDescriptor) + FirstDescriptor = FALSE; } } for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) { if (!LogDev->Dma[i].Description.Mask) - break; + continue; - DPRINT("Device.Dma[%d].Mask = 0x%02x\n", i, LogDev->Dma[i].Description.Mask); - DPRINT("Device.Dma[%d].Information = 0x%02x\n", i, LogDev->Dma[i].Description.Information); + FirstDescriptor = TRUE; - for (j = 0; j < 8; j++) + for (j = 0; j < RTL_BITS_OF(LogDev->Dma[i].Description.Mask); j++) { - if (!RtlCheckBit(&DmaBitmap[i], j)) + if (!(LogDev->Dma[i].Description.Mask & (1 << j))) continue; - if (FirstDma) - FirstDma = FALSE; - else - Descriptor->Option = IO_RESOURCE_ALTERNATIVE; - Descriptor->Type = CmResourceTypeDma; - switch (LogDev->Dma[i].Description.Information & 0x3) + IsaConvertDmaRequirement(Descriptor++, + &LogDev->Dma[i].Description, + j, + FirstDescriptor); + + if (FirstDescriptor) + FirstDescriptor = FALSE; + } + } + for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++) + { + if (!LogDev->MemRange[i].Description.Length) + continue; + + IsaConvertMemRangeRequirement(Descriptor++, + &LogDev->MemRange[i].Description); + } + for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++) + { + if (!LogDev->MemRange32[i].Description.Length) + continue; + + IsaConvertMemRange32Requirement(Descriptor++, + &LogDev->MemRange32[i].Description); + } + if (Alternatives) + { + UCHAR BestConfig[ISAPNP_MAX_ALTERNATIVES]; + PIO_RESOURCE_LIST AltList = &RequirementsList->List[0]; + PIO_RESOURCE_LIST NextList = AltList; + + IsaDetermineBestConfig(BestConfig, Alternatives); + + for (i = 0; i < RequirementsList->AlternativeLists; i++) + { + RtlMoveMemory(NextList, AltList, sizeof(IO_RESOURCE_LIST)); + + /* Just because the 'NextList->Count++' correction */ + NextList->Count = ResourceCount; + /* + * For example, the ROM + * 0x15, ... // Logical device ID + * 0x30, // Start DF + * 0x22, 0x04, 0x00 // IRQ + * 0x30, // Start DF + * 0x22, 0xC0, 0x00 // IRQ + * 0x38, // End DF + * 0x2A, 0x20, 0x3A // DMA + * 0x22, 0x00, 0x08 // IRQ + * 0x79, 0x00 // END + * + * will be represented as the following resource requirements list: + * Interface 1 Bus 0 Slot 0 AlternativeLists 2 + * AltList 1, AltList->Count 3 + * [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B + * [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5 + * [Option 0, ShareDisposition 1, Flags 1] INT: Min 2 Max 2 + * End Descriptors + * AltList 2, AltList->Count 4 + * [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B + * [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5 + * [Option 0, ShareDisposition 1, Flags 1] INT: Min 6 Max 6 + * [Option 8, ShareDisposition 1, Flags 1] INT: Min 7 Max 7 + * End Descriptors + */ + + /* Propagate the fixed resources to our new list */ + for (j = 0; j < AltList->Count - AltCount; j++) { - case 0x0: Descriptor->Flags |= CM_RESOURCE_DMA_8; break; - case 0x1: Descriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break; - case 0x2: Descriptor->Flags |= CM_RESOURCE_DMA_16; break; - default: break; + RtlMoveMemory(&NextList->Descriptors[j], + &AltList->Descriptors[j], + sizeof(IO_RESOURCE_DESCRIPTOR)); } - if (LogDev->Dma[i].Description.Information & 0x4) - Descriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER; - switch ((LogDev->Dma[i].Description.Information >> 5) & 0x3) + + Descriptor = &NextList->Descriptors[NextList->Count - AltCount]; + + /* + * Append alternatives. + * NOTE: To keep it simple, we append these to the end of the list. + */ + if (HasIoAlternatives(Alternatives)) { - case 0x1: Descriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break; - case 0x2: Descriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break; - case 0x3: Descriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break; - default: break; + IsaConvertIoRequirement(Descriptor++, + &Alternatives->Io[BestConfig[i]]); } - Descriptor->u.Dma.MinimumChannel = Descriptor->u.Dma.MaximumChannel = j; - Descriptor++; + if (HasIrqAlternatives(Alternatives)) + { + FirstDescriptor = TRUE; + + for (j = 0; j < RTL_BITS_OF(Alternatives->Irq[BestConfig[i]].Mask); j++) + { + if (!(Alternatives->Irq[BestConfig[i]].Mask & (1 << j))) + continue; + + IsaConvertIrqRequirement(Descriptor++, + &Alternatives->Irq[BestConfig[i]], + j, + FirstDescriptor); + + if (FirstDescriptor) + FirstDescriptor = FALSE; + else + NextList->Count++; + } + } + if (HasDmaAlternatives(Alternatives)) + { + FirstDescriptor = TRUE; + + for (j = 0; j < RTL_BITS_OF(Alternatives->Dma[BestConfig[i]].Mask); j++) + { + if (!(Alternatives->Dma[BestConfig[i]].Mask & (1 << j))) + continue; + + IsaConvertDmaRequirement(Descriptor++, + &Alternatives->Dma[BestConfig[i]], + j, + FirstDescriptor); + + if (FirstDescriptor) + FirstDescriptor = FALSE; + else + NextList->Count++; + } + } + if (HasMemoryAlternatives(Alternatives)) + { + IsaConvertMemRangeRequirement(Descriptor++, + &Alternatives->MemRange[BestConfig[i]]); + } + if (HasMemory32Alternatives(Alternatives)) + { + IsaConvertMemRange32Requirement(Descriptor++, + &Alternatives->MemRange32[BestConfig[i]]); + } + + NextList = (PIO_RESOURCE_LIST)(NextList->Descriptors + NextList->Count); } } @@ -197,6 +513,275 @@ IsaPnpCreateLogicalDeviceRequirements( return STATUS_SUCCESS; } +CODE_SEG("PAGE") +BOOLEAN +FindIoDescriptor( + _In_ PISAPNP_LOGICAL_DEVICE LogDevice, + _In_opt_ ULONG Base, + _In_ ULONG RangeStart, + _In_ ULONG RangeEnd, + _Out_opt_ PUCHAR Information, + _Out_opt_ PULONG Length, + _Out_opt_ PUCHAR WriteOrder) +{ + ULONG i; + BOOLEAN Match; + PISAPNP_IO_DESCRIPTION Description; + + PAGED_CODE(); + + for (i = 0; i < RTL_NUMBER_OF(LogDevice->Io); i++) + { + Description = &LogDevice->Io[i].Description; + + Match = Base ? (Base >= Description->Minimum) && (Base <= Description->Maximum) + : (RangeStart >= Description->Minimum) && + (RangeEnd <= (ULONG)(Description->Maximum + Description->Length - 1)); + + if (Match) + { + if (Information) + *Information = Description->Information; + if (Length) + *Length = Description->Length; + if (WriteOrder) + *WriteOrder = LogDevice->Io[i].Index; + + return TRUE; + } + } + + if (!LogDevice->Alternatives) + return FALSE; + + for (i = 0; i < LogDevice->Alternatives->Count; i++) + { + Description = &LogDevice->Alternatives->Io[i]; + + Match = Base ? (Base >= Description->Minimum) && (Base <= Description->Maximum) + : (RangeStart >= Description->Minimum) && + (RangeEnd <= (ULONG)(Description->Maximum + Description->Length - 1)); + + if (Match) + { + if (Information) + *Information = Description->Information; + if (Length) + *Length = Description->Length; + if (WriteOrder) + *WriteOrder = LogDevice->Alternatives->IoIndex; + + return TRUE; + } + } + + return FALSE; +} + +CODE_SEG("PAGE") +BOOLEAN +FindIrqDescriptor( + _In_ PISAPNP_LOGICAL_DEVICE LogDevice, + _In_ ULONG Vector, + _Out_opt_ PUCHAR WriteOrder) +{ + ULONG i, j; + PISAPNP_IRQ_DESCRIPTION Description; + + PAGED_CODE(); + + for (i = 0; i < RTL_NUMBER_OF(LogDevice->Irq); i++) + { + Description = &LogDevice->Irq[i].Description; + + for (j = 0; j < RTL_BITS_OF(Description->Mask); j++) + { + if (Description->Mask & (1 << j)) + { + if (j == Vector) + { + if (WriteOrder) + *WriteOrder = LogDevice->Irq[i].Index; + + return TRUE; + } + } + } + } + + if (!LogDevice->Alternatives) + return FALSE; + + for (i = 0; i < LogDevice->Alternatives->Count; i++) + { + Description = &LogDevice->Alternatives->Irq[i]; + + for (j = 0; j < RTL_BITS_OF(Description->Mask); j++) + { + if (Description->Mask & (1 << j)) + { + if (j == Vector) + { + if (WriteOrder) + *WriteOrder = LogDevice->Alternatives->IrqIndex; + + return TRUE; + } + } + } + } + + return FALSE; +} + +CODE_SEG("PAGE") +BOOLEAN +FindDmaDescriptor( + _In_ PISAPNP_LOGICAL_DEVICE LogDevice, + _In_ ULONG Channel, + _Out_opt_ PUCHAR WriteOrder) +{ + ULONG i, j; + PISAPNP_DMA_DESCRIPTION Description; + + PAGED_CODE(); + + for (i = 0; i < RTL_NUMBER_OF(LogDevice->Dma); i++) + { + Description = &LogDevice->Dma[i].Description; + + for (j = 0; j < RTL_BITS_OF(Description->Mask); j++) + { + if (Description->Mask & (1 << j)) + { + if (j == Channel) + { + if (WriteOrder) + *WriteOrder = LogDevice->Dma[i].Index; + + return TRUE; + } + } + } + } + + if (!LogDevice->Alternatives) + return FALSE; + + for (i = 0; i < LogDevice->Alternatives->Count; i++) + { + Description = &LogDevice->Alternatives->Dma[i]; + + for (j = 0; j < RTL_BITS_OF(Description->Mask); j++) + { + if (Description->Mask & (1 << j)) + { + if (j == Channel) + { + if (WriteOrder) + *WriteOrder = LogDevice->Alternatives->DmaIndex; + + return TRUE; + } + } + } + } + + return FALSE; +} + +CODE_SEG("PAGE") +BOOLEAN +FindMemoryDescriptor( + _In_ PISAPNP_LOGICAL_DEVICE LogDevice, + _In_ ULONG RangeStart, + _In_ ULONG RangeEnd, + _Out_opt_ PBOOLEAN Memory32, + _Out_opt_ PUCHAR Information, + _Out_opt_ PUCHAR WriteOrder) +{ + ULONG i; + PISAPNP_MEMRANGE_DESCRIPTION Description; + PISAPNP_MEMRANGE32_DESCRIPTION Description32; + + PAGED_CODE(); + + for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange); i++) + { + Description = &LogDevice->MemRange[i].Description; + + if ((RangeStart >= (ULONG)(Description->Minimum << 8)) && + (RangeEnd <= (ULONG)((Description->Maximum << 8) + (Description->Length << 8) - 1))) + { + if (Memory32) + *Memory32 = FALSE; + if (Information) + *Information = Description->Information; + if (WriteOrder) + *WriteOrder = LogDevice->MemRange[i].Index; + + return TRUE; + } + } + for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange32); i++) + { + Description32 = &LogDevice->MemRange32[i].Description; + + if ((RangeStart >= Description32->Minimum) && + (RangeEnd <= (Description32->Maximum + Description32->Length - 1))) + { + if (Memory32) + *Memory32 = TRUE; + if (Information) + *Information = Description32->Information; + if (WriteOrder) + *WriteOrder = LogDevice->MemRange32[i].Index; + + return TRUE; + } + } + + if (!LogDevice->Alternatives) + return FALSE; + + for (i = 0; i < LogDevice->Alternatives->Count; i++) + { + Description = &LogDevice->Alternatives->MemRange[i]; + + if ((RangeStart >= (ULONG)(Description->Minimum << 8)) && + (RangeEnd <= (ULONG)((Description->Maximum << 8) + (Description->Length << 8) - 1))) + { + if (Memory32) + *Memory32 = FALSE; + if (Information) + *Information = Description->Information; + if (WriteOrder) + *WriteOrder = LogDevice->Alternatives->MemRangeIndex; + + return TRUE; + } + } + for (i = 0; i < LogDevice->Alternatives->Count; i++) + { + Description32 = &LogDevice->Alternatives->MemRange32[i]; + + if ((RangeStart >= Description32->Minimum) && + (RangeEnd <= (Description32->Maximum + Description32->Length - 1))) + { + if (Memory32) + *Memory32 = TRUE; + if (Information) + *Information = Description32->Information; + if (WriteOrder) + *WriteOrder = LogDevice->Alternatives->MemRange32Index; + + return TRUE; + } + } + + return FALSE; +} + static CODE_SEG("PAGE") NTSTATUS @@ -205,12 +790,16 @@ IsaPnpCreateLogicalDeviceResources( { PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; ULONG ResourceCount = 0; + UCHAR Information; ULONG ListSize, i; PCM_RESOURCE_LIST ResourceList; PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; PAGED_CODE(); + if (!(LogDev->Flags & ISAPNP_HAS_RESOURCES)) + return STATUS_SUCCESS; + /* Count number of required resources */ for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) { @@ -233,6 +822,20 @@ IsaPnpCreateLogicalDeviceResources( else break; } + for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++) + { + if (LogDev->MemRange[i].CurrentBase) + ResourceCount++; + else + break; + } + for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++) + { + if (LogDev->MemRange32[i].CurrentBase) + ResourceCount++; + else + break; + } if (ResourceCount == 0) return STATUS_SUCCESS; @@ -253,17 +856,31 @@ IsaPnpCreateLogicalDeviceResources( ResourceCount = 0; for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) { + ULONG CurrentLength; + if (!LogDev->Io[i].CurrentBase) break; + if (!FindIoDescriptor(LogDev, + LogDev->Io[i].CurrentBase, + 0, + 0, + &Information, + &CurrentLength, + NULL)) + { + goto InvalidBiosResources; + } + Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; Descriptor->Type = CmResourceTypePort; Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; - if (LogDev->Io[i].Description.Information & 0x1) - Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + if (Information & 0x1) + Descriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE; else - Descriptor->Flags = CM_RESOURCE_PORT_10_BIT_DECODE; - Descriptor->u.Port.Length = LogDev->Io[i].Description.Length; + Descriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE; + Descriptor->u.Port.Length = CurrentLength; Descriptor->u.Port.Start.LowPart = LogDev->Io[i].CurrentBase; } for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) @@ -271,6 +888,9 @@ IsaPnpCreateLogicalDeviceResources( if (!LogDev->Irq[i].CurrentNo) break; + if (!FindIrqDescriptor(LogDev, LogDev->Irq[i].CurrentNo, NULL)) + goto InvalidBiosResources; + Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; Descriptor->Type = CmResourceTypeInterrupt; Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; @@ -280,38 +900,85 @@ IsaPnpCreateLogicalDeviceResources( Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; Descriptor->u.Interrupt.Level = LogDev->Irq[i].CurrentNo; Descriptor->u.Interrupt.Vector = LogDev->Irq[i].CurrentNo; - Descriptor->u.Interrupt.Affinity = -1; + Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF; } for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) { if (LogDev->Dma[i].CurrentChannel == 4) break; + if (!FindDmaDescriptor(LogDev, LogDev->Dma[i].CurrentChannel, NULL)) + goto InvalidBiosResources; + Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; Descriptor->Type = CmResourceTypeDma; Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; - switch (LogDev->Dma[i].Description.Information & 0x3) + Descriptor->Flags = CM_RESOURCE_DMA_8; /* Ignore information byte for compatibility */ + Descriptor->u.Dma.Channel = LogDev->Dma[i].CurrentChannel; + } + for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++) + { + if (!LogDev->MemRange[i].CurrentBase) + break; + + if (!FindMemoryDescriptor(LogDev, + LogDev->MemRange[i].CurrentBase, + LogDev->MemRange[i].CurrentLength, + NULL, + &Information, + NULL)) { - case 0x0: Descriptor->Flags |= CM_RESOURCE_DMA_8; break; - case 0x1: Descriptor->Flags |= CM_RESOURCE_DMA_8 | CM_RESOURCE_DMA_16; break; - case 0x2: Descriptor->Flags |= CM_RESOURCE_DMA_16; break; - default: break; + goto InvalidBiosResources; } - if (LogDev->Dma[i].Description.Information & 0x4) - Descriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER; - switch ((LogDev->Dma[i].Description.Information >> 5) & 0x3) + + Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; + Descriptor->Type = CmResourceTypeMemory; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_MEMORY_24; + if ((Information & 0x40) || !(Information & 0x01)) + Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY; + else + Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE; + Descriptor->u.Memory.Length = LogDev->MemRange[i].Description.Length; + Descriptor->u.Memory.Start.QuadPart = LogDev->MemRange[i].CurrentBase; + } + for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++) + { + if (!LogDev->MemRange32[i].CurrentBase) + break; + + if (!FindMemoryDescriptor(LogDev, + LogDev->MemRange32[i].CurrentBase, + LogDev->MemRange32[i].CurrentLength, + NULL, + &Information, + NULL)) { - case 0x1: Descriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break; - case 0x2: Descriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break; - case 0x3: Descriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break; - default: break; + goto InvalidBiosResources; } - Descriptor->u.Dma.Channel = LogDev->Dma[i].CurrentChannel; + + Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; + Descriptor->Type = CmResourceTypeMemory; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_MEMORY_24; + if ((Information & 0x40) || !(Information & 0x01)) + Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY; + else + Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE; + Descriptor->u.Memory.Length = LogDev->MemRange32[i].Description.Length; + Descriptor->u.Memory.Start.QuadPart = LogDev->MemRange32[i].CurrentBase; } PdoExt->ResourceList = ResourceList; PdoExt->ResourceListSize = ListSize; return STATUS_SUCCESS; + +InvalidBiosResources: + DPRINT("Invalid boot resources! (CSN %u, LDN %u)\n", LogDev->CSN, LogDev->LDN); + + LogDev->Flags &= ~ISAPNP_HAS_RESOURCES; + ExFreePoolWithTag(ResourceList, TAG_ISAPNP); + return STATUS_SUCCESS; } _Dispatch_type_(IRP_MJ_CREATE) @@ -544,14 +1211,16 @@ IsaPnpCreateReadPortDOResources( ResourceList->List[0].PartialResourceList.Revision = 1; ResourceList->List[0].PartialResourceList.Count = RTL_NUMBER_OF(Ports); + Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0]; for (i = 0; i < RTL_NUMBER_OF(Ports); i++) { - Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i]; Descriptor->Type = CmResourceTypePort; Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; Descriptor->u.Port.Length = 0x01; Descriptor->u.Port.Start.LowPart = Ports[i]; + + Descriptor++; } PdoExt->ResourceList = ResourceList; diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index 3ba3e5032ac..00b82cb104b 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -279,6 +279,41 @@ HasMemory32Alternatives( /* isapnp.c */ +CODE_SEG("PAGE") +BOOLEAN +FindIoDescriptor( + _In_ PISAPNP_LOGICAL_DEVICE LogDevice, + _In_opt_ ULONG Base, + _In_ ULONG RangeStart, + _In_ ULONG RangeEnd, + _Out_opt_ PUCHAR Information, + _Out_opt_ PULONG Length, + _Out_opt_ PUCHAR WriteOrder); + +CODE_SEG("PAGE") +BOOLEAN +FindIrqDescriptor( + _In_ PISAPNP_LOGICAL_DEVICE LogDevice, + _In_ ULONG Vector, + _Out_opt_ PUCHAR WriteOrder); + +CODE_SEG("PAGE") +BOOLEAN +FindDmaDescriptor( + _In_ PISAPNP_LOGICAL_DEVICE LogDevice, + _In_ ULONG Channel, + _Out_opt_ PUCHAR WriteOrder); + +CODE_SEG("PAGE") +BOOLEAN +FindMemoryDescriptor( + _In_ PISAPNP_LOGICAL_DEVICE LogDevice, + _In_ ULONG RangeStart, + _In_ ULONG RangeEnd, + _Out_opt_ PBOOLEAN Memory32, + _Out_opt_ PUCHAR Information, + _Out_opt_ PUCHAR WriteOrder); + CODE_SEG("PAGE") NTSTATUS IsaPnpCreateReadPortDORequirements(
3 years, 6 months
1
0
0
0
[reactos] 13/20: [ISAPNP] Read all resources when detecting devices
by Dmitry Borisov
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b29a3ac524901bc17e66e…
commit b29a3ac524901bc17e66ebbbcd87d8e70cab6a72 Author: Dmitry Borisov <di.sean(a)protonmail.com> AuthorDate: Sat Mar 20 20:51:05 2021 +0600 Commit: Dmitry Borisov <di.sean(a)protonmail.com> CommitDate: Sun Jun 20 19:24:31 2021 +0600 [ISAPNP] Read all resources when detecting devices --- drivers/bus/isapnp/hardware.c | 180 ++++++++++++++++++++++++++++++++++++++---- drivers/bus/isapnp/isapnp.h | 1 + drivers/bus/isapnp/isapnphw.h | 10 +++ drivers/bus/isapnp/pdo.c | 7 ++ 4 files changed, 182 insertions(+), 16 deletions(-) diff --git a/drivers/bus/isapnp/hardware.c b/drivers/bus/isapnp/hardware.c index 9dae1c66eb6..0b6e200478a 100644 --- a/drivers/bus/isapnp/hardware.c +++ b/drivers/bus/isapnp/hardware.c @@ -83,6 +83,17 @@ ReadWord( (ReadByte(ReadDataPort, Address + 1))); } +static +inline +ULONG +ReadDoubleWord( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Address) +{ + return ((ReadWord(ReadDataPort, Address) << 8) | + (ReadWord(ReadDataPort, Address + 2))); +} + static inline VOID @@ -198,7 +209,7 @@ ReadIrqNo( _In_ PUCHAR ReadDataPort, _In_ UCHAR Index) { - return ReadByte(ReadDataPort, ISAPNP_IRQNO(Index)); + return ReadByte(ReadDataPort, ISAPNP_IRQNO(Index)) & 0x0F; } static @@ -218,7 +229,67 @@ ReadDmaChannel( _In_ PUCHAR ReadDataPort, _In_ UCHAR Index) { - return ReadByte(ReadDataPort, ISAPNP_DMACHANNEL(Index)); + return ReadByte(ReadDataPort, ISAPNP_DMACHANNEL(Index)) & 0x07; +} + +static +inline +USHORT +ReadMemoryBase( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Index) +{ + return ReadWord(ReadDataPort, ISAPNP_MEMBASE(Index)); +} + +static +inline +UCHAR +ReadMemoryControl( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Index) +{ + return ReadByte(ReadDataPort, ISAPNP_MEMCONTROL(Index)); +} + +static +inline +USHORT +ReadMemoryLimit( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Index) +{ + return ReadWord(ReadDataPort, ISAPNP_MEMLIMIT(Index)); +} + +static +inline +ULONG +ReadMemoryBase32( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Index) +{ + return ReadDoubleWord(ReadDataPort, ISAPNP_MEMBASE32(Index)); +} + +static +inline +UCHAR +ReadMemoryControl32( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Index) +{ + return ReadByte(ReadDataPort, ISAPNP_MEMCONTROL32(Index)); +} + +static +inline +ULONG +ReadMemoryLimit32( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Index) +{ + return ReadDoubleWord(ReadDataPort, ISAPNP_MEMLIMIT32(Index)); } static @@ -1016,6 +1087,95 @@ SkipTag: } } +static +CODE_SEG("PAGE") +BOOLEAN +ReadCurrentResources( + _In_ PUCHAR ReadDataPort, + _Inout_ PISAPNP_LOGICAL_DEVICE LogDevice) +{ + UCHAR i; + + PAGED_CODE(); + + DPRINT("%s for CSN %u, LDN %u\n", __FUNCTION__, LogDevice->CSN, LogDevice->LDN); + + WriteLogicalDeviceNumber(LogDevice->LDN); + + /* If the device is not activated by BIOS we just report a NULL resource list */ + if (!(ReadByte(ReadDataPort, ISAPNP_ACTIVATE) & 1)) + { + LogDevice->Flags &= ~ISAPNP_HAS_RESOURCES; + return FALSE; + } + + for (i = 0; i < RTL_NUMBER_OF(LogDevice->Io); i++) + { + LogDevice->Io[i].CurrentBase = ReadIoBase(ReadDataPort, i); + + /* Skip empty descriptors */ + if (!LogDevice->Io[i].CurrentBase) + break; + } + for (i = 0; i < RTL_NUMBER_OF(LogDevice->Irq); i++) + { + LogDevice->Irq[i].CurrentNo = ReadIrqNo(ReadDataPort, i); + + if (!LogDevice->Irq[i].CurrentNo) + break; + + LogDevice->Irq[i].CurrentType = ReadIrqType(ReadDataPort, i); + } + for (i = 0; i < RTL_NUMBER_OF(LogDevice->Dma); i++) + { + LogDevice->Dma[i].CurrentChannel = ReadDmaChannel(ReadDataPort, i); + + if (LogDevice->Dma[i].CurrentChannel == 4) + break; + } + for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange); i++) + { + LogDevice->MemRange[i].CurrentBase = ReadMemoryBase(ReadDataPort, i) << 8; + + if (!LogDevice->MemRange[i].CurrentBase) + break; + + LogDevice->MemRange[i].CurrentLength = ReadMemoryLimit(ReadDataPort, i) << 8; + + if (ReadMemoryControl(ReadDataPort, i) & MEMORY_UPPER_LIMIT) + { + LogDevice->MemRange[i].CurrentLength -= LogDevice->MemRange[i].CurrentBase; + } + else + { + LogDevice->MemRange[i].CurrentLength = + RANGE_LENGTH_TO_LENGTH(LogDevice->MemRange[i].CurrentLength); + } + } + for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange32); i++) + { + LogDevice->MemRange32[i].CurrentBase = ReadMemoryBase32(ReadDataPort, i); + + if (!LogDevice->MemRange32[i].CurrentBase) + break; + + LogDevice->MemRange32[i].CurrentLength = ReadMemoryLimit32(ReadDataPort, i); + + if (ReadMemoryControl32(ReadDataPort, i) & MEMORY_UPPER_LIMIT) + { + LogDevice->MemRange32[i].CurrentLength -= LogDevice->MemRange32[i].CurrentBase; + } + else + { + LogDevice->MemRange32[i].CurrentLength = + RANGE_LENGTH_TO_LENGTH(LogDevice->MemRange32[i].CurrentLength); + } + } + + LogDevice->Flags |= ISAPNP_HAS_RESOURCES; + return TRUE; +} + static CODE_SEG("PAGE") INT @@ -1153,7 +1313,6 @@ IsaHwFillDeviceList( { PISAPNP_LOGICAL_DEVICE LogDevice; UCHAR Csn; - ULONG i; PLIST_ENTRY Entry; PUCHAR ResourceData; @@ -1264,19 +1423,8 @@ IsaHwFillDeviceList( goto Deactivate; } - WriteLogicalDeviceNumber(LogDev); - - for (i = 0; i < ARRAYSIZE(LogDevice->Io); i++) - LogDevice->Io[i].CurrentBase = ReadIoBase(FdoExt->ReadDataPort, i); - for (i = 0; i < ARRAYSIZE(LogDevice->Irq); i++) - { - LogDevice->Irq[i].CurrentNo = ReadIrqNo(FdoExt->ReadDataPort, i); - LogDevice->Irq[i].CurrentType = ReadIrqType(FdoExt->ReadDataPort, i); - } - for (i = 0; i < ARRAYSIZE(LogDevice->Dma); i++) - { - LogDevice->Dma[i].CurrentChannel = ReadDmaChannel(FdoExt->ReadDataPort, i); - } + if (!ReadCurrentResources(FdoExt->ReadDataPort, LogDevice)) + DPRINT("Unable to read boot resources\n"); IsaPnpExtractAscii(LogDevice->VendorId, Identifier.VendorId); LogDevice->ProdId = Identifier.ProdId; diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index d80d05dced1..3ba3e5032ac 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -133,6 +133,7 @@ typedef struct _ISAPNP_LOGICAL_DEVICE ULONG Flags; #define ISAPNP_PRESENT 0x00000001 /**< @brief Cleared when the device is physically removed. */ #define ISAPNP_HAS_MULTIPLE_LOGDEVS 0x00000002 /**< @brief Indicates if the parent card has multiple logical devices. */ +#define ISAPNP_HAS_RESOURCES 0x00000004 /**< @brief Cleared when the device has no boot resources. */ LIST_ENTRY DeviceLink; } ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE; diff --git a/drivers/bus/isapnp/isapnphw.h b/drivers/bus/isapnp/isapnphw.h index b3d8021a62c..c41d6d1b7be 100644 --- a/drivers/bus/isapnp/isapnphw.h +++ b/drivers/bus/isapnp/isapnphw.h @@ -28,10 +28,17 @@ extern "C" { #define ISAPNP_ACTIVATE 0x30 #define ISAPNP_IORANGECHECK 0x31 +#define ISAPNP_MEMBASE(n) (0x40 + ((n) * 8)) +#define ISAPNP_MEMCONTROL(n) (0x42 + ((n) * 8)) +#define MEMORY_UPPER_LIMIT 0x01 +#define ISAPNP_MEMLIMIT(n) (0x43 + ((n) * 8)) #define ISAPNP_IOBASE(n) (0x60 + ((n)*2)) #define ISAPNP_IRQNO(n) (0x70 + ((n)*2)) #define ISAPNP_IRQTYPE(n) (0x71 + ((n) * 2)) #define ISAPNP_DMACHANNEL(n) (0x74 + (n)) +#define ISAPNP_MEMBASE32(n) ((n) == 0 ? 0x76 : (0x70 + (n) * 16)) +#define ISAPNP_MEMCONTROL32(n) ((n) == 0 ? 0x7A : (0x74 + (n) * 16)) +#define ISAPNP_MEMLIMIT32(n) ((n) == 0 ? 0x7B : (0x75 + (n) * 16)) #define ISAPNP_CONFIG_RESET (1 << 0) #define ISAPNP_CONFIG_WAIT_FOR_KEY (1 << 1) @@ -61,6 +68,9 @@ extern "C" { #define ISAPNP_TAG_MEM32RANGE 0x85 #define ISAPNP_TAG_FIXEDMEM32RANGE 0x86 +#define RANGE_LENGTH_TO_LENGTH(RangeLength) ((~(RangeLength) + 1) & 0xFFFFFF) +#define LENGTH_TO_RANGE_LENGTH(Length) (~(Length) + 1) + #include <pshpack1.h> typedef struct _ISAPNP_IDENTIFIER diff --git a/drivers/bus/isapnp/pdo.c b/drivers/bus/isapnp/pdo.c index 67a30891ac1..8490bf9c14d 100644 --- a/drivers/bus/isapnp/pdo.c +++ b/drivers/bus/isapnp/pdo.c @@ -478,6 +478,13 @@ IsaPdoQueryResources( PAGED_CODE(); + if (PdoExt->Common.Signature == IsaPnpLogicalDevice && + !(PdoExt->IsaPnpDevice->Flags & ISAPNP_HAS_RESOURCES)) + { + Irp->IoStatus.Information = 0; + return STATUS_SUCCESS; + } + if (!PdoExt->ResourceList) return Irp->IoStatus.Status;
3 years, 6 months
1
0
0
0
[reactos] 12/20: [ISAPNP] Rewrite the tag parser
by Dmitry Borisov
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ca42de9c314c5c97e212d…
commit ca42de9c314c5c97e212dc08e6a2e2df15324151 Author: Dmitry Borisov <di.sean(a)protonmail.com> AuthorDate: Sat Mar 20 20:50:34 2021 +0600 Commit: Dmitry Borisov <di.sean(a)protonmail.com> CommitDate: Sun Jun 20 19:24:31 2021 +0600 [ISAPNP] Rewrite the tag parser - Support all resource descriptors. - Optimize card identification. - Detect cards that is no longer present on the bus. - Deactivate cards after the identification phase; they will be activated by start device IRP. - Provide a device description and compatible IDs to the device manager. - Prevent duplicate IDs across multiple logical devices. - Suppress warning about the usage of literals in port addresses. --- drivers/bus/isapnp/hardware.c | 868 +++++++++++++++++++++++++++++++++++++----- drivers/bus/isapnp/isapnp.c | 8 +- drivers/bus/isapnp/isapnp.h | 120 +++++- drivers/bus/isapnp/isapnphw.h | 72 ++-- drivers/bus/isapnp/pdo.c | 194 +++++++++- 5 files changed, 1114 insertions(+), 148 deletions(-) diff --git a/drivers/bus/isapnp/hardware.c b/drivers/bus/isapnp/hardware.c index 6673e200194..9dae1c66eb6 100644 --- a/drivers/bus/isapnp/hardware.c +++ b/drivers/bus/isapnp/hardware.c @@ -4,6 +4,7 @@ * PURPOSE: Hardware support code * COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman(a)reactos.org> * Copyright 2020 Hervé Poussineau <hpoussin(a)reactos.org> + * Copyright 2021 Dmitry Borisov <di.sean(a)protonmail.com> */ #include "isapnp.h" @@ -11,6 +12,17 @@ #define NDEBUG #include <debug.h> +#ifdef _MSC_VER +#pragma warning(disable:28138) /* ISA bus always uses hardcoded port addresses */ +#endif + +typedef enum +{ + dfNotStarted, + dfStarted, + dfDone +} DEPEDENT_FUNCTION_STATE; + static inline VOID @@ -291,6 +303,24 @@ Peek( } } +static +CODE_SEG("PAGE") +VOID +PeekCached( + _In_reads_bytes_(Length) PUCHAR ResourceData, + _Out_writes_bytes_all_(Length) PVOID Buffer, + _In_ USHORT Length) +{ + PUCHAR Dest = Buffer; + + PAGED_CODE(); + + while (Length--) + { + *Dest++ = *ResourceData++; + } +} + static CODE_SEG("PAGE") UCHAR @@ -318,24 +348,48 @@ IsaPnpChecksum( static CODE_SEG("PAGE") -BOOLEAN +VOID +IsaPnpExtractAscii( + _Out_writes_all_(3) PUCHAR Buffer, + _In_ USHORT CompressedData) +{ + PAGED_CODE(); + + Buffer[0] = ((CompressedData >> 2) & 0x1F) + 'A' - 1; + Buffer[1] = (((CompressedData & 0x3) << 3) | ((CompressedData >> 13) & 0x7)) + 'A' - 1; + Buffer[2] = ((CompressedData >> 8) & 0x1F) + 'A' - 1; +} + +static +CODE_SEG("PAGE") +NTSTATUS ReadTags( _In_ PUCHAR ReadDataPort, - _In_ USHORT LogDev, - _Inout_ PISAPNP_LOGICAL_DEVICE LogDevice) + _Out_writes_(ISAPNP_MAX_RESOURCEDATA) PUCHAR Buffer, + _In_ ULONG MaxLength, + _Out_ PUSHORT MaxLogDev) { - BOOLEAN res = FALSE; - PVOID Buffer; - USHORT Tag, TagLen, MaxLen; - ULONG NumberOfIo = 0, NumberOfIrq = 0, NumberOfDma = 0; - PAGED_CODE(); - LogDev += 1; + *MaxLogDev = 0; while (TRUE) { + UCHAR Tag; + USHORT TagLen; + + if (MaxLength < 1) + return STATUS_BUFFER_OVERFLOW; + Tag = PeekByte(ReadDataPort); + if (Tag == 0) + { + DPRINT("Invalid tag\n"); + return STATUS_INVALID_PARAMETER_1; + } + *Buffer++ = Tag; + --MaxLength; + if (ISAPNP_IS_SMALL_TAG(Tag)) { TagLen = ISAPNP_SMALL_TAG_LEN(Tag); @@ -343,64 +397,623 @@ ReadTags( } else { - TagLen = PeekByte(ReadDataPort) + (PeekByte(ReadDataPort) << 8); + UCHAR Temp[2]; + + if (MaxLength < sizeof(Temp)) + return STATUS_BUFFER_OVERFLOW; + + Peek(ReadDataPort, &Temp, sizeof(Temp)); + *Buffer++ = Temp[0]; + *Buffer++ = Temp[1]; + MaxLength -= sizeof(Temp); + + TagLen = Temp[0] + (Temp[1] << 8); Tag = ISAPNP_LARGE_TAG_NAME(Tag); } - if (Tag == ISAPNP_TAG_END) - break; - Buffer = NULL; - if (Tag == ISAPNP_TAG_LOGDEVID) - { - MaxLen = sizeof(LogDevice->LogDevId); - Buffer = &LogDevice->LogDevId; - LogDev--; - } - else if (Tag == ISAPNP_TAG_IRQ && NumberOfIrq < ARRAYSIZE(LogDevice->Irq)) - { - MaxLen = sizeof(LogDevice->Irq[NumberOfIrq].Description); - Buffer = &LogDevice->Irq[NumberOfIrq].Description; - NumberOfIrq++; - } - else if (Tag == ISAPNP_TAG_IOPORT && NumberOfIo < ARRAYSIZE(LogDevice->Io)) + if (Tag == 0xFF && TagLen == 0xFFFF) { - MaxLen = sizeof(LogDevice->Io[NumberOfIo].Description); - Buffer = &LogDevice->Io[NumberOfIo].Description; - NumberOfIo++; + DPRINT("Invalid tag\n"); + return STATUS_INVALID_PARAMETER_2; } - else if (Tag == ISAPNP_TAG_DMA && NumberOfDma < ARRAYSIZE(LogDevice->Dma)) + + if (TagLen > MaxLength) + return STATUS_BUFFER_OVERFLOW; + + Peek(ReadDataPort, Buffer, TagLen); + MaxLength -= TagLen; + Buffer += TagLen; + + if (Tag == ISAPNP_TAG_LOGDEVID) + (*MaxLogDev)++; + + if (Tag == ISAPNP_TAG_END) + break; + } + + return STATUS_SUCCESS; +} + +static +CODE_SEG("PAGE") +VOID +FreeLogicalDevice( + _In_ __drv_freesMem(Mem) PISAPNP_LOGICAL_DEVICE LogDevice) +{ + PLIST_ENTRY Entry; + + PAGED_CODE(); + + if (LogDevice->FriendlyName) + ExFreePoolWithTag(LogDevice->FriendlyName, TAG_ISAPNP); + + if (LogDevice->Alternatives) + ExFreePoolWithTag(LogDevice->Alternatives, TAG_ISAPNP); + + Entry = LogDevice->CompatibleIdList.Flink; + while (Entry != &LogDevice->CompatibleIdList) + { + PISAPNP_COMPATIBLE_ID_ENTRY CompatibleId = + CONTAINING_RECORD(Entry, ISAPNP_COMPATIBLE_ID_ENTRY, IdLink); + + RemoveEntryList(&CompatibleId->IdLink); + + Entry = Entry->Flink; + + ExFreePoolWithTag(CompatibleId, TAG_ISAPNP); + } + + ExFreePoolWithTag(LogDevice, TAG_ISAPNP); +} + +static +CODE_SEG("PAGE") +NTSTATUS +ParseTags( + _In_ PUCHAR ResourceData, + _In_ USHORT LogDevToParse, + _Inout_ PISAPNP_LOGICAL_DEVICE LogDevice) +{ + USHORT LogDev; + DEPEDENT_FUNCTION_STATE DfState = dfNotStarted; + PUCHAR IdStrPos = NULL; + USHORT IdStrLen = 0; + UCHAR NumberOfIo = 0, + NumberOfIrq = 0, + NumberOfDma = 0, + NumberOfMemRange = 0, + NumberOfMemRange32 = 0, + NumberOfDepedentSet = 0; + + PAGED_CODE(); + + DPRINT("%s for CSN %u, LDN %u\n", __FUNCTION__, LogDevice->CSN, LogDevice->LDN); + + LogDev = LogDevToParse + 1; + + while (TRUE) + { + UCHAR Tag; + USHORT TagLen; + + Tag = *ResourceData++; + + if (ISAPNP_IS_SMALL_TAG(Tag)) { - MaxLen = sizeof(LogDevice->Dma[NumberOfDma].Description); - Buffer = &LogDevice->Dma[NumberOfDma].Description; - NumberOfDma++; + TagLen = ISAPNP_SMALL_TAG_LEN(Tag); + Tag = ISAPNP_SMALL_TAG_NAME(Tag); } - else if (LogDev == 0) + else { - DPRINT1("Found unknown tag 0x%x (len %d)\n", Tag, TagLen); + TagLen = *ResourceData++; + TagLen += *ResourceData++ << 8; + + Tag = ISAPNP_LARGE_TAG_NAME(Tag); } - if (Buffer && LogDev == 0) + switch (Tag) { - res = TRUE; - if (MaxLen > TagLen) + case ISAPNP_TAG_LOGDEVID: { - Peek(ReadDataPort, Buffer, TagLen); + ISAPNP_LOGDEVID Temp; + + --LogDev; + + if (LogDev != 0 || + (TagLen > sizeof(ISAPNP_LOGDEVID) || + TagLen < (sizeof(ISAPNP_LOGDEVID) - 1))) + { + goto SkipTag; + } + + PeekCached(ResourceData, &Temp, TagLen); + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " VendorId 0x%04X\n" + " ProdId 0x%04X\n", + Tag, TagLen, + Temp.VendorId, + Temp.ProdId); + + IsaPnpExtractAscii(LogDevice->LogVendorId, Temp.VendorId); + LogDevice->LogProdId = RtlUshortByteSwap(Temp.ProdId); + + break; } - else + + case ISAPNP_TAG_COMPATDEVID: { - Peek(ReadDataPort, Buffer, MaxLen); - Peek(ReadDataPort, NULL, TagLen - MaxLen); + ISAPNP_COMPATID Temp; + PISAPNP_COMPATIBLE_ID_ENTRY CompatibleId; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_COMPATID)) + goto SkipTag; + + CompatibleId = ExAllocatePoolWithTag(PagedPool, + sizeof(ISAPNP_COMPATIBLE_ID_ENTRY), + TAG_ISAPNP); + if (!CompatibleId) + return STATUS_INSUFFICIENT_RESOURCES; + + PeekCached(ResourceData, &Temp, TagLen); + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " VendorId 0x%04X\n" + " ProdId 0x%04X\n", + Tag, TagLen, + Temp.VendorId, + Temp.ProdId); + + IsaPnpExtractAscii(CompatibleId->VendorId, Temp.VendorId); + CompatibleId->ProdId = RtlUshortByteSwap(Temp.ProdId); + + InsertTailList(&LogDevice->CompatibleIdList, &CompatibleId->IdLink); + + break; } - } - else - { - /* We don't want to read informations on this - * logical device, or we don't know the tag. */ - Peek(ReadDataPort, NULL, TagLen); - } - }; - return res; + case ISAPNP_TAG_IRQ: + { + PISAPNP_IRQ_DESCRIPTION Description; + + if (LogDev != 0 || + (TagLen > sizeof(ISAPNP_IRQ_DESCRIPTION) || + TagLen < (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1)) || + NumberOfIrq >= RTL_NUMBER_OF(LogDevice->Irq)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->Irq[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->Irq[NumberOfIrq].Description; + + LogDevice->Irq[NumberOfIrq].Index = NumberOfIrq; + ++NumberOfIrq; + } + + PeekCached(ResourceData, Description, TagLen); + ResourceData += TagLen; + + if (TagLen == (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1)) + Description->Information = 0x01; + + DPRINT("Found tag 0x%X (len %u)\n" + " Mask 0x%X\n" + " Information 0x%X\n", + Tag, TagLen, + Description->Mask, + Description->Information); + + break; + } + + case ISAPNP_TAG_DMA: + { + PISAPNP_DMA_DESCRIPTION Description; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_DMA_DESCRIPTION) || + NumberOfDma >= RTL_NUMBER_OF(LogDevice->Dma)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->Dma[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->Dma[NumberOfDma].Description; + + LogDevice->Dma[NumberOfDma].Index = NumberOfDma; + ++NumberOfDma; + } + + PeekCached(ResourceData, Description, TagLen); + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " Mask 0x%X\n" + " Information 0x%X\n", + Tag, TagLen, + Description->Mask, + Description->Information); + + break; + } + + case ISAPNP_TAG_STARTDEP: + { + if (LogDev != 0 || TagLen > 1 || + NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + { + goto SkipTag; + } + + if (DfState == dfNotStarted) + { + LogDevice->Alternatives = ExAllocatePoolZero(PagedPool, + sizeof(ISAPNP_ALTERNATIVES), + TAG_ISAPNP); + if (!LogDevice->Alternatives) + return STATUS_INSUFFICIENT_RESOURCES; + + DfState = dfStarted; + } + else if (DfState == dfStarted) + { + ++NumberOfDepedentSet; + } + else + { + goto SkipTag; + } + + ++LogDevice->Alternatives->Count; + + if (TagLen != 1) + { + LogDevice->Alternatives->Priority[NumberOfDepedentSet] = 1; + } + else + { + PeekCached(ResourceData, + &LogDevice->Alternatives->Priority[NumberOfDepedentSet], + TagLen); + ResourceData += TagLen; + } + + DPRINT("*** Start depedent set %u, priority %u ***\n", + NumberOfDepedentSet, + LogDevice->Alternatives->Priority[NumberOfDepedentSet]); + + break; + } + + case ISAPNP_TAG_ENDDEP: + { + if (LogDev != 0 || DfState != dfStarted) + goto SkipTag; + + DfState = dfDone; + + ResourceData += TagLen; + + if (HasIoAlternatives(LogDevice->Alternatives)) + LogDevice->Alternatives->IoIndex = NumberOfIo++; + if (HasIrqAlternatives(LogDevice->Alternatives)) + LogDevice->Alternatives->IrqIndex = NumberOfIrq++; + if (HasDmaAlternatives(LogDevice->Alternatives)) + LogDevice->Alternatives->DmaIndex = NumberOfDma++; + if (HasMemoryAlternatives(LogDevice->Alternatives)) + LogDevice->Alternatives->MemRangeIndex = NumberOfMemRange++; + if (HasMemory32Alternatives(LogDevice->Alternatives)) + LogDevice->Alternatives->MemRange32Index = NumberOfMemRange32++; + + DPRINT("*** End of depedent set ***\n"); + + break; + } + + case ISAPNP_TAG_IOPORT: + { + PISAPNP_IO_DESCRIPTION Description; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_IO_DESCRIPTION) || + NumberOfIo >= RTL_NUMBER_OF(LogDevice->Io)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->Io[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->Io[NumberOfIo].Description; + + LogDevice->Io[NumberOfIo].Index = NumberOfIo; + ++NumberOfIo; + } + + PeekCached(ResourceData, Description, TagLen); + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " Information 0x%X\n" + " Minimum 0x%X\n" + " Maximum 0x%X\n" + " Alignment 0x%X\n" + " Length 0x%X\n", + Tag, TagLen, + Description->Information, + Description->Minimum, + Description->Maximum, + Description->Alignment, + Description->Length); + + break; + } + + case ISAPNP_TAG_FIXEDIO: + { + ISAPNP_FIXED_IO_DESCRIPTION Temp; + PISAPNP_IO_DESCRIPTION Description; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_FIXED_IO_DESCRIPTION) || + NumberOfIo >= RTL_NUMBER_OF(LogDevice->Io)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->Io[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->Io[NumberOfIo].Description; + + LogDevice->Io[NumberOfIo].Index = NumberOfIo; + ++NumberOfIo; + } + + PeekCached(ResourceData, &Temp, TagLen); + ResourceData += TagLen; + + Description->Information = 0; + Description->Minimum = + Description->Maximum = Temp.IoBase; + Description->Alignment = 1; + Description->Length = Temp.Length; + + DPRINT("Found tag 0x%X (len %u)\n" + " IoBase 0x%X\n" + " Length 0x%X\n", + Tag, TagLen, + Temp.IoBase, + Temp.Length); + + break; + } + + case ISAPNP_TAG_END: + { + if (IdStrPos) + { + PSTR End; + + LogDevice->FriendlyName = ExAllocatePoolWithTag(PagedPool, + IdStrLen + sizeof(ANSI_NULL), + TAG_ISAPNP); + if (!LogDevice->FriendlyName) + return STATUS_INSUFFICIENT_RESOURCES; + + PeekCached(IdStrPos, LogDevice->FriendlyName, IdStrLen); + + End = LogDevice->FriendlyName + IdStrLen - 1; + while (End > LogDevice->FriendlyName && *End == ' ') + { + --End; + } + *++End = ANSI_NULL; + } + + return STATUS_SUCCESS; + } + + case ISAPNP_TAG_MEMRANGE: + { + PISAPNP_MEMRANGE_DESCRIPTION Description; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_MEMRANGE_DESCRIPTION) || + NumberOfMemRange >= RTL_NUMBER_OF(LogDevice->MemRange)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->MemRange[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->MemRange[NumberOfMemRange].Description; + + LogDevice->MemRange[NumberOfMemRange].Index = NumberOfMemRange; + ++NumberOfMemRange; + } + + PeekCached(ResourceData, Description, TagLen); + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " Information 0x%X\n" + " Minimum 0x%X\n" + " Maximum 0x%X\n" + " Alignment 0x%X\n" + " Length 0x%X\n", + Tag, TagLen, + Description->Information, + Description->Minimum, + Description->Maximum, + Description->Alignment, + Description->Length); + + break; + } + + case ISAPNP_TAG_ANSISTR: + { + /* If logical device identifier is not supplied, use card identifier */ + if (LogDev == LogDevToParse + 1 || LogDev == 0) + { + IdStrPos = ResourceData; + IdStrLen = TagLen; + + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " '%.*s'\n", + Tag, TagLen, + IdStrLen, + IdStrPos); + } + else + { + goto SkipTag; + } + + break; + } + + case ISAPNP_TAG_MEM32RANGE: + { + PISAPNP_MEMRANGE32_DESCRIPTION Description; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_MEMRANGE32_DESCRIPTION) || + NumberOfMemRange32 >= RTL_NUMBER_OF(LogDevice->MemRange32)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->MemRange32[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->MemRange32[NumberOfMemRange32].Description; + + LogDevice->MemRange32[NumberOfMemRange32].Index = NumberOfMemRange32; + ++NumberOfMemRange32; + } + + PeekCached(ResourceData, Description, TagLen); + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " Information 0x%X\n" + " Minimum 0x%08lX\n" + " Maximum 0x%08lX\n" + " Alignment 0x%08lX\n" + " Length 0x%08lX\n", + Tag, TagLen, + Description->Information, + Description->Minimum, + Description->Maximum, + Description->Alignment, + Description->Length); + + break; + } + + case ISAPNP_TAG_FIXEDMEM32RANGE: + { + ISAPNP_FIXEDMEMRANGE_DESCRIPTION Temp; + PISAPNP_MEMRANGE32_DESCRIPTION Description; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_FIXEDMEMRANGE_DESCRIPTION) || + NumberOfMemRange32 >= RTL_NUMBER_OF(LogDevice->MemRange32)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->MemRange32[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->MemRange32[NumberOfMemRange32].Description; + + LogDevice->MemRange32[NumberOfMemRange32].Index = NumberOfMemRange32; + ++NumberOfMemRange32; + } + + PeekCached(ResourceData, &Temp, TagLen); + ResourceData += TagLen; + + Description->Information = Temp.Information; + Description->Minimum = + Description->Maximum = Temp.MemoryBase; + Description->Alignment = 1; + Description->Length = Temp.Length; + + DPRINT("Found tag 0x%X (len %u)\n" + " Information 0x%X\n" + " MemoryBase 0x%08lX\n" + " Length 0x%08lX\n", + Tag, TagLen, + Temp.Information, + Temp.MemoryBase, + Temp.Length); + + break; + } + +SkipTag: + default: + { + if (LogDev == 0) + DPRINT("Found unknown tag 0x%X (len %u)\n", Tag, TagLen); + + /* We don't want to read informations on this + * logical device, or we don't know the tag. */ + ResourceData += TagLen; + break; + } + } + } } static @@ -532,54 +1145,127 @@ DeviceActivation( WaitForKey(); } -static +_Requires_lock_held_(FdoExt->DeviceSyncEvent) CODE_SEG("PAGE") NTSTATUS -ProbeIsaPnpBus( +IsaHwFillDeviceList( _In_ PISAPNP_FDO_EXTENSION FdoExt) { PISAPNP_LOGICAL_DEVICE LogDevice; - ISAPNP_IDENTIFIER Identifier; - USHORT Csn; - USHORT LogDev; + UCHAR Csn; ULONG i; + PLIST_ENTRY Entry; + PUCHAR ResourceData; PAGED_CODE(); ASSERT(FdoExt->ReadDataPort); - for (Csn = 1; Csn <= 0xFF; Csn++) + DPRINT("%s for read port 0x%p\n", __FUNCTION__, FdoExt->ReadDataPort); + + ResourceData = ExAllocatePoolWithTag(PagedPool, ISAPNP_MAX_RESOURCEDATA, TAG_ISAPNP); + if (!ResourceData) + { + DPRINT1("Failed to allocate memory for cache data\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + for (Entry = FdoExt->DeviceListHead.Flink; + Entry != &FdoExt->DeviceListHead; + Entry = Entry->Flink) + { + LogDevice = CONTAINING_RECORD(Entry, ISAPNP_LOGICAL_DEVICE, DeviceLink); + + LogDevice->Flags &= ~ISAPNP_PRESENT; + } + + WaitForKey(); + SendKey(); + + for (Csn = 1; Csn <= FdoExt->Cards; Csn++) { - for (LogDev = 0; LogDev <= 0xFF; LogDev++) + NTSTATUS Status; + UCHAR TempId[3], LogDev; + ISAPNP_IDENTIFIER Identifier; + USHORT MaxLogDev; + + Wake(Csn); + + Peek(FdoExt->ReadDataPort, &Identifier, sizeof(Identifier)); + + IsaPnpExtractAscii(TempId, Identifier.VendorId); + Identifier.ProdId = RtlUshortByteSwap(Identifier.ProdId); + + Status = ReadTags(FdoExt->ReadDataPort, ResourceData, ISAPNP_MAX_RESOURCEDATA, &MaxLogDev); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to read tags with status 0x%08lx, CSN %u\n", Status, Csn); + continue; + } + + DPRINT("Detected ISA PnP device - VID: '%.3s' PID: 0x%04x SN: 0x%08lX\n", + TempId, Identifier.ProdId, Identifier.Serial); + + for (LogDev = 0; LogDev < MaxLogDev; LogDev++) { + BOOLEAN IsAlreadyEnumerated = FALSE; + + for (Entry = FdoExt->DeviceListHead.Flink; + Entry != &FdoExt->DeviceListHead; + Entry = Entry->Flink) + { + LogDevice = CONTAINING_RECORD(Entry, ISAPNP_LOGICAL_DEVICE, DeviceLink); + + /* This logical device has already been enumerated */ + if ((LogDevice->SerialNumber == Identifier.Serial) && + (RtlCompareMemory(LogDevice->VendorId, TempId, 3) == 3) && + (LogDevice->ProdId == Identifier.ProdId) && + (LogDevice->LDN == LogDev)) + { + LogDevice->Flags |= ISAPNP_PRESENT; + + /* Assign a new CSN */ + LogDevice->CSN = Csn; + + if (LogDevice->Pdo) + { + PISAPNP_PDO_EXTENSION PdoExt = LogDevice->Pdo->DeviceExtension; + + if (PdoExt->Common.State == dsStarted) + ActivateDevice(LogDev); + } + + DPRINT("Skip CSN %u, LDN %u\n", LogDevice->CSN, LogDevice->LDN); + IsAlreadyEnumerated = TRUE; + break; + } + } + + if (IsAlreadyEnumerated) + continue; + LogDevice = ExAllocatePoolZero(NonPagedPool, sizeof(ISAPNP_LOGICAL_DEVICE), TAG_ISAPNP); if (!LogDevice) - return STATUS_NO_MEMORY; + { + DPRINT1("Failed to allocate logical device!\n"); + goto Deactivate; + } + + InitializeListHead(&LogDevice->CompatibleIdList); LogDevice->CSN = Csn; LogDevice->LDN = LogDev; - WaitForKey(); - SendKey(); - Wake(Csn); - - Peek(FdoExt->ReadDataPort, &Identifier, sizeof(Identifier)); - - if (Identifier.VendorId & 0x80) + Status = ParseTags(ResourceData, LogDev, LogDevice); + if (!NT_SUCCESS(Status)) { - ExFreePoolWithTag(LogDevice, TAG_ISAPNP); - return STATUS_SUCCESS; + DPRINT1("Failed to parse tags with status 0x%08lx, CSN %u, LDN %u\n", + Status, LogDevice->CSN, LogDevice->LDN); + FreeLogicalDevice(LogDevice); + goto Deactivate; } - if (!ReadTags(FdoExt->ReadDataPort, LogDev, LogDevice)) - break; - WriteLogicalDeviceNumber(LogDev); - LogDevice->VendorId[0] = ((LogDevice->LogDevId.VendorId >> 2) & 0x1f) + 'A' - 1, - LogDevice->VendorId[1] = (((LogDevice->LogDevId.VendorId & 0x3) << 3) | ((LogDevice->LogDevId.VendorId >> 13) & 0x7)) + 'A' - 1, - LogDevice->VendorId[2] = ((LogDevice->LogDevId.VendorId >> 8) & 0x1f) + 'A' - 1, - LogDevice->ProdId = RtlUshortByteSwap(LogDevice->LogDevId.ProdId); - LogDevice->SerialNumber = Identifier.Serial; for (i = 0; i < ARRAYSIZE(LogDevice->Io); i++) LogDevice->Io[i].CurrentBase = ReadIoBase(FdoExt->ReadDataPort, i); for (i = 0; i < ARRAYSIZE(LogDevice->Irq); i++) @@ -592,27 +1278,37 @@ ProbeIsaPnpBus( LogDevice->Dma[i].CurrentChannel = ReadDmaChannel(FdoExt->ReadDataPort, i); } - DPRINT1("Detected ISA PnP device - VID: '%3s' PID: 0x%x SN: 0x%08x IoBase: 0x%x IRQ:0x%x\n", - LogDevice->VendorId, LogDevice->ProdId, LogDevice->SerialNumber, LogDevice->Io[0].CurrentBase, LogDevice->Irq[0].CurrentNo); + IsaPnpExtractAscii(LogDevice->VendorId, Identifier.VendorId); + LogDevice->ProdId = Identifier.ProdId; + LogDevice->SerialNumber = Identifier.Serial; - WaitForKey(); + if (MaxLogDev > 1) + LogDevice->Flags |= ISAPNP_HAS_MULTIPLE_LOGDEVS; + + LogDevice->Flags |= ISAPNP_PRESENT; InsertTailList(&FdoExt->DeviceListHead, &LogDevice->DeviceLink); FdoExt->DeviceCount++; + + /* Now we wait for the start device IRP */ +Deactivate: + DeactivateDevice(LogDev); } } + ExFreePoolWithTag(ResourceData, TAG_ISAPNP); + return STATUS_SUCCESS; } CODE_SEG("PAGE") -NTSTATUS +ULONG IsaHwTryReadDataPort( _In_ PUCHAR ReadDataPort) { PAGED_CODE(); - return TryIsolate(ReadDataPort) > 0 ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; + return TryIsolate(ReadDataPort); } _IRQL_requires_max_(DISPATCH_LEVEL) @@ -636,13 +1332,3 @@ IsaHwDeactivateDevice( return STATUS_SUCCESS; } - -CODE_SEG("PAGE") -NTSTATUS -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 41f52c9aed6..842929ee0ce 100644 --- a/drivers/bus/isapnp/isapnp.c +++ b/drivers/bus/isapnp/isapnp.c @@ -676,11 +676,11 @@ IsaPnpFillDeviceRelations( DPRINT("Rescan ISA PnP bus\n"); /* Run the isolation protocol */ - if (NT_SUCCESS(IsaHwTryReadDataPort(FdoExt->ReadDataPort))) - { - /* Card identification */ + FdoExt->Cards = IsaHwTryReadDataPort(FdoExt->ReadDataPort); + + /* Card identification */ + if (FdoExt->Cards > 0) (VOID)IsaHwFillDeviceList(FdoExt); - } } ReadPortExt->Flags &= ~ISAPNP_SCANNED_BY_READ_PORT; diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index ed4a6027a9b..d80d05dced1 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -23,6 +23,12 @@ extern "C" { #define TAG_ISAPNP 'pasI' +/** @brief Maximum size of resource data structure supported by the driver. */ +#define ISAPNP_MAX_RESOURCEDATA 0x1000 + +/** @brief Maximum number of Start DF tags supported by the driver. */ +#define ISAPNP_MAX_ALTERNATIVES 8 + typedef enum { dsStopped, @@ -33,6 +39,7 @@ typedef struct _ISAPNP_IO { USHORT CurrentBase; ISAPNP_IO_DESCRIPTION Description; + UCHAR Index; } ISAPNP_IO, *PISAPNP_IO; typedef struct _ISAPNP_IRQ @@ -40,29 +47,92 @@ typedef struct _ISAPNP_IRQ UCHAR CurrentNo; UCHAR CurrentType; ISAPNP_IRQ_DESCRIPTION Description; + UCHAR Index; } ISAPNP_IRQ, *PISAPNP_IRQ; typedef struct _ISAPNP_DMA { UCHAR CurrentChannel; ISAPNP_DMA_DESCRIPTION Description; + UCHAR Index; } ISAPNP_DMA, *PISAPNP_DMA; +typedef struct _ISAPNP_MEMRANGE +{ + ULONG CurrentBase; + ULONG CurrentLength; + ISAPNP_MEMRANGE_DESCRIPTION Description; + UCHAR Index; +} ISAPNP_MEMRANGE, *PISAPNP_MEMRANGE; + +typedef struct _ISAPNP_MEMRANGE32 +{ + ULONG CurrentBase; + ULONG CurrentLength; + ISAPNP_MEMRANGE32_DESCRIPTION Description; + UCHAR Index; +} ISAPNP_MEMRANGE32, *PISAPNP_MEMRANGE32; + +typedef struct _ISAPNP_COMPATIBLE_ID_ENTRY +{ + UCHAR VendorId[3]; + USHORT ProdId; + LIST_ENTRY IdLink; +} ISAPNP_COMPATIBLE_ID_ENTRY, *PISAPNP_COMPATIBLE_ID_ENTRY; + +typedef struct _ISAPNP_ALTERNATIVES +{ + ISAPNP_IO_DESCRIPTION Io[ISAPNP_MAX_ALTERNATIVES]; + ISAPNP_IRQ_DESCRIPTION Irq[ISAPNP_MAX_ALTERNATIVES]; + ISAPNP_DMA_DESCRIPTION Dma[ISAPNP_MAX_ALTERNATIVES]; + ISAPNP_MEMRANGE_DESCRIPTION MemRange[ISAPNP_MAX_ALTERNATIVES]; + ISAPNP_MEMRANGE32_DESCRIPTION MemRange32[ISAPNP_MAX_ALTERNATIVES]; + UCHAR Priority[ISAPNP_MAX_ALTERNATIVES]; + UCHAR IoIndex; + UCHAR IrqIndex; + UCHAR DmaIndex; + UCHAR MemRangeIndex; + UCHAR MemRange32Index; + + _Field_range_(0, ISAPNP_MAX_ALTERNATIVES) + UCHAR Count; +} ISAPNP_ALTERNATIVES, *PISAPNP_ALTERNATIVES; + typedef struct _ISAPNP_LOGICAL_DEVICE { PDEVICE_OBJECT Pdo; - ISAPNP_LOGDEVID LogDevId; + + /** + * @name The card data. + * @{ + */ + UCHAR CSN; UCHAR VendorId[3]; USHORT ProdId; ULONG SerialNumber; + /**@}*/ + + /** + * @name The logical device data. + * @{ + */ + UCHAR LDN; + UCHAR LogVendorId[3]; + USHORT LogProdId; + LIST_ENTRY CompatibleIdList; + PSTR FriendlyName; + PISAPNP_ALTERNATIVES Alternatives; + ISAPNP_IO Io[8]; ISAPNP_IRQ Irq[2]; ISAPNP_DMA Dma[2]; - UCHAR CSN; - UCHAR LDN; + ISAPNP_MEMRANGE MemRange[4]; + ISAPNP_MEMRANGE32 MemRange32[4]; + /**@}*/ ULONG Flags; #define ISAPNP_PRESENT 0x00000001 /**< @brief Cleared when the device is physically removed. */ +#define ISAPNP_HAS_MULTIPLE_LOGDEVS 0x00000002 /**< @brief Indicates if the parent card has multiple logical devices. */ LIST_ENTRY DeviceLink; } ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE; @@ -98,6 +168,7 @@ typedef struct _ISAPNP_FDO_EXTENSION PDRIVER_OBJECT DriverObject; PUCHAR ReadDataPort; + ULONG Cards; LIST_ENTRY BusLink; } ISAPNP_FDO_EXTENSION, *PISAPNP_FDO_EXTENSION; @@ -165,6 +236,46 @@ IsaPnpReleaseDeviceDataLock( KeSetEvent(&FdoExt->DeviceSyncEvent, IO_NO_INCREMENT, FALSE); } +FORCEINLINE +BOOLEAN +HasIoAlternatives( + _In_ PISAPNP_ALTERNATIVES Alternatives) +{ + return (Alternatives->Io[0].Length != 0); +} + +FORCEINLINE +BOOLEAN +HasIrqAlternatives( + _In_ PISAPNP_ALTERNATIVES Alternatives) +{ + return (Alternatives->Irq[0].Mask != 0); +} + +FORCEINLINE +BOOLEAN +HasDmaAlternatives( + _In_ PISAPNP_ALTERNATIVES Alternatives) +{ + return (Alternatives->Dma[0].Mask != 0); +} + +FORCEINLINE +BOOLEAN +HasMemoryAlternatives( + _In_ PISAPNP_ALTERNATIVES Alternatives) +{ + return (Alternatives->MemRange[0].Length != 0); +} + +FORCEINLINE +BOOLEAN +HasMemory32Alternatives( + _In_ PISAPNP_ALTERNATIVES Alternatives) +{ + return (Alternatives->MemRange32[0].Length != 0); +} + /* isapnp.c */ CODE_SEG("PAGE") @@ -218,10 +329,11 @@ IsaPnpRemoveLogicalDeviceDO( /* hardware.c */ CODE_SEG("PAGE") -NTSTATUS +ULONG IsaHwTryReadDataPort( _In_ PUCHAR ReadDataPort); +_Requires_lock_held_(FdoExt->DeviceSyncEvent) CODE_SEG("PAGE") NTSTATUS IsaHwFillDeviceList( diff --git a/drivers/bus/isapnp/isapnphw.h b/drivers/bus/isapnp/isapnphw.h index cc33c320683..b3d8021a62c 100644 --- a/drivers/bus/isapnp/isapnphw.h +++ b/drivers/bus/isapnp/isapnphw.h @@ -4,6 +4,7 @@ * PURPOSE: Hardware definitions * COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman(a)reactos.org> * Copyright 2020 Hervé Poussineau <hpoussin(a)reactos.org> + * Copyright 2021 Dmitry Borisov <di.sean(a)protonmail.com> */ #pragma once @@ -15,14 +16,6 @@ extern "C" { #define ISAPNP_ADDRESS 0x279 #define ISAPNP_WRITE_DATA 0xA79 -#define ISAPNP_READ_PORT_MIN 0x203 -#define ISAPNP_READ_PORT_START 0x213 -#define ISAPNP_READ_PORT_MAX 0x3FF -#define ISAPNP_READ_PORT_STEP 0x10 - -#define ISAPNP_CSN_MIN 0x01 -#define ISAPNP_CSN_MAX 0x0F - #define ISAPNP_READPORT 0x00 #define ISAPNP_SERIALISOLATION 0x01 #define ISAPNP_CONFIGCONTROL 0x02 @@ -58,11 +51,6 @@ extern "C" { #define ISAPNP_TAG_ENDDEP 0x07 #define ISAPNP_TAG_IOPORT 0x08 #define ISAPNP_TAG_FIXEDIO 0x09 -#define ISAPNP_TAG_RSVDSHORTA 0x0A -#define ISAPNP_TAG_RSVDSHORTB 0x0B -#define ISAPNP_TAG_RSVDSHORTC 0x0C -#define ISAPNP_TAG_RSVDSHORTD 0x0D -#define ISAPNP_TAG_VENDORSHORT 0x0E #define ISAPNP_TAG_END 0x0F #define ISAPNP_IS_LARGE_TAG(t) (((t) & 0x80)) @@ -70,26 +58,10 @@ extern "C" { #define ISAPNP_TAG_MEMRANGE 0x81 #define ISAPNP_TAG_ANSISTR 0x82 #define ISAPNP_TAG_UNICODESTR 0x83 -#define ISAPNP_TAG_VENDORLONG 0x84 #define ISAPNP_TAG_MEM32RANGE 0x85 #define ISAPNP_TAG_FIXEDMEM32RANGE 0x86 -#define ISAPNP_TAG_RSVDLONG0 0xF0 -#define ISAPNP_TAG_RSVDLONG1 0xF1 -#define ISAPNP_TAG_RSVDLONG2 0xF2 -#define ISAPNP_TAG_RSVDLONG3 0xF3 -#define ISAPNP_TAG_RSVDLONG4 0xF4 -#define ISAPNP_TAG_RSVDLONG5 0xF5 -#define ISAPNP_TAG_RSVDLONG6 0xF6 -#define ISAPNP_TAG_RSVDLONG7 0xF7 -#define ISAPNP_TAG_RSVDLONG8 0xF8 -#define ISAPNP_TAG_RSVDLONG9 0xF9 -#define ISAPNP_TAG_RSVDLONGA 0xFA -#define ISAPNP_TAG_RSVDLONGB 0xFB -#define ISAPNP_TAG_RSVDLONGC 0xFC -#define ISAPNP_TAG_RSVDLONGD 0xFD -#define ISAPNP_TAG_RSVDLONGE 0xFE -#define ISAPNP_TAG_RSVDLONGF 0xFF -#define ISAPNP_TAG_PSEUDO_NEWBOARD 0x100 + +#include <pshpack1.h> typedef struct _ISAPNP_IDENTIFIER { @@ -106,14 +78,11 @@ typedef struct _ISAPNP_LOGDEVID USHORT Flags; } ISAPNP_LOGDEVID, *PISAPNP_LOGDEVID; -typedef struct _ISAPNP_DEVICEID +typedef struct _ISAPNP_COMPATID { - CHAR* Name; USHORT VendorId; USHORT ProdId; -} ISAPNP_DEVICEID, *PISAPNP_DEVICEID; - -#include <pshpack1.h> +} ISAPNP_COMPATID, *PISAPNP_COMPATID; typedef struct _ISAPNP_IO_DESCRIPTION { @@ -124,6 +93,12 @@ typedef struct _ISAPNP_IO_DESCRIPTION UCHAR Length; } ISAPNP_IO_DESCRIPTION, *PISAPNP_IO_DESCRIPTION; +typedef struct _ISAPNP_FIXED_IO_DESCRIPTION +{ + USHORT IoBase; + UCHAR Length; +} ISAPNP_FIXED_IO_DESCRIPTION, *PISAPNP_FIXED_IO_DESCRIPTION; + typedef struct _ISAPNP_IRQ_DESCRIPTION { USHORT Mask; @@ -136,6 +111,31 @@ typedef struct _ISAPNP_DMA_DESCRIPTION UCHAR Information; } ISAPNP_DMA_DESCRIPTION, *PISAPNP_DMA_DESCRIPTION; +typedef struct _ISAPNP_MEMRANGE_DESCRIPTION +{ + UCHAR Information; + USHORT Minimum; + USHORT Maximum; + USHORT Alignment; + USHORT Length; +} ISAPNP_MEMRANGE_DESCRIPTION, *PISAPNP_MEMRANGE_DESCRIPTION; + +typedef struct _ISAPNP_MEMRANGE32_DESCRIPTION +{ + UCHAR Information; + ULONG Minimum; + ULONG Maximum; + ULONG Alignment; + ULONG Length; +} ISAPNP_MEMRANGE32_DESCRIPTION, *PISAPNP_MEMRANGE32_DESCRIPTION; + +typedef struct _ISAPNP_FIXEDMEMRANGE_DESCRIPTION +{ + UCHAR Information; + ULONG MemoryBase; + ULONG Length; +} ISAPNP_FIXEDMEMRANGE_DESCRIPTION, *PISAPNP_FIXEDMEMRANGE_DESCRIPTION; + #include <poppack.h> #ifdef __cplusplus diff --git a/drivers/bus/isapnp/pdo.c b/drivers/bus/isapnp/pdo.c index 6e3676a01cc..67a30891ac1 100644 --- a/drivers/bus/isapnp/pdo.c +++ b/drivers/bus/isapnp/pdo.c @@ -130,6 +130,11 @@ IsaPdoQueryId( { CharCount = sizeof("ISAPNP\\XXXFFFF"); + if (LogDev->Flags & ISAPNP_HAS_MULTIPLE_LOGDEVS) + { + CharCount += sizeof("_DEV1234") - sizeof(ANSI_NULL); + } + Buffer = ExAllocatePoolWithTag(PagedPool, CharCount * sizeof(WCHAR), TAG_ISAPNP); @@ -147,6 +152,19 @@ IsaPdoQueryId( if (!NT_VERIFY(NT_SUCCESS(Status))) goto Failure; + if (LogDev->Flags & ISAPNP_HAS_MULTIPLE_LOGDEVS) + { + Status = RtlStringCchPrintfExW(End, + Remaining, + NULL, + NULL, + 0, + L"_DEV%04X", + LogDev->LDN); + if (!NT_VERIFY(NT_SUCCESS(Status))) + goto Failure; + } + DPRINT("Device ID: '%S'\n", Buffer); break; } @@ -157,6 +175,11 @@ IsaPdoQueryId( sizeof("*PNPxxxx") + sizeof(ANSI_NULL); /* multi-string */ + if (LogDev->Flags & ISAPNP_HAS_MULTIPLE_LOGDEVS) + { + CharCount += sizeof("_DEV1234") - sizeof(ANSI_NULL); + } + Buffer = ExAllocatePoolWithTag(PagedPool, CharCount * sizeof(WCHAR), TAG_ISAPNP); @@ -177,6 +200,19 @@ IsaPdoQueryId( if (!NT_VERIFY(NT_SUCCESS(Status))) goto Failure; + if (LogDev->Flags & ISAPNP_HAS_MULTIPLE_LOGDEVS) + { + Status = RtlStringCchPrintfExW(End, + Remaining, + &End, + &Remaining, + 0, + L"_DEV%04X", + LogDev->LDN); + if (!NT_VERIFY(NT_SUCCESS(Status))) + goto Failure; + } + DPRINT(" '%S'\n", Buffer); ++End; @@ -190,8 +226,8 @@ IsaPdoQueryId( &Remaining, 0, L"*%.3S%04x", - LogDev->VendorId, - LogDev->ProdId); + LogDev->LogVendorId, + LogDev->LogProdId); if (!NT_VERIFY(NT_SUCCESS(Status))) goto Failure; @@ -204,7 +240,57 @@ IsaPdoQueryId( } case BusQueryCompatibleIDs: - return STATUS_NOT_IMPLEMENTED; + { + PLIST_ENTRY Entry; + + for (Entry = LogDev->CompatibleIdList.Flink, CharCount = 0; + Entry != &LogDev->CompatibleIdList; + Entry = Entry->Flink) + { + CharCount += sizeof("*PNPxxxx"); + } + CharCount += sizeof(ANSI_NULL); /* multi-string */ + + if (CharCount == sizeof(ANSI_NULL)) + return Irp->IoStatus.Status; + + Buffer = ExAllocatePoolWithTag(PagedPool, + CharCount * sizeof(WCHAR), + TAG_ISAPNP); + if (!Buffer) + return STATUS_INSUFFICIENT_RESOURCES; + + DPRINT("Compatible IDs:\n"); + + for (Entry = LogDev->CompatibleIdList.Flink, End = Buffer, Remaining = CharCount; + Entry != &LogDev->CompatibleIdList; + Entry = Entry->Flink) + { + PISAPNP_COMPATIBLE_ID_ENTRY CompatibleId = + CONTAINING_RECORD(Entry, ISAPNP_COMPATIBLE_ID_ENTRY, IdLink); + + IdStart = End; + Status = RtlStringCchPrintfExW(End, + Remaining, + &End, + &Remaining, + 0, + L"*%.3S%04x", + CompatibleId->VendorId, + CompatibleId->ProdId); + if (!NT_VERIFY(NT_SUCCESS(Status))) + goto Failure; + + DPRINT(" '%S'\n", IdStart); + + ++End; + --Remaining; + } + + *End = UNICODE_NULL; + + break; + } case BusQueryInstanceID: { @@ -319,6 +405,64 @@ IsaReadPortQueryId( return STATUS_SUCCESS; } +static +CODE_SEG("PAGE") +NTSTATUS +IsaPdoQueryDeviceText( + _In_ PISAPNP_PDO_EXTENSION PdoExt, + _Inout_ PIRP Irp, + _In_ PIO_STACK_LOCATION IrpSp) +{ + NTSTATUS Status; + PWCHAR Buffer; + size_t CharCount; + + PAGED_CODE(); + + switch (IrpSp->Parameters.QueryDeviceText.DeviceTextType) + { + case DeviceTextDescription: + { + if (!PdoExt->IsaPnpDevice->FriendlyName) + return Irp->IoStatus.Status; + + CharCount = strlen(PdoExt->IsaPnpDevice->FriendlyName) + + sizeof(ANSI_NULL); + + if (CharCount == sizeof(ANSI_NULL)) + return Irp->IoStatus.Status; + + Buffer = ExAllocatePoolWithTag(PagedPool, + CharCount * sizeof(WCHAR), + TAG_ISAPNP); + if (!Buffer) + return STATUS_INSUFFICIENT_RESOURCES; + + Status = RtlStringCchPrintfExW(Buffer, + CharCount, + NULL, + NULL, + 0, + L"%hs", + PdoExt->IsaPnpDevice->FriendlyName); + if (!NT_VERIFY(NT_SUCCESS(Status))) + { + ExFreePoolWithTag(Buffer, TAG_ISAPNP); + return Status; + } + + DPRINT("TextDescription: '%S'\n", Buffer); + break; + } + + default: + return Irp->IoStatus.Status; + } + + Irp->IoStatus.Information = (ULONG_PTR)Buffer; + return STATUS_SUCCESS; +} + static CODE_SEG("PAGE") NTSTATUS @@ -428,7 +572,7 @@ IsaPdoStartReadPort( SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart; /* We detected some ISAPNP cards */ - if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort))) + if (IsaHwTryReadDataPort(ReadDataPort) > 0) { SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart; break; @@ -473,7 +617,9 @@ IsaPdoStartReadPort( PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3); /* Run the isolation protocol */ - if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort))) + FdoExt->Cards = IsaHwTryReadDataPort(ReadDataPort); + + if (FdoExt->Cards > 0) { FdoExt->ReadDataPort = ReadDataPort; @@ -482,16 +628,13 @@ IsaPdoStartReadPort( /* Card identification */ Status = IsaHwFillDeviceList(FdoExt); - if (FdoExt->DeviceCount > 0) - { - PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN | - ISAPNP_SCANNED_BY_READ_PORT; + IsaPnpReleaseDeviceDataLock(FdoExt); - IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations); - IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations); - } + PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN | + ISAPNP_SCANNED_BY_READ_PORT; - IsaPnpReleaseDeviceDataLock(FdoExt); + IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations); + IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations); return Status; } @@ -653,6 +796,7 @@ IsaPnpRemoveLogicalDeviceDO( { PISAPNP_PDO_EXTENSION PdoExt = Pdo->DeviceExtension; PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; + PLIST_ENTRY Entry; PAGED_CODE(); ASSERT(LogDev); @@ -665,6 +809,25 @@ IsaPnpRemoveLogicalDeviceDO( if (PdoExt->ResourceList) ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP); + if (LogDev->FriendlyName) + ExFreePoolWithTag(LogDev->FriendlyName, TAG_ISAPNP); + + if (LogDev->Alternatives) + ExFreePoolWithTag(LogDev->Alternatives, TAG_ISAPNP); + + Entry = LogDev->CompatibleIdList.Flink; + while (Entry != &LogDev->CompatibleIdList) + { + PISAPNP_COMPATIBLE_ID_ENTRY CompatibleId = + CONTAINING_RECORD(Entry, ISAPNP_COMPATIBLE_ID_ENTRY, IdLink); + + RemoveEntryList(&CompatibleId->IdLink); + + Entry = Entry->Flink; + + ExFreePoolWithTag(CompatibleId, TAG_ISAPNP); + } + ExFreePoolWithTag(LogDev, TAG_ISAPNP); IoDeleteDevice(PdoExt->Common.Self); @@ -790,6 +953,11 @@ IsaPdoPnp( Status = IsaReadPortQueryId(Irp, IrpSp); break; + case IRP_MN_QUERY_DEVICE_TEXT: + if (PdoExt->Common.Signature == IsaPnpLogicalDevice) + Status = IsaPdoQueryDeviceText(PdoExt, Irp, IrpSp); + break; + case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: Status = IsaPdoFilterResourceRequirements(PdoExt, Irp, IrpSp); break;
3 years, 6 months
1
0
0
0
[reactos] 11/20: [ISAPNP] Use the correct types for helper functions
by Dmitry Borisov
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7c897dfbd170aa12fdd3c…
commit 7c897dfbd170aa12fdd3c179baffd868331ae592 Author: Dmitry Borisov <di.sean(a)protonmail.com> AuthorDate: Sat Mar 20 20:49:57 2021 +0600 Commit: Dmitry Borisov <di.sean(a)protonmail.com> CommitDate: Sun Jun 20 19:24:31 2021 +0600 [ISAPNP] Use the correct types for helper functions --- drivers/bus/isapnp/hardware.c | 55 ++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/drivers/bus/isapnp/hardware.c b/drivers/bus/isapnp/hardware.c index 5922049864f..6673e200194 100644 --- a/drivers/bus/isapnp/hardware.c +++ b/drivers/bus/isapnp/hardware.c @@ -15,7 +15,7 @@ static inline VOID WriteAddress( - _In_ USHORT Address) + _In_ UCHAR Address) { WRITE_PORT_UCHAR((PUCHAR)ISAPNP_ADDRESS, Address); } @@ -24,7 +24,7 @@ static inline VOID WriteData( - _In_ USHORT Data) + _In_ UCHAR Data) { WRITE_PORT_UCHAR((PUCHAR)ISAPNP_WRITE_DATA, Data); } @@ -42,8 +42,8 @@ static inline VOID WriteByte( - _In_ USHORT Address, - _In_ USHORT Value) + _In_ UCHAR Address, + _In_ UCHAR Value) { WriteAddress(Address); WriteData(Value); @@ -54,7 +54,7 @@ inline UCHAR ReadByte( _In_ PUCHAR ReadDataPort, - _In_ USHORT Address) + _In_ UCHAR Address) { WriteAddress(Address); return ReadData(ReadDataPort); @@ -65,7 +65,7 @@ inline USHORT ReadWord( _In_ PUCHAR ReadDataPort, - _In_ USHORT Address) + _In_ UCHAR Address) { return ((ReadByte(ReadDataPort, Address) << 8) | (ReadByte(ReadDataPort, Address + 1))); @@ -77,7 +77,7 @@ VOID SetReadDataPort( _In_ PUCHAR ReadDataPort) { - WriteByte(ISAPNP_READPORT, ((ULONG_PTR)ReadDataPort >> 2)); + WriteByte(ISAPNP_READPORT, (UCHAR)((ULONG_PTR)ReadDataPort >> 2)); } static @@ -108,14 +108,14 @@ static inline VOID Wake( - _In_ USHORT Csn) + _In_ UCHAR Csn) { WriteByte(ISAPNP_WAKE, Csn); } static inline -USHORT +UCHAR ReadResourceData( _In_ PUCHAR ReadDataPort) { @@ -124,7 +124,7 @@ ReadResourceData( static inline -USHORT +UCHAR ReadStatus( _In_ PUCHAR ReadDataPort) { @@ -135,7 +135,7 @@ static inline VOID WriteCsn( - _In_ USHORT Csn) + _In_ UCHAR Csn) { WriteByte(ISAPNP_CARDSELECTNUMBER, Csn); } @@ -144,7 +144,7 @@ static inline VOID WriteLogicalDeviceNumber( - _In_ USHORT LogDev) + _In_ UCHAR LogDev) { WriteByte(ISAPNP_LOGICALDEVICENUMBER, LogDev); } @@ -153,7 +153,7 @@ static inline VOID ActivateDevice( - _In_ USHORT LogDev) + _In_ UCHAR LogDev) { WriteLogicalDeviceNumber(LogDev); WriteByte(ISAPNP_ACTIVATE, 1); @@ -163,7 +163,7 @@ static inline VOID DeactivateDevice( - _In_ USHORT LogDev) + _In_ UCHAR LogDev) { WriteLogicalDeviceNumber(LogDev); WriteByte(ISAPNP_ACTIVATE, 0); @@ -174,37 +174,37 @@ inline USHORT ReadIoBase( _In_ PUCHAR ReadDataPort, - _In_ USHORT Index) + _In_ UCHAR Index) { return ReadWord(ReadDataPort, ISAPNP_IOBASE(Index)); } static inline -USHORT +UCHAR ReadIrqNo( _In_ PUCHAR ReadDataPort, - _In_ USHORT Index) + _In_ UCHAR Index) { return ReadByte(ReadDataPort, ISAPNP_IRQNO(Index)); } static inline -USHORT +UCHAR ReadIrqType( _In_ PUCHAR ReadDataPort, - _In_ USHORT Index) + _In_ UCHAR Index) { return ReadByte(ReadDataPort, ISAPNP_IRQTYPE(Index)); } static inline -USHORT +UCHAR ReadDmaChannel( _In_ PUCHAR ReadDataPort, - _In_ USHORT Index) + _In_ UCHAR Index) { return ReadByte(ReadDataPort, ISAPNP_DMACHANNEL(Index)); } @@ -251,11 +251,11 @@ SendKey(VOID) static CODE_SEG("PAGE") -USHORT +UCHAR PeekByte( _In_ PUCHAR ReadDataPort) { - USHORT i; + UCHAR i; PAGED_CODE(); @@ -276,15 +276,16 @@ VOID Peek( _In_ PUCHAR ReadDataPort, _Out_writes_bytes_all_opt_(Length) PVOID Buffer, - _In_ ULONG Length) + _In_ USHORT Length) { - USHORT i, Byte; + USHORT i; PAGED_CODE(); for (i = 0; i < Length; i++) { - Byte = PeekByte(ReadDataPort); + UCHAR Byte = PeekByte(ReadDataPort); + if (Buffer) ((PUCHAR)Buffer)[i] = Byte; } @@ -292,7 +293,7 @@ Peek( static CODE_SEG("PAGE") -USHORT +UCHAR IsaPnpChecksum( _In_ PISAPNP_IDENTIFIER Identifier) {
3 years, 6 months
1
0
0
0
[reactos] 10/20: [ISAPNP] Implement the Read Port resource management
by Dmitry Borisov
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c4b6330b14043add278ef…
commit c4b6330b14043add278ef4b74ca6a7566d667737 Author: Dmitry Borisov <di.sean(a)protonmail.com> AuthorDate: Sun Mar 28 23:29:02 2021 +0600 Commit: Dmitry Borisov <di.sean(a)protonmail.com> CommitDate: Sun Jun 20 19:24:31 2021 +0600 [ISAPNP] Implement the Read Port resource management Currently disabled until the kernel is ready --- drivers/bus/isapnp/isapnp.c | 151 ++++++++++++++++++++++++++++++++++++-------- drivers/bus/isapnp/isapnp.h | 7 ++ drivers/bus/isapnp/pdo.c | 144 ++++++++++++++++++++++++++++++++---------- 3 files changed, 243 insertions(+), 59 deletions(-) diff --git a/drivers/bus/isapnp/isapnp.c b/drivers/bus/isapnp/isapnp.c index 148dfb6b090..41f52c9aed6 100644 --- a/drivers/bus/isapnp/isapnp.c +++ b/drivers/bus/isapnp/isapnp.c @@ -370,22 +370,54 @@ IsaForwardOrIgnore( } } -static CODE_SEG("PAGE") NTSTATUS IsaPnpCreateReadPortDORequirements( - _In_ PISAPNP_PDO_EXTENSION PdoExt) + _In_ PISAPNP_PDO_EXTENSION PdoExt, + _In_opt_ ULONG SelectedReadPort) { - ULONG ListSize, i; + ULONG ResourceCount, ListSize, i; PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; PIO_RESOURCE_DESCRIPTOR Descriptor; - const ULONG Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS, - 0x274, 0x3E4, 0x204, 0x2E4, 0x354, 0x2F4 }; + const ULONG Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS }; + const ULONG ReadPorts[] = { 0x274, 0x3E4, 0x204, 0x2E4, 0x354, 0x2F4 }; PAGED_CODE(); - ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) - + 2 * RTL_NUMBER_OF(Ports) * sizeof(IO_RESOURCE_DESCRIPTOR); + if (SelectedReadPort) + { + /* + * [IO descriptor: ISAPNP_WRITE_DATA, required] + * [IO descriptor: ISAPNP_WRITE_DATA, optional] + * [IO descriptor: ISAPNP_ADDRESS, required] + * [IO descriptor: ISAPNP_ADDRESS, optional] + * [IO descriptor: Selected Read Port, required] + * [IO descriptor: Read Port 1, optional] + * [IO descriptor: Read Port 2, optional] + * [...] + * [IO descriptor: Read Port X - 1, optional] + */ + ResourceCount = RTL_NUMBER_OF(Ports) * 2 + RTL_NUMBER_OF(ReadPorts); + } + else + { + /* + * [IO descriptor: ISAPNP_WRITE_DATA, required] + * [IO descriptor: ISAPNP_WRITE_DATA, optional] + * [IO descriptor: ISAPNP_ADDRESS, required] + * [IO descriptor: ISAPNP_ADDRESS, optional] + * [IO descriptor: Read Port 1, required] + * [IO descriptor: Read Port 1, optional] + * [IO descriptor: Read Port 2, required] + * [IO descriptor: Read Port 2, optional] + * [...] + * [IO descriptor: Read Port X, required] + * [IO descriptor: Read Port X, optional] + */ + ResourceCount = (RTL_NUMBER_OF(Ports) + RTL_NUMBER_OF(ReadPorts)) * 2; + } + ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + + sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1); RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); if (!RequirementsList) return STATUS_NO_MEMORY; @@ -395,27 +427,92 @@ IsaPnpCreateReadPortDORequirements( RequirementsList->List[0].Version = 1; RequirementsList->List[0].Revision = 1; - RequirementsList->List[0].Count = 2 * RTL_NUMBER_OF(Ports); + RequirementsList->List[0].Count = ResourceCount; + + Descriptor = &RequirementsList->List[0].Descriptors[0]; + + /* Store the Data port and the Address port */ + for (i = 0; i < RTL_NUMBER_OF(Ports) * 2; i++) + { + if ((i % 2) == 0) + { + /* Expected port */ + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; + Descriptor->u.Port.Length = 0x01; + Descriptor->u.Port.Alignment = 0x01; + Descriptor->u.Port.MinimumAddress.LowPart = + Descriptor->u.Port.MaximumAddress.LowPart = Ports[i / 2]; + } + else + { + /* ... but mark it as optional */ + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; + Descriptor->u.Port.Alignment = 0x01; + } + + Descriptor++; + } - for (i = 0; i < 2 * RTL_NUMBER_OF(Ports); i += 2) + /* Store the Read Ports */ + if (SelectedReadPort) { - Descriptor = &RequirementsList->List[0].Descriptors[i]; - - /* Expected port */ - Descriptor[0].Type = CmResourceTypePort; - Descriptor[0].ShareDisposition = CmResourceShareDeviceExclusive; - Descriptor[0].Flags = CM_RESOURCE_PORT_16_BIT_DECODE; - Descriptor[0].u.Port.Length = Ports[i / 2] & 1 ? 0x01 : 0x04; - Descriptor[0].u.Port.Alignment = 0x01; - Descriptor[0].u.Port.MinimumAddress.LowPart = Ports[i / 2]; - Descriptor[0].u.Port.MaximumAddress.LowPart = Ports[i / 2] + Descriptor[0].u.Port.Length - 1; - - /* ... but mark it as optional */ - Descriptor[1].Option = IO_RESOURCE_ALTERNATIVE; - Descriptor[1].Type = CmResourceTypePort; - Descriptor[1].ShareDisposition = CmResourceShareDeviceExclusive; - Descriptor[1].Flags = CM_RESOURCE_PORT_16_BIT_DECODE; - Descriptor[1].u.Port.Alignment = 0x01; + BOOLEAN Selected = FALSE; + + DBG_UNREFERENCED_LOCAL_VARIABLE(Selected); + + for (i = 0; i < RTL_NUMBER_OF(ReadPorts); i++) + { + if (ReadPorts[i] != SelectedReadPort) + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + else + Selected = TRUE; + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; + Descriptor->u.Port.Length = 0x04; + Descriptor->u.Port.Alignment = 0x01; + Descriptor->u.Port.MinimumAddress.LowPart = ReadPorts[i]; + Descriptor->u.Port.MaximumAddress.LowPart = ReadPorts[i] + + Descriptor->u.Port.Length - 1; + + Descriptor++; + } + + ASSERT(Selected == TRUE); + } + else + { + for (i = 0; i < RTL_NUMBER_OF(ReadPorts) * 2; i++) + { + if ((i % 2) == 0) + { + /* Expected port */ + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; + Descriptor->u.Port.Length = 0x04; + Descriptor->u.Port.Alignment = 0x01; + Descriptor->u.Port.MinimumAddress.LowPart = ReadPorts[i / 2]; + Descriptor->u.Port.MaximumAddress.LowPart = ReadPorts[i / 2] + + Descriptor->u.Port.Length - 1; + } + else + { + /* ... but mark it as optional */ + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; + Descriptor->u.Port.Alignment = 0x01; + } + + Descriptor++; + } } PdoExt->RequirementsList = RequirementsList; @@ -493,7 +590,7 @@ IsaPnpCreateReadPortDO( PdoExt->Common.State = dsStopped; PdoExt->FdoExt = FdoExt; - Status = IsaPnpCreateReadPortDORequirements(PdoExt); + Status = IsaPnpCreateReadPortDORequirements(PdoExt, 0); if (!NT_SUCCESS(Status)) goto Failure; diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index e476f9737b0..ed4a6027a9b 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -115,6 +115,7 @@ typedef struct _ISAPNP_PDO_EXTENSION #define ISAPNP_ENUMERATED 0x00000001 /**< @brief Whether the device has been reported to the PnP manager. */ #define ISAPNP_SCANNED_BY_READ_PORT 0x00000002 /**< @brief The bus has been scanned by Read Port PDO. */ #define ISAPNP_READ_PORT_ALLOW_FDO_SCAN 0x00000004 /**< @brief Allows the active FDO to scan the bus. */ +#define ISAPNP_READ_PORT_NEED_REBALANCE 0x00000008 /**< @brief The I/O resource requirements have changed. */ _Write_guarded_by_(_Global_interlock_) volatile LONG SpecialFiles; @@ -166,6 +167,12 @@ IsaPnpReleaseDeviceDataLock( /* isapnp.c */ +CODE_SEG("PAGE") +NTSTATUS +IsaPnpCreateReadPortDORequirements( + _In_ PISAPNP_PDO_EXTENSION PdoExt, + _In_opt_ ULONG SelectedReadPort); + CODE_SEG("PAGE") VOID IsaPnpRemoveReadPortDO( diff --git a/drivers/bus/isapnp/pdo.c b/drivers/bus/isapnp/pdo.c index 27aedff6c6f..6e3676a01cc 100644 --- a/drivers/bus/isapnp/pdo.c +++ b/drivers/bus/isapnp/pdo.c @@ -93,7 +93,14 @@ IsaPdoQueryPnpDeviceState( { PAGED_CODE(); - if (PdoExt->SpecialFiles > 0) + if (PdoExt->Flags & ISAPNP_READ_PORT_NEED_REBALANCE) + { + Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE | + PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED | + PNP_DEVICE_FAILED; + return STATUS_SUCCESS; + } + else if (PdoExt->SpecialFiles > 0) { Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; return STATUS_SUCCESS; @@ -368,24 +375,24 @@ IsaPdoQueryResourceRequirements( return STATUS_SUCCESS; } +#define IS_READ_PORT(_d) ((_d)->Type == CmResourceTypePort && (_d)->u.Port.Length > 1) + static CODE_SEG("PAGE") NTSTATUS IsaPdoStartReadPort( - _In_ PISAPNP_FDO_EXTENSION FdoExt, - _In_ PIO_STACK_LOCATION IrpSp) + _In_ PISAPNP_PDO_EXTENSION PdoExt, + _In_ PCM_RESOURCE_LIST ResourceList) { - PISAPNP_PDO_EXTENSION PdoExt = FdoExt->ReadPortPdo->DeviceExtension; - PCM_RESOURCE_LIST ResourceList = IrpSp->Parameters.StartDevice.AllocatedResources; - NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; + PISAPNP_FDO_EXTENSION FdoExt = PdoExt->FdoExt; + NTSTATUS Status; ULONG i; PAGED_CODE(); - if (!ResourceList || ResourceList->Count != 1) + if (!ResourceList) { - DPRINT1("No resource list (%p) or bad count (%d)\n", - ResourceList, ResourceList ? ResourceList->Count : 0); + DPRINT1("No resource list\n"); return STATUS_INSUFFICIENT_RESOURCES; } @@ -398,43 +405,110 @@ IsaPdoStartReadPort( return STATUS_REVISION_MISMATCH; } - for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++) +#if 0 + /* Try various Read Ports from the list */ + if (ResourceList->List[0].PartialResourceList.Count > 3) { - PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor = - &ResourceList->List[0].PartialResourceList.PartialDescriptors[i]; + ULONG SelectedPort = 0; - if (PartialDescriptor->Type == CmResourceTypePort && - PartialDescriptor->u.Port.Length > 1 && !FdoExt->ReadDataPort) + for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++) { - PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3); - if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort))) + PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor = + &ResourceList->List[0].PartialResourceList.PartialDescriptors[i]; + + if (IS_READ_PORT(PartialDescriptor)) { + PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3); + + /* + * Remember the first Read Port in the resource list. + * It will be selected by default even if no card has been detected. + */ + if (!SelectedPort) + SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart; + /* We detected some ISAPNP cards */ + if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort))) + { + SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart; + break; + } + } + } + + ASSERT(SelectedPort != 0); + + if (PdoExt->RequirementsList) + { + ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP); + PdoExt->RequirementsList = NULL; + } + + /* Discard the Read Ports at conflicting locations */ + Status = IsaPnpCreateReadPortDORequirements(PdoExt, SelectedPort); + if (!NT_SUCCESS(Status)) + return Status; + + PdoExt->Flags |= ISAPNP_READ_PORT_NEED_REBALANCE; + + IoInvalidateDeviceState(PdoExt->Common.Self); + + return STATUS_SUCCESS; + } + /* Set the Read Port */ + else if (ResourceList->List[0].PartialResourceList.Count == 3) +#else + if (ResourceList->List[0].PartialResourceList.Count > 3) /* Temporary HACK */ +#endif + { + PdoExt->Flags &= ~ISAPNP_READ_PORT_NEED_REBALANCE; - FdoExt->ReadDataPort = ReadDataPort; + for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++) + { + PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor = + &ResourceList->List[0].PartialResourceList.PartialDescriptors[i]; - IsaPnpAcquireDeviceDataLock(FdoExt); - Status = IsaHwFillDeviceList(FdoExt); - IsaPnpReleaseDeviceDataLock(FdoExt); + if (IS_READ_PORT(PartialDescriptor)) + { + PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3); - if (FdoExt->DeviceCount > 0) + /* Run the isolation protocol */ + if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort))) { - PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN | - ISAPNP_SCANNED_BY_READ_PORT; + FdoExt->ReadDataPort = ReadDataPort; + + IsaPnpAcquireDeviceDataLock(FdoExt); - IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations); - IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations); + /* Card identification */ + Status = IsaHwFillDeviceList(FdoExt); + + if (FdoExt->DeviceCount > 0) + { + PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN | + ISAPNP_SCANNED_BY_READ_PORT; + + IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations); + IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations); + } + + IsaPnpReleaseDeviceDataLock(FdoExt); + + return Status; + } + else + { + break; } - } - else - { - /* Mark read data port as started, even if no card has been detected */ - Status = STATUS_SUCCESS; } } } + else + { + return STATUS_DEVICE_CONFIGURATION_ERROR; + } - return Status; + /* Mark Read Port as started, even if no card has been detected */ + return STATUS_SUCCESS; } static @@ -632,7 +706,10 @@ IsaPdoPnp( if (PdoExt->Common.Signature == IsaPnpLogicalDevice) Status = IsaHwActivateDevice(PdoExt->IsaPnpDevice); else - Status = IsaPdoStartReadPort(PdoExt->FdoExt, IrpSp); + { + Status = IsaPdoStartReadPort(PdoExt, + IrpSp->Parameters.StartDevice.AllocatedResources); + } if (NT_SUCCESS(Status)) PdoExt->Common.State = dsStarted; @@ -655,8 +732,11 @@ IsaPdoPnp( { if (PdoExt->SpecialFiles > 0) Status = STATUS_DEVICE_BUSY; + else if (PdoExt->Flags & ISAPNP_READ_PORT_NEED_REBALANCE) + Status = STATUS_RESOURCE_REQUIREMENTS_CHANGED; else Status = STATUS_SUCCESS; + break; }
3 years, 6 months
1
0
0
0
[reactos] 09/20: [ISAPNP] Fixes and improvements for IRP handling
by Dmitry Borisov
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f15de1555420f87aa20c2…
commit f15de1555420f87aa20c2cfaeb07a1e46846e350 Author: Dmitry Borisov <di.sean(a)protonmail.com> AuthorDate: Thu Mar 4 18:48:43 2021 +0600 Commit: Dmitry Borisov <di.sean(a)protonmail.com> CommitDate: Sun Jun 20 19:24:26 2021 +0600 [ISAPNP] Fixes and improvements for IRP handling - Implement device removal. - Finish the Read Port special handling introduced in 21514e473f5. - Gracefully handle low memory situations. - Implement IRQ translator. - Correctly stub power IRP handling. - Remove unneeded dispatch routines; implement WMI IRP handling. - Do not handle requests like WRITE_CONFIG. - Add a signature member to device extensions to make checks clearer. --- drivers/bus/isapnp/CMakeLists.txt | 1 + drivers/bus/isapnp/fdo.c | 166 +++++++++++++++++---- drivers/bus/isapnp/interface.c | 73 ++++++++++ drivers/bus/isapnp/isapnp.c | 295 ++++++++++++++++++++++++-------------- drivers/bus/isapnp/isapnp.h | 80 +++++++++-- drivers/bus/isapnp/pdo.c | 292 +++++++++++++++++++++++++++---------- 6 files changed, 682 insertions(+), 225 deletions(-) diff --git a/drivers/bus/isapnp/CMakeLists.txt b/drivers/bus/isapnp/CMakeLists.txt index 0d91dbf2691..6b8a6747546 100644 --- a/drivers/bus/isapnp/CMakeLists.txt +++ b/drivers/bus/isapnp/CMakeLists.txt @@ -4,6 +4,7 @@ list(APPEND SOURCE pdo.c fdo.c hardware.c + interface.c isapnp.h) add_library(isapnp MODULE ${SOURCE} isapnp.rc) diff --git a/drivers/bus/isapnp/fdo.c b/drivers/bus/isapnp/fdo.c index 7b32e790246..5d61c8b2dc4 100644 --- a/drivers/bus/isapnp/fdo.c +++ b/drivers/bus/isapnp/fdo.c @@ -4,6 +4,7 @@ * PURPOSE: FDO-specific code * COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman(a)reactos.org> * Copyright 2020 Hervé Poussineau <hpoussin(a)reactos.org> + * Copyright 2021 Dmitry Borisov <di.sean(a)protonmail.com> */ #include "isapnp.h" @@ -16,14 +17,22 @@ CODE_SEG("PAGE") NTSTATUS IsaFdoStartDevice( _In_ PISAPNP_FDO_EXTENSION FdoExt, - _Inout_ PIRP Irp, - _In_ PIO_STACK_LOCATION IrpSp) + _Inout_ PIRP Irp) { - UNREFERENCED_PARAMETER(Irp); - UNREFERENCED_PARAMETER(IrpSp); + NTSTATUS Status; PAGED_CODE(); + if (!IoForwardIrpSynchronously(FdoExt->Ldo, Irp)) + { + return STATUS_UNSUCCESSFUL; + } + Status = Irp->IoStatus.Status; + if (!NT_SUCCESS(Status)) + { + return Status; + } + FdoExt->Common.State = dsStarted; return STATUS_SUCCESS; @@ -32,19 +41,83 @@ IsaFdoStartDevice( static CODE_SEG("PAGE") NTSTATUS -IsaFdoQueryDeviceRelations( +IsaFdoQueryBusRelations( _In_ PISAPNP_FDO_EXTENSION FdoExt, - _Inout_ PIRP Irp, - _In_ PIO_STACK_LOCATION IrpSp) + _Inout_ PIRP Irp) { PAGED_CODE(); - if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations) - return Irp->IoStatus.Status; - return IsaPnpFillDeviceRelations(FdoExt, Irp, TRUE); } +static +CODE_SEG("PAGE") +NTSTATUS +IsaFdoRemoveDevice( + _In_ PISAPNP_FDO_EXTENSION FdoExt, + _Inout_ PIRP Irp) +{ + NTSTATUS Status; + PLIST_ENTRY Entry; + + PAGED_CODE(); + + IsaPnpAcquireDeviceDataLock(FdoExt); + + /* Remove our logical devices */ + while (!IsListEmpty(&FdoExt->DeviceListHead)) + { + PISAPNP_LOGICAL_DEVICE LogDevice = CONTAINING_RECORD(RemoveHeadList(&FdoExt-> + DeviceListHead), + ISAPNP_LOGICAL_DEVICE, + DeviceLink); + + --FdoExt->DeviceCount; + + if (LogDevice->Pdo) + { + IsaPnpRemoveLogicalDeviceDO(LogDevice->Pdo); + } + } + + IsaPnpReleaseDeviceDataLock(FdoExt); + + IsaPnpAcquireBusDataLock(); + + /* Remove the Read Port */ + if (FdoExt->ReadPortPdo) + { + IsaPnpRemoveReadPortDO(FdoExt->ReadPortPdo); + ReadPortCreated = FALSE; + } + + /* Find the next ISA bus, if any */ + Entry = BusListHead.Flink; + if (Entry != &BusListHead) + { + PISAPNP_FDO_EXTENSION NextIsaBus = CONTAINING_RECORD(Entry, + ISAPNP_FDO_EXTENSION, + BusLink); + + /* Create a new Read Port for it */ + if (!ReadPortCreated) + IoInvalidateDeviceRelations(NextIsaBus->Pdo, BusRelations); + } + + RemoveEntryList(&FdoExt->BusLink); + + IsaPnpReleaseBusDataLock(); + + Irp->IoStatus.Status = STATUS_SUCCESS; + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(FdoExt->Ldo, Irp); + + IoDetachDevice(FdoExt->Ldo); + IoDeleteDevice(FdoExt->Common.Self); + + return Status; +} + CODE_SEG("PAGE") NTSTATUS IsaFdoPnp( @@ -52,43 +125,82 @@ IsaFdoPnp( _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IrpSp) { - NTSTATUS Status = Irp->IoStatus.Status; + NTSTATUS Status; PAGED_CODE(); + DPRINT("%s(%p, %p) FDO %lu, Minor - %X\n", + __FUNCTION__, + FdoExt, + Irp, + FdoExt->BusNumber, + IrpSp->MinorFunction); + switch (IrpSp->MinorFunction) { case IRP_MN_START_DEVICE: - Status = IsaForwardIrpSynchronous(FdoExt, Irp); - - if (NT_SUCCESS(Status)) - Status = IsaFdoStartDevice(FdoExt, Irp, IrpSp); + Status = IsaFdoStartDevice(FdoExt, Irp); Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; - case IRP_MN_STOP_DEVICE: - FdoExt->Common.State = dsStopped; + case IRP_MN_QUERY_DEVICE_RELATIONS: + { + if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations) + break; - Status = STATUS_SUCCESS; - break; + Status = IsaFdoQueryBusRelations(FdoExt, Irp); + if (!NT_SUCCESS(Status)) + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); - case IRP_MN_QUERY_DEVICE_RELATIONS: - Status = IsaFdoQueryDeviceRelations(FdoExt, Irp, IrpSp); + return Status; + } Irp->IoStatus.Status = Status; + break; + } - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; + case IRP_MN_REMOVE_DEVICE: + return IsaFdoRemoveDevice(FdoExt, Irp); - case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: - DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); + case IRP_MN_QUERY_PNP_DEVICE_STATE: + Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; + Irp->IoStatus.Status = STATUS_SUCCESS; + break; + + case IRP_MN_QUERY_INTERFACE: + { + Status = IsaFdoQueryInterface(FdoExt, IrpSp); + if (Status == STATUS_NOT_SUPPORTED) + { + break; + } + else if (!NT_SUCCESS(Status)) + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; + } + + Irp->IoStatus.Status = Status; + break; + } + + case IRP_MN_SURPRISE_REMOVAL: + case IRP_MN_QUERY_STOP_DEVICE: + case IRP_MN_QUERY_REMOVE_DEVICE: + case IRP_MN_CANCEL_STOP_DEVICE: + case IRP_MN_CANCEL_REMOVE_DEVICE: + case IRP_MN_STOP_DEVICE: + Irp->IoStatus.Status = STATUS_SUCCESS; break; default: - DPRINT1("Unknown PnP code: %x\n", IrpSp->MinorFunction); + DPRINT("Unknown PnP code: %X\n", IrpSp->MinorFunction); break; } diff --git a/drivers/bus/isapnp/interface.c b/drivers/bus/isapnp/interface.c new file mode 100644 index 00000000000..057589bb35a --- /dev/null +++ b/drivers/bus/isapnp/interface.c @@ -0,0 +1,73 @@ +/* + * PROJECT: ReactOS ISA PnP Bus driver + * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later
) + * PURPOSE: Driver interface + * COPYRIGHT: Copyright 2021 Dmitry Borisov <di.sean(a)protonmail.com> + */ + +/* INCLUDES *******************************************************************/ + +#include "isapnp.h" + +#define NDEBUG +#include <debug.h> + +/* FUNCTIONS ******************************************************************/ + +CODE_SEG("PAGE") +NTSTATUS +IsaFdoQueryInterface( + _In_ PISAPNP_FDO_EXTENSION FdoExt, + _In_ PIO_STACK_LOCATION IrpSp) +{ + PAGED_CODE(); + + if (IsEqualGUIDAligned(IrpSp->Parameters.QueryInterface.InterfaceType, + &GUID_TRANSLATOR_INTERFACE_STANDARD)) + { + NTSTATUS Status; + CM_RESOURCE_TYPE ResourceType; + ULONG ParentBusType, ParentBusNumber, Dummy; + + ResourceType = PtrToUlong(IrpSp->Parameters.QueryInterface.InterfaceSpecificData); + + if (IrpSp->Parameters.QueryInterface.Size < sizeof(TRANSLATOR_INTERFACE) || + ResourceType != CmResourceTypeInterrupt) + { + return STATUS_NOT_SUPPORTED; + } + + Status = IoGetDeviceProperty(FdoExt->Pdo, + DevicePropertyLegacyBusType, + sizeof(ParentBusType), + &ParentBusType, + &Dummy); + if (!NT_SUCCESS(Status)) + { + DPRINT1("BusType request failed with status 0x%08lx\n", Status); + return Status; + } + + Status = IoGetDeviceProperty(FdoExt->Pdo, + DevicePropertyBusNumber, + sizeof(ParentBusNumber), + &ParentBusNumber, + &Dummy); + if (!NT_SUCCESS(Status)) + { + DPRINT1("BusNumber request failed with status 0x%08lx\n", Status); + return Status; + } + + return HalGetInterruptTranslator(ParentBusType, + ParentBusNumber, + Isa, + IrpSp->Parameters.QueryInterface.Size, + IrpSp->Parameters.QueryInterface.Version, + (PTRANSLATOR_INTERFACE)IrpSp-> + Parameters.QueryInterface.Interface, + &ParentBusNumber); + } + + return STATUS_NOT_SUPPORTED; +} diff --git a/drivers/bus/isapnp/isapnp.c b/drivers/bus/isapnp/isapnp.c index c477fecf767..148dfb6b090 100644 --- a/drivers/bus/isapnp/isapnp.c +++ b/drivers/bus/isapnp/isapnp.c @@ -4,15 +4,28 @@ * PURPOSE: Driver entry * COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman(a)reactos.org> * Copyright 2020 Hervé Poussineau <hpoussin(a)reactos.org> + * Copyright 2021 Dmitry Borisov <di.sean(a)protonmail.com> */ +/* INCLUDES *******************************************************************/ + #include "isapnp.h" #define NDEBUG #include <debug.h> +/* GLOBALS ********************************************************************/ + +KEVENT BusSyncEvent; + +_Guarded_by_(BusSyncEvent) BOOLEAN ReadPortCreated = FALSE; +_Guarded_by_(BusSyncEvent) +LIST_ENTRY BusListHead; + +/* FUNCTIONS ******************************************************************/ + static CODE_SEG("PAGE") NTSTATUS @@ -301,49 +314,6 @@ IsaPnpCreateLogicalDeviceResources( return STATUS_SUCCESS; } -static IO_COMPLETION_ROUTINE ForwardIrpCompletion; - -static -NTSTATUS -NTAPI -ForwardIrpCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context) -{ - UNREFERENCED_PARAMETER(DeviceObject); - - if (Irp->PendingReturned) - KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -NTAPI -IsaForwardIrpSynchronous( - IN PISAPNP_FDO_EXTENSION FdoExt, - IN PIRP Irp) -{ - KEVENT Event; - NTSTATUS Status; - - KeInitializeEvent(&Event, NotificationEvent, FALSE); - IoCopyCurrentIrpStackLocationToNext(Irp); - - IoSetCompletionRoutine(Irp, ForwardIrpCompletion, &Event, TRUE, TRUE, TRUE); - - Status = IoCallDriver(FdoExt->Ldo, Irp); - if (Status == STATUS_PENDING) - { - Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); - if (NT_SUCCESS(Status)) - Status = Irp->IoStatus.Status; - } - - return Status; -} - _Dispatch_type_(IRP_MJ_CREATE) _Dispatch_type_(IRP_MJ_CLOSE) static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaCreateClose; @@ -359,7 +329,6 @@ IsaCreateClose( PAGED_CODE(); Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = FILE_OPENED; DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); @@ -368,51 +337,37 @@ IsaCreateClose( return STATUS_SUCCESS; } -static DRIVER_DISPATCH IsaIoctl; +_Dispatch_type_(IRP_MJ_DEVICE_CONTROL) +_Dispatch_type_(IRP_MJ_SYSTEM_CONTROL) +static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaForwardOrIgnore; static +CODE_SEG("PAGE") NTSTATUS NTAPI -IsaIoctl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) +IsaForwardOrIgnore( + _In_ PDEVICE_OBJECT DeviceObject, + _Inout_ PIRP Irp) { - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); - NTSTATUS Status; + PISAPNP_COMMON_EXTENSION CommonExt = DeviceObject->DeviceExtension; - DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); + PAGED_CODE(); + + DPRINT("%s(%p, %p) Minor - %X\n", __FUNCTION__, DeviceObject, Irp, + IoGetCurrentIrpStackLocation(Irp)->MinorFunction); - switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) + if (CommonExt->Signature == IsaPnpBus) { - default: - DPRINT1("Unknown ioctl code: %x\n", IrpSp->Parameters.DeviceIoControl.IoControlCode); - Status = STATUS_NOT_SUPPORTED; - break; + IoSkipCurrentIrpStackLocation(Irp); + return IoCallDriver(((PISAPNP_FDO_EXTENSION)CommonExt)->Ldo, Irp); } + else + { + NTSTATUS Status = Irp->IoStatus.Status; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return Status; -} - -static DRIVER_DISPATCH IsaReadWrite; - -static -NTSTATUS -NTAPI -IsaReadWrite( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); - - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return STATUS_NOT_SUPPORTED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } } static @@ -533,7 +488,7 @@ IsaPnpCreateReadPortDO( PdoExt = FdoExt->ReadPortPdo->DeviceExtension; RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION)); - PdoExt->Common.IsFdo = FALSE; + PdoExt->Common.Signature = IsaPnpReadDataPort; PdoExt->Common.Self = FdoExt->ReadPortPdo; PdoExt->Common.State = dsStopped; PdoExt->FdoExt = FdoExt; @@ -551,17 +506,33 @@ IsaPnpCreateReadPortDO( return Status; Failure: - if (PdoExt->RequirementsList) - ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP); + IsaPnpRemoveReadPortDO(FdoExt->ReadPortPdo); - if (PdoExt->ResourceList) - ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP); - - IoDeleteDevice(FdoExt->ReadPortPdo); + FdoExt->ReadPortPdo = NULL; return Status; } +CODE_SEG("PAGE") +VOID +IsaPnpRemoveReadPortDO( + _In_ PDEVICE_OBJECT Pdo) +{ + PISAPNP_PDO_EXTENSION ReadPortExt = Pdo->DeviceExtension; + + PAGED_CODE(); + + DPRINT("Removing Read Port\n"); + + if (ReadPortExt->RequirementsList) + ExFreePoolWithTag(ReadPortExt->RequirementsList, TAG_ISAPNP); + + if (ReadPortExt->ResourceList) + ExFreePoolWithTag(ReadPortExt->ResourceList, TAG_ISAPNP); + + IoDeleteDevice(Pdo); +} + CODE_SEG("PAGE") NTSTATUS IsaPnpFillDeviceRelations( @@ -577,6 +548,8 @@ IsaPnpFillDeviceRelations( PAGED_CODE(); + IsaPnpAcquireBusDataLock(); + /* Try to claim the Read Port for our FDO */ if (!ReadPortCreated) { @@ -587,26 +560,68 @@ IsaPnpFillDeviceRelations( ReadPortCreated = TRUE; } + IsaPnpReleaseBusDataLock(); + /* Inactive ISA bus */ if (!FdoExt->ReadPortPdo) IncludeDataPort = FALSE; + IsaPnpAcquireDeviceDataLock(FdoExt); + + /* If called from the FDO dispatch routine && Active bus */ + if (IncludeDataPort && FdoExt->ReadPortPdo) + { + PISAPNP_PDO_EXTENSION ReadPortExt = FdoExt->ReadPortPdo->DeviceExtension; + + if ((ReadPortExt->Flags & ISAPNP_READ_PORT_ALLOW_FDO_SCAN) && + !(ReadPortExt->Flags & ISAPNP_SCANNED_BY_READ_PORT)) + { + DPRINT("Rescan ISA PnP bus\n"); + + /* Run the isolation protocol */ + if (NT_SUCCESS(IsaHwTryReadDataPort(FdoExt->ReadDataPort))) + { + /* Card identification */ + (VOID)IsaHwFillDeviceList(FdoExt); + } + } + + ReadPortExt->Flags &= ~ISAPNP_SCANNED_BY_READ_PORT; + } + PdoCount = FdoExt->DeviceCount; if (IncludeDataPort) ++PdoCount; + CurrentEntry = FdoExt->DeviceListHead.Flink; + while (CurrentEntry != &FdoExt->DeviceListHead) + { + IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink); + + if (!(IsaDevice->Flags & ISAPNP_PRESENT)) + --PdoCount; + + CurrentEntry = CurrentEntry->Flink; + } + DeviceRelations = ExAllocatePoolWithTag(PagedPool, FIELD_OFFSET(DEVICE_RELATIONS, Objects[PdoCount]), TAG_ISAPNP); if (!DeviceRelations) { + IsaPnpReleaseDeviceDataLock(FdoExt); return STATUS_NO_MEMORY; } if (IncludeDataPort) { + PISAPNP_PDO_EXTENSION ReadPortExt = FdoExt->ReadPortPdo->DeviceExtension; + DeviceRelations->Objects[i++] = FdoExt->ReadPortPdo; ObReferenceObject(FdoExt->ReadPortPdo); + + /* The Read Port PDO can only be removed by FDO */ + ReadPortExt->Flags |= ISAPNP_ENUMERATED; } CurrentEntry = FdoExt->DeviceListHead.Flink; @@ -616,6 +631,9 @@ IsaPnpFillDeviceRelations( IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink); + if (!(IsaDevice->Flags & ISAPNP_PRESENT)) + goto SkipPdo; + if (!IsaDevice->Pdo) { Status = IoCreateDevice(FdoExt->DriverObject, @@ -626,43 +644,66 @@ IsaPnpFillDeviceRelations( FALSE, &IsaDevice->Pdo); if (!NT_SUCCESS(Status)) - { - break; - } + goto SkipPdo; IsaDevice->Pdo->Flags &= ~DO_DEVICE_INITIALIZING; - - //Device->Pdo->Flags |= DO_POWER_PAGABLE; + /* The power pagable flag is always unset */ PdoExt = IsaDevice->Pdo->DeviceExtension; RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION)); - - PdoExt->Common.IsFdo = FALSE; + PdoExt->Common.Signature = IsaPnpLogicalDevice; PdoExt->Common.Self = IsaDevice->Pdo; PdoExt->Common.State = dsStopped; PdoExt->IsaPnpDevice = IsaDevice; PdoExt->FdoExt = FdoExt; - Status = IsaPnpCreateLogicalDeviceRequirements(PdoExt); - - if (NT_SUCCESS(Status)) - Status = IsaPnpCreateLogicalDeviceResources(PdoExt); - - if (!NT_SUCCESS(Status)) + if (!NT_SUCCESS(IsaPnpCreateLogicalDeviceRequirements(PdoExt)) || + !NT_SUCCESS(IsaPnpCreateLogicalDeviceResources(PdoExt))) { + if (PdoExt->RequirementsList) + { + ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP); + PdoExt->RequirementsList = NULL; + } + + if (PdoExt->ResourceList) + { + ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP); + PdoExt->ResourceList = NULL; + } + IoDeleteDevice(IsaDevice->Pdo); IsaDevice->Pdo = NULL; - break; + goto SkipPdo; } } + else + { + PdoExt = IsaDevice->Pdo->DeviceExtension; + } DeviceRelations->Objects[i++] = IsaDevice->Pdo; - ObReferenceObject(IsaDevice->Pdo); + PdoExt->Flags |= ISAPNP_ENUMERATED; + + CurrentEntry = CurrentEntry->Flink; + continue; + +SkipPdo: + if (IsaDevice->Pdo) + { + PdoExt = IsaDevice->Pdo->DeviceExtension; + + if (PdoExt) + PdoExt->Flags &= ~ISAPNP_ENUMERATED; + } + CurrentEntry = CurrentEntry->Flink; } + IsaPnpReleaseDeviceDataLock(FdoExt); + DeviceRelations->Count = i; Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; @@ -694,7 +735,7 @@ IsaAddDevice( NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, - TRUE, + FALSE, &Fdo); if (!NT_SUCCESS(Status)) { @@ -706,17 +747,26 @@ IsaAddDevice( RtlZeroMemory(FdoExt, sizeof(*FdoExt)); FdoExt->Common.Self = Fdo; - FdoExt->Common.IsFdo = TRUE; + FdoExt->Common.Signature = IsaPnpBus; FdoExt->Common.State = dsStopped; FdoExt->DriverObject = DriverObject; FdoExt->BusNumber = BusNumber++; FdoExt->Pdo = PhysicalDeviceObject; FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject); + if (!FdoExt->Ldo) + { + IoDeleteDevice(Fdo); + return STATUS_DEVICE_REMOVED; + } InitializeListHead(&FdoExt->DeviceListHead); KeInitializeEvent(&FdoExt->DeviceSyncEvent, SynchronizationEvent, TRUE); + IsaPnpAcquireBusDataLock(); + InsertTailList(&BusListHead, &FdoExt->BusLink); + IsaPnpReleaseBusDataLock(); + Fdo->Flags &= ~DO_DEVICE_INITIALIZING; return STATUS_SUCCESS; @@ -735,9 +785,22 @@ IsaPower( PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension; NTSTATUS Status; - if (!DevExt->IsFdo) + if (DevExt->Signature != IsaPnpBus) { - Status = Irp->IoStatus.Status; + switch (IoGetCurrentIrpStackLocation(Irp)->MinorFunction) + { + case IRP_MN_SET_POWER: + case IRP_MN_QUERY_POWER: + Status = STATUS_SUCCESS; + Irp->IoStatus.Status = Status; + break; + + default: + Status = Irp->IoStatus.Status; + break; + } + + PoStartNextPowerIrp(Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -763,9 +826,7 @@ IsaPnp( PAGED_CODE(); - DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); - - if (DevExt->IsFdo) + if (DevExt->Signature == IsaPnpBus) return IsaFdoPnp((PISAPNP_FDO_EXTENSION)DevExt, Irp, IrpSp); else return IsaPdoPnp((PISAPNP_PDO_EXTENSION)DevExt, Irp, IrpSp); @@ -782,13 +843,25 @@ DriverEntry( DriverObject->MajorFunction[IRP_MJ_CREATE] = IsaCreateClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = IsaCreateClose; - DriverObject->MajorFunction[IRP_MJ_READ] = IsaReadWrite; - DriverObject->MajorFunction[IRP_MJ_WRITE] = IsaReadWrite; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IsaIoctl; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IsaForwardOrIgnore; + DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IsaForwardOrIgnore; DriverObject->MajorFunction[IRP_MJ_PNP] = IsaPnp; DriverObject->MajorFunction[IRP_MJ_POWER] = IsaPower; DriverObject->DriverExtension->AddDevice = IsaAddDevice; + /* FIXME: Fix SDK headers */ +#if 0 + _No_competing_thread_begin_ +#endif + + KeInitializeEvent(&BusSyncEvent, SynchronizationEvent, TRUE); + InitializeListHead(&BusListHead); + + /* FIXME: Fix SDK headers */ +#if 0 + _No_competing_thread_end_ +#endif + return STATUS_SUCCESS; } diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index 4eb7fb4e19b..e476f9737b0 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -9,7 +9,7 @@ #ifndef _ISAPNP_PCH_ #define _ISAPNP_PCH_ -#include <wdm.h> +#include <ntddk.h> #include <ntstrsafe.h> #include <section_attribs.h> #include "isapnphw.h" @@ -60,13 +60,24 @@ typedef struct _ISAPNP_LOGICAL_DEVICE ISAPNP_DMA Dma[2]; UCHAR CSN; UCHAR LDN; + + ULONG Flags; +#define ISAPNP_PRESENT 0x00000001 /**< @brief Cleared when the device is physically removed. */ + LIST_ENTRY DeviceLink; } ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE; +typedef enum _ISAPNP_SIGNATURE +{ + IsaPnpBus = 'odFI', + IsaPnpLogicalDevice = 'veDI', + IsaPnpReadDataPort = 'pdRI' +} ISAPNP_SIGNATURE; + typedef struct _ISAPNP_COMMON_EXTENSION { + ISAPNP_SIGNATURE Signature; PDEVICE_OBJECT Self; - BOOLEAN IsFdo; ISAPNP_DEVICE_STATE State; } ISAPNP_COMMON_EXTENSION, *PISAPNP_COMMON_EXTENSION; @@ -75,13 +86,19 @@ typedef struct _ISAPNP_FDO_EXTENSION ISAPNP_COMMON_EXTENSION Common; PDEVICE_OBJECT Ldo; PDEVICE_OBJECT Pdo; - PDEVICE_OBJECT ReadPortPdo; + PDEVICE_OBJECT ReadPortPdo; /**< @remarks The pointer is NULL for all inactive FDOs. */ ULONG BusNumber; KEVENT DeviceSyncEvent; + + _Guarded_by_(DeviceSyncEvent) LIST_ENTRY DeviceListHead; + + _Guarded_by_(DeviceSyncEvent) ULONG DeviceCount; + PDRIVER_OBJECT DriverObject; PUCHAR ReadDataPort; + LIST_ENTRY BusLink; } ISAPNP_FDO_EXTENSION, *PISAPNP_FDO_EXTENSION; typedef struct _ISAPNP_PDO_EXTENSION @@ -90,10 +107,44 @@ typedef struct _ISAPNP_PDO_EXTENSION PISAPNP_LOGICAL_DEVICE IsaPnpDevice; PISAPNP_FDO_EXTENSION FdoExt; PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; + PCM_RESOURCE_LIST ResourceList; ULONG ResourceListSize; + + ULONG Flags; +#define ISAPNP_ENUMERATED 0x00000001 /**< @brief Whether the device has been reported to the PnP manager. */ +#define ISAPNP_SCANNED_BY_READ_PORT 0x00000002 /**< @brief The bus has been scanned by Read Port PDO. */ +#define ISAPNP_READ_PORT_ALLOW_FDO_SCAN 0x00000004 /**< @brief Allows the active FDO to scan the bus. */ + + _Write_guarded_by_(_Global_interlock_) + volatile LONG SpecialFiles; } ISAPNP_PDO_EXTENSION, *PISAPNP_PDO_EXTENSION; +extern KEVENT BusSyncEvent; + +_Guarded_by_(BusSyncEvent) +extern BOOLEAN ReadPortCreated; + +_Guarded_by_(BusSyncEvent) +extern LIST_ENTRY BusListHead; + +_Requires_lock_not_held_(BusSyncEvent) +_Acquires_lock_(BusSyncEvent) +FORCEINLINE +VOID +IsaPnpAcquireBusDataLock(VOID) +{ + KeWaitForSingleObject(&BusSyncEvent, Executive, KernelMode, FALSE, NULL); +} + +_Releases_lock_(BusSyncEvent) +FORCEINLINE +VOID +IsaPnpReleaseBusDataLock(VOID) +{ + KeSetEvent(&BusSyncEvent, IO_NO_INCREMENT, FALSE); +} + _Requires_lock_not_held_(FdoExt->DeviceSyncEvent) _Acquires_lock_(FdoExt->DeviceSyncEvent) FORCEINLINE @@ -115,6 +166,11 @@ IsaPnpReleaseDeviceDataLock( /* isapnp.c */ +CODE_SEG("PAGE") +VOID +IsaPnpRemoveReadPortDO( + _In_ PDEVICE_OBJECT Pdo); + CODE_SEG("PAGE") NTSTATUS IsaPnpFillDeviceRelations( @@ -125,12 +181,6 @@ IsaPnpFillDeviceRelations( CODE_SEG("INIT") DRIVER_INITIALIZE DriverEntry; -NTSTATUS -NTAPI -IsaForwardIrpSynchronous( - _In_ PISAPNP_FDO_EXTENSION FdoExt, - _Inout_ PIRP Irp); - /* fdo.c */ CODE_SEG("PAGE") NTSTATUS @@ -139,6 +189,13 @@ IsaFdoPnp( _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IrpSp); +/* interface.c */ +CODE_SEG("PAGE") +NTSTATUS +IsaFdoQueryInterface( + _In_ PISAPNP_FDO_EXTENSION FdoExt, + _In_ PIO_STACK_LOCATION IrpSp); + /* pdo.c */ CODE_SEG("PAGE") NTSTATUS @@ -147,6 +204,11 @@ IsaPdoPnp( _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IrpSp); +CODE_SEG("PAGE") +VOID +IsaPnpRemoveLogicalDeviceDO( + _In_ PDEVICE_OBJECT Pdo); + /* hardware.c */ CODE_SEG("PAGE") NTSTATUS diff --git a/drivers/bus/isapnp/pdo.c b/drivers/bus/isapnp/pdo.c index 1fae349f9e0..27aedff6c6f 100644 --- a/drivers/bus/isapnp/pdo.c +++ b/drivers/bus/isapnp/pdo.c @@ -4,6 +4,7 @@ * PURPOSE: PDO-specific code * COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman(a)reactos.org> * Copyright 2020 Hervé Poussineau <hpoussin(a)reactos.org> + * Copyright 2021 Dmitry Borisov <di.sean(a)protonmail.com> */ #include "isapnp.h" @@ -24,7 +25,7 @@ IsaPdoQueryDeviceRelations( PAGED_CODE(); if (IrpSp->Parameters.QueryDeviceRelations.Type == RemovalRelations && - PdoExt->Common.Self == PdoExt->FdoExt->ReadPortPdo) + PdoExt->Common.Signature == IsaPnpReadDataPort) { return IsaPnpFillDeviceRelations(PdoExt->FdoExt, Irp, FALSE); } @@ -70,8 +71,7 @@ IsaPdoQueryCapabilities( DeviceCapabilities->UniqueID = TRUE; - if (PdoExt->FdoExt->ReadPortPdo && - PdoExt->Common.Self == PdoExt->FdoExt->ReadPortPdo) + if (PdoExt->Common.Signature == IsaPnpReadDataPort) { DeviceCapabilities->RawDeviceOK = TRUE; DeviceCapabilities->SilentInstall = TRUE; @@ -89,13 +89,17 @@ CODE_SEG("PAGE") NTSTATUS IsaPdoQueryPnpDeviceState( _In_ PISAPNP_PDO_EXTENSION PdoExt, - _Inout_ PIRP Irp, - _In_ PIO_STACK_LOCATION IrpSp) + _Inout_ PIRP Irp) { PAGED_CODE(); - Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; - return STATUS_SUCCESS; + if (PdoExt->SpecialFiles > 0) + { + Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; + return STATUS_SUCCESS; + } + + return Irp->IoStatus.Status; } static @@ -319,6 +323,8 @@ IsaPdoQueryResources( ULONG ListSize; PCM_RESOURCE_LIST ResourceList; + UNREFERENCED_PARAMETER(IrpSp); + PAGED_CODE(); if (!PdoExt->ResourceList) @@ -345,6 +351,8 @@ IsaPdoQueryResourceRequirements( ULONG ListSize; PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; + UNREFERENCED_PARAMETER(IrpSp); + PAGED_CODE(); if (!PdoExt->RequirementsList) @@ -367,6 +375,7 @@ IsaPdoStartReadPort( _In_ PISAPNP_FDO_EXTENSION FdoExt, _In_ PIO_STACK_LOCATION IrpSp) { + PISAPNP_PDO_EXTENSION PdoExt = FdoExt->ReadPortPdo->DeviceExtension; PCM_RESOURCE_LIST ResourceList = IrpSp->Parameters.StartDevice.AllocatedResources; NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; ULONG i; @@ -410,6 +419,9 @@ IsaPdoStartReadPort( if (FdoExt->DeviceCount > 0) { + PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN | + ISAPNP_SCANNED_BY_READ_PORT; + IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations); IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations); } @@ -426,61 +438,19 @@ IsaPdoStartReadPort( } static +CODE_SEG("PAGE") NTSTATUS -NTAPI -IsaPdoOnRepeaterComplete( - PDEVICE_OBJECT Tdo, - PIRP SubIrp, - PVOID NeedsVote) -{ - PIO_STACK_LOCATION SubStack = IoGetCurrentIrpStackLocation(SubIrp); - PIRP Irp = (PIRP)SubStack->Parameters.Others.Argument1; - ObDereferenceObject(Tdo); - - if (SubIrp->IoStatus.Status == STATUS_NOT_SUPPORTED) - { - if (NeedsVote) - { - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - } - } - else - { - Irp->IoStatus = SubIrp->IoStatus; - } - - IoFreeIrp(SubIrp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -NTAPI -IsaPdoRepeatRequest( +IsaPdoFilterResourceRequirements( _In_ PISAPNP_PDO_EXTENSION PdoExt, - _In_ PIRP Irp, - _In_ BOOLEAN NeedsVote) + _Inout_ PIRP Irp, + _In_ PIO_STACK_LOCATION IrpSp) { - PDEVICE_OBJECT Fdo = PdoExt->FdoExt->Common.Self; - PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); - PDEVICE_OBJECT Tdo = IoGetAttachedDeviceReference(Fdo); - PIRP SubIrp = IoAllocateIrp(Tdo->StackSize + 1, FALSE); - PIO_STACK_LOCATION SubStack = IoGetNextIrpStackLocation(SubIrp); - - SubStack->DeviceObject = Tdo; - SubStack->Parameters.Others.Argument1 = (PVOID)Irp; - - IoSetNextIrpStackLocation(SubIrp); - SubStack = IoGetNextIrpStackLocation(SubIrp); - RtlCopyMemory(SubStack, Stack, FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine)); - SubStack->Control = 0; - IoSetCompletionRoutine(SubIrp, IsaPdoOnRepeaterComplete, (PVOID)(ULONG_PTR)NeedsVote, TRUE, TRUE, TRUE); - - SubIrp->IoStatus.Status = STATUS_NOT_SUPPORTED; - IoMarkIrpPending(Irp); - IoCallDriver(Tdo, SubIrp); - - return STATUS_PENDING; + PAGED_CODE(); + + /* TODO: Handle */ + UNREFERENCED_PARAMETER(PdoExt); + UNREFERENCED_PARAMETER(IrpSp); + return Irp->IoStatus.Status; } static @@ -508,6 +478,124 @@ IsaPdoQueryBusInformation( return STATUS_SUCCESS; } +static +CODE_SEG("PAGE") +NTSTATUS +IsaPdoQueryDeviceUsageNotification( + _In_ PISAPNP_PDO_EXTENSION PdoExt, + _Inout_ PIRP Irp, + _In_ PIO_STACK_LOCATION IrpSp) +{ + BOOLEAN InPath = IrpSp->Parameters.UsageNotification.InPath; + + PAGED_CODE(); + + switch (IrpSp->Parameters.UsageNotification.Type) + { + case DeviceUsageTypePaging: + case DeviceUsageTypeHibernation: + case DeviceUsageTypeDumpFile: + IoAdjustPagingPathCount(&PdoExt->SpecialFiles, InPath); + IoInvalidateDeviceState(PdoExt->Common.Self); + break; + + default: + return Irp->IoStatus.Status; + } + + /* Do not send it to FDO for compatibility */ + return STATUS_SUCCESS; +} + +static +CODE_SEG("PAGE") +NTSTATUS +IsaPdoRemoveDevice( + _In_ PISAPNP_PDO_EXTENSION PdoExt, + _In_ BOOLEAN FinalRemove) +{ + PISAPNP_FDO_EXTENSION FdoExt = PdoExt->FdoExt; + + PAGED_CODE(); + + if (FinalRemove && !(PdoExt->Flags & ISAPNP_ENUMERATED)) + { + IsaPnpAcquireDeviceDataLock(FdoExt); + + RemoveEntryList(&PdoExt->IsaPnpDevice->DeviceLink); + --FdoExt->DeviceCount; + + IsaPnpReleaseDeviceDataLock(FdoExt); + + IsaPnpRemoveLogicalDeviceDO(PdoExt->Common.Self); + } + + return STATUS_SUCCESS; +} + +static +CODE_SEG("PAGE") +NTSTATUS +IsaReadPortRemoveDevice( + _In_ PISAPNP_PDO_EXTENSION PdoExt, + _In_ BOOLEAN FinalRemove) +{ + PISAPNP_FDO_EXTENSION FdoExt = PdoExt->FdoExt; + PLIST_ENTRY Entry; + + PAGED_CODE(); + + IsaPnpAcquireDeviceDataLock(FdoExt); + + /* Logical devices will receive a remove request afterwards */ + for (Entry = FdoExt->DeviceListHead.Flink; + Entry != &FdoExt->DeviceListHead; + Entry = Entry->Flink) + { + PISAPNP_LOGICAL_DEVICE LogDevice = CONTAINING_RECORD(Entry, + ISAPNP_LOGICAL_DEVICE, + DeviceLink); + + LogDevice->Flags &= ~ISAPNP_PRESENT; + } + + IsaPnpReleaseDeviceDataLock(FdoExt); + + PdoExt->Flags &= ~ISAPNP_READ_PORT_ALLOW_FDO_SCAN; + IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations); + + if (FinalRemove && !(PdoExt->Flags & ISAPNP_ENUMERATED)) + { + IsaPnpRemoveReadPortDO(PdoExt->Common.Self); + } + + return STATUS_SUCCESS; +} + +CODE_SEG("PAGE") +VOID +IsaPnpRemoveLogicalDeviceDO( + _In_ PDEVICE_OBJECT Pdo) +{ + PISAPNP_PDO_EXTENSION PdoExt = Pdo->DeviceExtension; + PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; + + PAGED_CODE(); + ASSERT(LogDev); + + DPRINT("Removing CSN %u, LDN %u\n", LogDev->CSN, LogDev->LDN); + + if (PdoExt->RequirementsList) + ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP); + + if (PdoExt->ResourceList) + ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP); + + ExFreePoolWithTag(LogDev, TAG_ISAPNP); + + IoDeleteDevice(PdoExt->Common.Self); +} + CODE_SEG("PAGE") NTSTATUS IsaPdoPnp( @@ -519,10 +607,29 @@ IsaPdoPnp( PAGED_CODE(); + if (PdoExt->Common.Signature == IsaPnpLogicalDevice) + { + DPRINT("%s(%p, %p) CSN %u, LDN %u, Minor - %X\n", + __FUNCTION__, + PdoExt, + Irp, + PdoExt->IsaPnpDevice->CSN, + PdoExt->IsaPnpDevice->LDN, + IrpSp->MinorFunction); + } + else + { + DPRINT("%s(%p, %p) ReadPort, Minor - %X\n", + __FUNCTION__, + PdoExt, + Irp, + IrpSp->MinorFunction); + } + switch (IrpSp->MinorFunction) { case IRP_MN_START_DEVICE: - if (PdoExt->IsaPnpDevice) + if (PdoExt->Common.Signature == IsaPnpLogicalDevice) Status = IsaHwActivateDevice(PdoExt->IsaPnpDevice); else Status = IsaPdoStartReadPort(PdoExt->FdoExt, IrpSp); @@ -532,15 +639,36 @@ IsaPdoPnp( break; case IRP_MN_STOP_DEVICE: - if (PdoExt->IsaPnpDevice) + if (PdoExt->Common.Signature == IsaPnpLogicalDevice) Status = IsaHwDeactivateDevice(PdoExt->IsaPnpDevice); else + { + PdoExt->Flags &= ~ISAPNP_READ_PORT_ALLOW_FDO_SCAN; Status = STATUS_SUCCESS; + } if (NT_SUCCESS(Status)) PdoExt->Common.State = dsStopped; break; + case IRP_MN_QUERY_STOP_DEVICE: + { + if (PdoExt->SpecialFiles > 0) + Status = STATUS_DEVICE_BUSY; + else + Status = STATUS_SUCCESS; + break; + } + + case IRP_MN_QUERY_REMOVE_DEVICE: + { + if (PdoExt->SpecialFiles > 0) + Status = STATUS_DEVICE_BUSY; + else + Status = STATUS_SUCCESS; + break; + } + case IRP_MN_QUERY_DEVICE_RELATIONS: Status = IsaPdoQueryDeviceRelations(PdoExt, Irp, IrpSp); break; @@ -549,9 +677,22 @@ IsaPdoPnp( Status = IsaPdoQueryCapabilities(PdoExt, Irp, IrpSp); break; + case IRP_MN_SURPRISE_REMOVAL: + if (PdoExt->Common.Signature == IsaPnpLogicalDevice) + Status = IsaPdoRemoveDevice(PdoExt, FALSE); + else + Status = IsaReadPortRemoveDevice(PdoExt, FALSE); + break; + + case IRP_MN_REMOVE_DEVICE: + if (PdoExt->Common.Signature == IsaPnpLogicalDevice) + Status = IsaPdoRemoveDevice(PdoExt, TRUE); + else + Status = IsaReadPortRemoveDevice(PdoExt, TRUE); + break; + case IRP_MN_QUERY_PNP_DEVICE_STATE: - if (PdoExt->Common.Self == PdoExt->FdoExt->ReadPortPdo) - Status = IsaPdoQueryPnpDeviceState(PdoExt, Irp, IrpSp); + Status = IsaPdoQueryPnpDeviceState(PdoExt, Irp); break; case IRP_MN_QUERY_RESOURCES: @@ -563,36 +704,31 @@ IsaPdoPnp( break; case IRP_MN_QUERY_ID: - if (PdoExt->IsaPnpDevice) + if (PdoExt->Common.Signature == IsaPnpLogicalDevice) Status = IsaPdoQueryId(PdoExt, Irp, IrpSp); else Status = IsaReadPortQueryId(Irp, IrpSp); break; + case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: + Status = IsaPdoFilterResourceRequirements(PdoExt, Irp, IrpSp); + break; + case IRP_MN_QUERY_BUS_INFORMATION: Status = IsaPdoQueryBusInformation(PdoExt, Irp); break; - case IRP_MN_QUERY_REMOVE_DEVICE: - case IRP_MN_REMOVE_DEVICE: + case IRP_MN_DEVICE_USAGE_NOTIFICATION: + Status = IsaPdoQueryDeviceUsageNotification(PdoExt, Irp, IrpSp); + break; + case IRP_MN_CANCEL_REMOVE_DEVICE: - case IRP_MN_QUERY_STOP_DEVICE: case IRP_MN_CANCEL_STOP_DEVICE: - case IRP_MN_QUERY_DEVICE_TEXT: - case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: - case IRP_MN_SURPRISE_REMOVAL: Status = STATUS_SUCCESS; break; - case IRP_MN_READ_CONFIG: - case IRP_MN_WRITE_CONFIG: - case IRP_MN_EJECT: - case IRP_MN_SET_LOCK: - case IRP_MN_DEVICE_USAGE_NOTIFICATION: - return IsaPdoRepeatRequest(PdoExt, Irp, TRUE); - default: - DPRINT1("Unknown PnP code: %x\n", IrpSp->MinorFunction); + DPRINT("Unknown PnP code: %X\n", IrpSp->MinorFunction); break; }
3 years, 6 months
1
0
0
0
← Newer
1
...
7
8
9
10
11
12
13
...
23
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Results per page:
10
25
50
100
200