diff --git a/drivers/bus/acpi/acpica/include/acpi.h b/drivers/bus/acpi/acpica/include/acpi.h index 6519a5139a6..afc92503d63 100644 --- a/drivers/bus/acpi/acpica/include/acpi.h +++ b/drivers/bus/acpi/acpica/include/acpi.h @@ -44,7 +44,7 @@ #ifndef __ACPI_H__ #define __ACPI_H__ -#ifdef __REACTOS__ +#if defined(__REACTOS__) && !defined(UNIT_TEST) /* * Header inclusion HACK. */ diff --git a/drivers/bus/acpi/buspdo.c b/drivers/bus/acpi/buspdo.c index ac43a847dd5..61607abb44f 100644 --- a/drivers/bus/acpi/buspdo.c +++ b/drivers/bus/acpi/buspdo.c @@ -1,3 +1,4 @@ +#ifndef UNIT_TEST #include "precomp.h" #include @@ -1294,6 +1295,7 @@ Bus_PDO_QueryResources( Irp->IoStatus.Information = (ULONG_PTR)ResourceList; return STATUS_SUCCESS; } +#endif /* UNIT_TEST */ NTSTATUS Bus_PDO_QueryResourceRequirements( @@ -1796,6 +1798,7 @@ Bus_PDO_QueryResourceRequirements( return STATUS_SUCCESS; } +#ifndef UNIT_TEST NTSTATUS Bus_PDO_QueryDeviceRelations( PPDO_DEVICE_DATA DeviceData, @@ -2040,5 +2043,4 @@ GetDeviceCapabilitiesExit: return status; } - - +#endif /* UNIT_TEST */ diff --git a/modules/rostests/apitests/CMakeLists.txt b/modules/rostests/apitests/CMakeLists.txt index 9f1d6ce225b..752755a453f 100644 --- a/modules/rostests/apitests/CMakeLists.txt +++ b/modules/rostests/apitests/CMakeLists.txt @@ -3,6 +3,7 @@ PROJECT(ApiTests) include_directories(include) +add_subdirectory(acpi) add_subdirectory(advapi32) add_subdirectory(afd) add_subdirectory(apphelp) diff --git a/modules/rostests/apitests/acpi/Bus_PDO_QueryResourceRequirements.c b/modules/rostests/apitests/acpi/Bus_PDO_QueryResourceRequirements.c new file mode 100644 index 00000000000..08a7a13dd4c --- /dev/null +++ b/modules/rostests/apitests/acpi/Bus_PDO_QueryResourceRequirements.c @@ -0,0 +1,530 @@ +/* + * PROJECT: ReactOS API Tests + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Unit Tests for acpi!Bus_PDO_QueryResourceRequirements + * COPYRIGHT: Copyright 2017-2020 Thomas Faber (thomas.faber@reactos.org) + */ + +#include + +#define WIN32_NO_STATUS +#include +#define UNIT_TEST +#include + +/* Kernel definitions (copied) */ +#define IO_RESOURCE_PREFERRED 0x01 +#define IO_RESOURCE_DEFAULT 0x02 +#define IO_RESOURCE_ALTERNATIVE 0x08 + +typedef struct _IO_RESOURCE_DESCRIPTOR { + UCHAR Option; + UCHAR Type; + UCHAR ShareDisposition; + UCHAR Spare1; + USHORT Flags; + USHORT Spare2; + union { + struct { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; + } Port; + struct { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; + } Memory; + struct { + ULONG MinimumVector; + ULONG MaximumVector; + } Interrupt; + struct { + ULONG MinimumChannel; + ULONG MaximumChannel; + } Dma; + struct { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; + } Generic; + struct { + ULONG Data[3]; + } DevicePrivate; + struct { + ULONG Length; + ULONG MinBusNumber; + ULONG MaxBusNumber; + ULONG Reserved; + } BusNumber; + struct { + ULONG Priority; + ULONG Reserved1; + ULONG Reserved2; + } ConfigData; + } u; +} IO_RESOURCE_DESCRIPTOR, *PIO_RESOURCE_DESCRIPTOR; + +typedef struct _IO_RESOURCE_LIST { + USHORT Version; + USHORT Revision; + ULONG Count; + IO_RESOURCE_DESCRIPTOR Descriptors[1]; +} IO_RESOURCE_LIST, *PIO_RESOURCE_LIST; + +typedef struct _IO_RESOURCE_REQUIREMENTS_LIST { + ULONG ListSize; + INTERFACE_TYPE InterfaceType; + ULONG BusNumber; + ULONG SlotNumber; + ULONG Reserved[3]; + ULONG AlternativeLists; + IO_RESOURCE_LIST List[1]; +} IO_RESOURCE_REQUIREMENTS_LIST, *PIO_RESOURCE_REQUIREMENTS_LIST; + +/* Kernel definitions (mock) */ +#define PAGED_CODE() +#define DPRINT1(...) do { if (0) DbgPrint(__VA_ARGS__); } while (0) + +typedef struct _IRP +{ + IO_STATUS_BLOCK IoStatus; +} IRP, *PIRP; + +#define PagedPool 1 +static +PVOID +ExAllocatePoolWithTag(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag) +{ + PVOID *Mem; + + Mem = HeapAlloc(GetProcessHeap(), 0, NumberOfBytes + 2 * sizeof(PVOID)); + Mem[0] = (PVOID)NumberOfBytes; + Mem[1] = (PVOID)(ULONG_PTR)Tag; + return Mem + 2; +} + +static +VOID +ExFreePoolWithTag(PVOID MemPtr, ULONG Tag) +{ + PVOID *Mem = MemPtr; + + Mem -= 2; + ok(Mem[1] == (PVOID)(ULONG_PTR)Tag, "Tag is %lx, expected %p\n", Tag, Mem[1]); + HeapFree(GetProcessHeap(), 0, Mem); +} + +static +SIZE_T +GetPoolAllocSize(PVOID MemPtr) +{ + PVOID *Mem = MemPtr; + + Mem -= 2; + return (SIZE_T)Mem[0]; +} + +/* ACPI driver definitions */ +typedef struct _PDO_DEVICE_DATA +{ + HANDLE AcpiHandle; + PWCHAR HardwareIDs; +} PDO_DEVICE_DATA, *PPDO_DEVICE_DATA; + +/* ACPICA functions (mock) */ +static BOOLEAN AcpiCallExpected; +static ACPI_HANDLE CorrectHandle = &CorrectHandle; +static ACPI_BUFFER CurrentBuffer; +static ACPI_BUFFER PossibleBuffer; + +ACPI_STATUS +AcpiGetCurrentResources ( + ACPI_HANDLE Device, + ACPI_BUFFER *RetBuffer) +{ + ok(AcpiCallExpected, "Unexpected call to AcpiGetCurrentResources\n"); + ok(Device == CorrectHandle, "Device = %p, expected %p\n", Device, CorrectHandle); + if (RetBuffer->Length < CurrentBuffer.Length) + { + RetBuffer->Length = CurrentBuffer.Length; + return AE_BUFFER_OVERFLOW; + } + RetBuffer->Length = CurrentBuffer.Length; + CopyMemory(RetBuffer->Pointer, CurrentBuffer.Pointer, CurrentBuffer.Length); + return AE_OK; +} + +ACPI_STATUS +AcpiGetPossibleResources ( + ACPI_HANDLE Device, + ACPI_BUFFER *RetBuffer) +{ + ok(AcpiCallExpected, "Unexpected call to AcpiGetPossibleResources\n"); + ok(Device == CorrectHandle, "Device = %p, expected %p\n", Device, CorrectHandle); + if (RetBuffer->Length < PossibleBuffer.Length) + { + RetBuffer->Length = PossibleBuffer.Length; + return AE_BUFFER_OVERFLOW; + } + RetBuffer->Length = PossibleBuffer.Length; + CopyMemory(RetBuffer->Pointer, PossibleBuffer.Pointer, PossibleBuffer.Length); + return AE_OK; +} + +#include "../../../../drivers/bus/acpi/buspdo.c" + +/* ACPI_RESOURCE builder helpers */ +#define MAKE_IRQ(Resource, _DescriptorLength, _Triggering, _Polarity, _Shareable, _WakeCapable) \ + do { \ + Resource->Data.Irq.DescriptorLength = _DescriptorLength; \ + Resource->Data.Irq.Triggering = _Triggering; \ + Resource->Data.Irq.Polarity = _Polarity; \ + Resource->Data.Irq.Shareable = _Shareable; \ + Resource->Data.Irq.WakeCapable = _WakeCapable; \ + } while (0) + +/* IO_RESOURCE_DESCRIPTOR expectations */ +#define expect_irq(Desc, ExpectedOption, ExpectedShare, ExpectedMin, ExpectedMax) \ + do { \ + ok((Desc)->Option == ExpectedOption, "Desc->Option = %u\n", (Desc)->Option); \ + ok((Desc)->Type == CmResourceTypeInterrupt, "Desc->Type = %u\n", (Desc)->Type); \ + ok((Desc)->ShareDisposition == ExpectedShare, "Desc->ShareDisposition = %u\n", (Desc)->ShareDisposition); \ + ok((Desc)->u.Interrupt.MinimumVector == ExpectedMin, "Desc->u.Interrupt.MinimumVector = %lu\n", (Desc)->u.Interrupt.MinimumVector); \ + ok((Desc)->u.Interrupt.MaximumVector == ExpectedMax, "Desc->u.Interrupt.MaximumVector = %lu\n", (Desc)->u.Interrupt.MaximumVector); \ + } while (0) + +#define expect_port(Desc, ExpectedOption, ExpectedShare, ExpectedLength, ExpectedAlign, ExpectedMin, ExpectedMax) \ + do { \ + ok((Desc)->Option == ExpectedOption, "Desc->Option = %u\n", (Desc)->Option); \ + ok((Desc)->Type == CmResourceTypePort, "Desc->Type = %u\n", (Desc)->Type); \ + ok((Desc)->ShareDisposition == ExpectedShare, "Desc->ShareDisposition = %u\n", (Desc)->ShareDisposition); \ + ok((Desc)->u.Port.Length == ExpectedLength, "Desc->u.Port.Length = %lu\n", (Desc)->u.Port.Length); \ + ok((Desc)->u.Port.Alignment == ExpectedAlign, "Desc->u.Port.Alignment = %lu\n", (Desc)->u.Port.Alignment); \ + ok((Desc)->u.Port.MinimumAddress.QuadPart == ExpectedMin, "Desc->u.Port.MinimumAddress = 0x%I64x\n", (Desc)->u.Port.MinimumAddress.QuadPart); \ + ok((Desc)->u.Port.MaximumAddress.QuadPart == ExpectedMax, "Desc->u.Port.MaximumAddress = 0x%I64x\n", (Desc)->u.Port.MaximumAddress.QuadPart); \ + } while (0) + +START_TEST(Bus_PDO_QueryResourceRequirements) +{ + NTSTATUS Status; + PDO_DEVICE_DATA DeviceData; + IRP Irp; + ACPI_RESOURCE ResourcesBuffer[20]; + ACPI_RESOURCE *Resource; + PIO_RESOURCE_REQUIREMENTS_LIST ReqList; + PIO_RESOURCE_LIST ReqList2; + + /* Invalid AcpiHandle */ + AcpiCallExpected = FALSE; + Irp.IoStatus.Status = STATUS_WAIT_0 + 17; + DeviceData.AcpiHandle = NULL; + Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp); + ok(Status == STATUS_WAIT_0 + 17, "Status = 0x%lx\n", Status); + + /* PCI Bus device */ + AcpiCallExpected = FALSE; + Irp.IoStatus.Status = STATUS_WAIT_0 + 17; + DeviceData.AcpiHandle = CorrectHandle; + DeviceData.HardwareIDs = L"PNP0A03\0"; + Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp); + ok(Status == STATUS_WAIT_0 + 17, "Status = 0x%lx\n", Status); + + /* PCI Bus device #2 */ + AcpiCallExpected = FALSE; + Irp.IoStatus.Status = STATUS_WAIT_0 + 17; + DeviceData.AcpiHandle = CorrectHandle; + DeviceData.HardwareIDs = L"PNP0A08\0"; + Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp); + ok(Status == STATUS_WAIT_0 + 17, "Status = 0x%lx\n", Status); + + /* Empty buffer */ + AcpiCallExpected = TRUE; + Irp.IoStatus.Status = STATUS_WAIT_0 + 17; + DeviceData.AcpiHandle = CorrectHandle; + DeviceData.HardwareIDs = L"PNP0501\0"; + Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp); + ok(Status == STATUS_WAIT_0 + 17, "Status = 0x%lx\n", Status); + + /* Simple single-resource list */ + AcpiCallExpected = TRUE; + Irp.IoStatus.Status = STATUS_WAIT_0 + 17; + Irp.IoStatus.Information = 0; + DeviceData.AcpiHandle = CorrectHandle; + DeviceData.HardwareIDs = L"PNP0501\0"; + Resource = ResourcesBuffer; + Resource->Type = ACPI_RESOURCE_TYPE_IRQ; + Resource->Length = sizeof(*Resource); + MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE); + Resource->Data.Irq.InterruptCount = 1; + Resource->Data.Irq.Interrupts[0] = 7; + Resource = ACPI_NEXT_RESOURCE(Resource); + Resource->Type = ACPI_RESOURCE_TYPE_END_TAG; + Resource->Length = 0; + Resource++; + PossibleBuffer.Pointer = ResourcesBuffer; + PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer; + Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp); + ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status); + ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", Irp.IoStatus.Status); + ReqList = (PVOID)Irp.IoStatus.Information; + ok(ReqList != NULL, "ReqList is NULL\n"); + if (ReqList == NULL) + { + skip("No ReqList\n"); + return; + } + ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", ReqList->InterfaceType); + ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber); + ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber); + ok(ReqList->AlternativeLists == 1, "AlternativeLists = %lu\n", ReqList->AlternativeLists); + ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", ReqList->List[0].Version); + ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", ReqList->List[0].Revision); + ok(ReqList->List[0].Count == 1, "List[0].Count = %lu\n", ReqList->List[0].Count); + expect_irq(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, CmResourceShareDeviceExclusive, 7, 7); + ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList)); + ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList->List[0].Descriptors[1] - (ULONG_PTR)ReqList); + ExFreePoolWithTag(ReqList, 'RpcA'); + + /* Two IRQs */ + AcpiCallExpected = TRUE; + Irp.IoStatus.Status = STATUS_WAIT_0 + 17; + Irp.IoStatus.Information = 0; + DeviceData.AcpiHandle = CorrectHandle; + DeviceData.HardwareIDs = L"PNP0501\0"; + Resource = ResourcesBuffer; + Resource->Type = ACPI_RESOURCE_TYPE_IRQ; + Resource->Length = FIELD_OFFSET(ACPI_RESOURCE, Data) + FIELD_OFFSET(ACPI_RESOURCE_IRQ, Interrupts[2]); + MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE); + Resource->Data.Irq.InterruptCount = 2; + Resource->Data.Irq.Interrupts[0] = 3; + Resource->Data.Irq.Interrupts[1] = 7; + Resource = ACPI_NEXT_RESOURCE(Resource); + Resource->Type = ACPI_RESOURCE_TYPE_END_TAG; + Resource->Length = 0; + Resource++; + PossibleBuffer.Pointer = ResourcesBuffer; + PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer; + Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp); + ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status); + ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", Irp.IoStatus.Status); + ReqList = (PVOID)Irp.IoStatus.Information; + ok(ReqList != NULL, "ReqList is NULL\n"); + if (ReqList == NULL) + { + skip("No ReqList\n"); + return; + } + ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", ReqList->InterfaceType); + ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber); + ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber); + ok(ReqList->AlternativeLists == 1, "AlternativeLists = %lu\n", ReqList->AlternativeLists); + ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", ReqList->List[0].Version); + ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", ReqList->List[0].Revision); + ok(ReqList->List[0].Count == 2, "List[0].Count = %lu\n", ReqList->List[0].Count); + expect_irq(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, CmResourceShareDeviceExclusive, 3, 3); + expect_irq(&ReqList->List[0].Descriptors[1], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 7, 7); + ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList)); + ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList->List[0].Descriptors[2] - (ULONG_PTR)ReqList); + ExFreePoolWithTag(ReqList, 'RpcA'); + + /* Port */ + AcpiCallExpected = TRUE; + Irp.IoStatus.Status = STATUS_WAIT_0 + 17; + Irp.IoStatus.Information = 0; + DeviceData.AcpiHandle = CorrectHandle; + DeviceData.HardwareIDs = L"PNP0501\0"; + Resource = ResourcesBuffer; + Resource->Type = ACPI_RESOURCE_TYPE_IO; + Resource->Length = sizeof(*Resource); + Resource->Data.Io.IoDecode = ACPI_DECODE_16; + Resource->Data.Io.Alignment = 8; + Resource->Data.Io.AddressLength = 8; + Resource->Data.Io.Minimum = 0x3F8; + Resource->Data.Io.Maximum = 0x3F8; + Resource = ACPI_NEXT_RESOURCE(Resource); + Resource->Type = ACPI_RESOURCE_TYPE_END_TAG; + Resource->Length = 0; + Resource++; + PossibleBuffer.Pointer = ResourcesBuffer; + PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer; + Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp); + ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status); + ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", Irp.IoStatus.Status); + ReqList = (PVOID)Irp.IoStatus.Information; + ok(ReqList != NULL, "ReqList is NULL\n"); + if (ReqList == NULL) + { + skip("No ReqList\n"); + return; + } + ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", ReqList->InterfaceType); + ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber); + ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber); + ok(ReqList->AlternativeLists == 1, "AlternativeLists = %lu\n", ReqList->AlternativeLists); + ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", ReqList->List[0].Version); + ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", ReqList->List[0].Revision); + ok(ReqList->List[0].Count == 1, "List[0].Count = %lu\n", ReqList->List[0].Count); + expect_port(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, CmResourceShareDriverExclusive, 8, 8, 0x3F8, 0x3FF); + ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList)); + ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList->List[0].Descriptors[1] - (ULONG_PTR)ReqList); + ExFreePoolWithTag(ReqList, 'RpcA'); + + /* Port + two IRQs */ + AcpiCallExpected = TRUE; + Irp.IoStatus.Status = STATUS_WAIT_0 + 17; + Irp.IoStatus.Information = 0; + DeviceData.AcpiHandle = CorrectHandle; + DeviceData.HardwareIDs = L"PNP0501\0"; + Resource = ResourcesBuffer; + Resource->Type = ACPI_RESOURCE_TYPE_IO; + Resource->Length = sizeof(*Resource); + Resource->Data.Io.IoDecode = ACPI_DECODE_16; + Resource->Data.Io.Alignment = 8; + Resource->Data.Io.AddressLength = 8; + Resource->Data.Io.Minimum = 0x3F8; + Resource->Data.Io.Maximum = 0x3F8; + Resource = ACPI_NEXT_RESOURCE(Resource); + Resource->Type = ACPI_RESOURCE_TYPE_IRQ; + Resource->Length = FIELD_OFFSET(ACPI_RESOURCE, Data) + FIELD_OFFSET(ACPI_RESOURCE_IRQ, Interrupts[2]); + MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE); + Resource->Data.Irq.InterruptCount = 2; + Resource->Data.Irq.Interrupts[0] = 3; + Resource->Data.Irq.Interrupts[1] = 7; + Resource = ACPI_NEXT_RESOURCE(Resource); + Resource->Type = ACPI_RESOURCE_TYPE_END_TAG; + Resource->Length = 0; + Resource++; + PossibleBuffer.Pointer = ResourcesBuffer; + PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer; + Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp); + ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status); + ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", Irp.IoStatus.Status); + ReqList = (PVOID)Irp.IoStatus.Information; + ok(ReqList != NULL, "ReqList is NULL\n"); + if (ReqList == NULL) + { + skip("No ReqList\n"); + return; + } + ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", ReqList->InterfaceType); + ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber); + ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber); + ok(ReqList->AlternativeLists == 1, "AlternativeLists = %lu\n", ReqList->AlternativeLists); + ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", ReqList->List[0].Version); + ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", ReqList->List[0].Revision); + ok(ReqList->List[0].Count == 3, "List[0].Count = %lu\n", ReqList->List[0].Count); + expect_port(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, CmResourceShareDriverExclusive, 8, 8, 0x3F8, 0x3FF); + expect_irq(&ReqList->List[0].Descriptors[1], IO_RESOURCE_PREFERRED, CmResourceShareDeviceExclusive, 3, 3); + expect_irq(&ReqList->List[0].Descriptors[2], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 7, 7); + ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList)); + ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList->List[0].Descriptors[3] - (ULONG_PTR)ReqList); + ExFreePoolWithTag(ReqList, 'RpcA'); + + /* Multiple alternatives for ports + IRQs (VMware COM port, simplified) */ + AcpiCallExpected = TRUE; + Irp.IoStatus.Status = STATUS_WAIT_0 + 17; + Irp.IoStatus.Information = 0; + DeviceData.AcpiHandle = CorrectHandle; + DeviceData.HardwareIDs = L"PNP0501\0"; + Resource = ResourcesBuffer; + Resource->Type = ACPI_RESOURCE_TYPE_START_DEPENDENT; + Resource->Length = sizeof(*Resource); + + Resource = ACPI_NEXT_RESOURCE(Resource); + Resource->Type = ACPI_RESOURCE_TYPE_IO; + Resource->Length = sizeof(*Resource); + Resource->Data.Io.IoDecode = ACPI_DECODE_16; + Resource->Data.Io.Alignment = 8; + Resource->Data.Io.AddressLength = 8; + Resource->Data.Io.Minimum = 0x3E8; + Resource->Data.Io.Maximum = 0x3E8; + + Resource = ACPI_NEXT_RESOURCE(Resource); + Resource->Type = ACPI_RESOURCE_TYPE_IRQ; + Resource->Length = FIELD_OFFSET(ACPI_RESOURCE, Data) + FIELD_OFFSET(ACPI_RESOURCE_IRQ, Interrupts[5]); + MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE); + Resource->Data.Irq.InterruptCount = 5; + Resource->Data.Irq.Interrupts[0] = 3; + Resource->Data.Irq.Interrupts[1] = 4; + Resource->Data.Irq.Interrupts[2] = 5; + Resource->Data.Irq.Interrupts[3] = 6; + Resource->Data.Irq.Interrupts[4] = 7; + + Resource = ACPI_NEXT_RESOURCE(Resource); + Resource->Type = ACPI_RESOURCE_TYPE_START_DEPENDENT; + Resource->Length = sizeof(*Resource); + + Resource = ACPI_NEXT_RESOURCE(Resource); + Resource->Type = ACPI_RESOURCE_TYPE_IO; + Resource->Length = sizeof(*Resource); + Resource->Data.Io.IoDecode = ACPI_DECODE_16; + Resource->Data.Io.Alignment = 8; + Resource->Data.Io.AddressLength = 8; + Resource->Data.Io.Minimum = 0x2E8; + Resource->Data.Io.Maximum = 0x2E8; + + Resource = ACPI_NEXT_RESOURCE(Resource); + Resource->Type = ACPI_RESOURCE_TYPE_IRQ; + Resource->Length = FIELD_OFFSET(ACPI_RESOURCE, Data) + FIELD_OFFSET(ACPI_RESOURCE_IRQ, Interrupts[5]); + MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE); + Resource->Data.Irq.InterruptCount = 5; + Resource->Data.Irq.Interrupts[0] = 3; + Resource->Data.Irq.Interrupts[1] = 4; + Resource->Data.Irq.Interrupts[2] = 5; + Resource->Data.Irq.Interrupts[3] = 6; + Resource->Data.Irq.Interrupts[4] = 7; + + Resource = ACPI_NEXT_RESOURCE(Resource); + Resource->Type = ACPI_RESOURCE_TYPE_END_DEPENDENT; + Resource->Length = sizeof(*Resource); + + Resource = ACPI_NEXT_RESOURCE(Resource); + Resource->Type = ACPI_RESOURCE_TYPE_END_TAG; + Resource->Length = 0; + Resource++; + PossibleBuffer.Pointer = ResourcesBuffer; + PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer; + Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp); + ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status); + ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", Irp.IoStatus.Status); + ReqList = (PVOID)Irp.IoStatus.Information; + ok(ReqList != NULL, "ReqList is NULL\n"); + if (ReqList == NULL) + { + skip("No ReqList\n"); + return; + } + ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", ReqList->InterfaceType); + ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber); + ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber); + ok(ReqList->AlternativeLists == 2, "AlternativeLists = %lu\n", ReqList->AlternativeLists); + ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", ReqList->List[0].Version); + ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", ReqList->List[0].Revision); + ok(ReqList->List[0].Count == 6, "List[0].Count = %lu\n", ReqList->List[0].Count); + expect_port(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, CmResourceShareDriverExclusive, 8, 8, 0x3E8, 0x3EF); + expect_irq(&ReqList->List[0].Descriptors[1], IO_RESOURCE_PREFERRED, CmResourceShareDeviceExclusive, 3, 3); + expect_irq(&ReqList->List[0].Descriptors[2], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 4, 4); + expect_irq(&ReqList->List[0].Descriptors[3], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 5, 5); + expect_irq(&ReqList->List[0].Descriptors[4], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 6, 6); + expect_irq(&ReqList->List[0].Descriptors[5], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 7, 7); + ReqList2 = (PVOID)&ReqList->List[0].Descriptors[6]; + if (ReqList->ListSize > (ULONG_PTR)ReqList2 - (ULONG_PTR)ReqList) + { + ok(ReqList2->Version == 1, "List[1].Version = %u\n", ReqList->List[0].Version); + ok(ReqList2->Revision == 1, "List[1].Revision = %u\n", ReqList->List[0].Revision); + ok(ReqList2->Count == 6, "List[1].Count = %lu\n", ReqList->List[0].Count); + expect_port(&ReqList2->Descriptors[0], IO_RESOURCE_PREFERRED, CmResourceShareDriverExclusive, 8, 8, 0x2E8, 0x2EF); + expect_irq(&ReqList2->Descriptors[1], IO_RESOURCE_PREFERRED, CmResourceShareDeviceExclusive, 3, 3); + expect_irq(&ReqList2->Descriptors[2], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 4, 4); + expect_irq(&ReqList2->Descriptors[3], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 5, 5); + expect_irq(&ReqList2->Descriptors[4], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 6, 6); + expect_irq(&ReqList2->Descriptors[5], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 7, 7); + } + ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList)); + ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList2->Descriptors[6] - (ULONG_PTR)ReqList); + ExFreePoolWithTag(ReqList, 'RpcA'); +} diff --git a/modules/rostests/apitests/acpi/CMakeLists.txt b/modules/rostests/apitests/acpi/CMakeLists.txt new file mode 100644 index 00000000000..8092262c0ff --- /dev/null +++ b/modules/rostests/apitests/acpi/CMakeLists.txt @@ -0,0 +1,12 @@ + +include_directories(${REACTOS_SOURCE_DIR}/drivers/bus/acpi/acpica/include) + +list(APPEND SOURCE + Bus_PDO_QueryResourceRequirements.c + testlist.c) + +add_executable(acpi_apitest ${SOURCE}) +set_module_type(acpi_apitest win32cui) +add_importlibs(acpi_apitest msvcrt kernel32 ntdll) + +add_rostests_file(TARGET acpi_apitest) diff --git a/modules/rostests/apitests/acpi/testlist.c b/modules/rostests/apitests/acpi/testlist.c new file mode 100644 index 00000000000..e5fb3bc6e41 --- /dev/null +++ b/modules/rostests/apitests/acpi/testlist.c @@ -0,0 +1,10 @@ +#define STANDALONE +#include + +extern void func_Bus_PDO_QueryResourceRequirements(void); + +const struct test winetest_testlist[] = +{ + { "Bus_PDO_QueryResourceRequirements", func_Bus_PDO_QueryResourceRequirements }, + { 0, 0 } +};