[ISAPNP_UNITTEST] Add unit tests exercising device discovery and device resources functionality

CORE-18562
This commit is contained in:
Dmitry Borisov 2024-05-03 19:09:23 +06:00
parent 016d01e5d1
commit b36d9bd9c1
10 changed files with 2863 additions and 0 deletions

View file

@ -7,6 +7,8 @@
* Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
*/
#ifndef UNIT_TEST
#include "isapnp.h"
#define NDEBUG
@ -16,6 +18,8 @@
#pragma warning(disable:28138) /* ISA bus always uses hardcoded port addresses */
#endif
#endif /* UNIT_TEST */
typedef enum
{
dfNotStarted,
@ -1517,6 +1521,7 @@ IsaHwFillDeviceList(
{
BOOLEAN IsAlreadyEnumerated = FALSE;
#ifndef UNIT_TEST
for (Entry = FdoExt->DeviceListHead.Flink;
Entry != &FdoExt->DeviceListHead;
Entry = Entry->Flink)
@ -1547,6 +1552,7 @@ IsaHwFillDeviceList(
break;
}
}
#endif /* UNIT_TEST */
if (IsAlreadyEnumerated)
continue;
@ -1720,6 +1726,7 @@ IsaHwActivateDevice(
ActivateDevice(FdoExt->ReadDataPort, LogicalDevice->LDN);
}
#ifndef UNIT_TEST
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
IsaHwDeactivateDevice(
@ -1727,6 +1734,7 @@ IsaHwDeactivateDevice(
{
DeactivateDevice(LogicalDevice->LDN);
}
#endif /* UNIT_TEST */
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID

View file

@ -9,10 +9,14 @@
/* INCLUDES *******************************************************************/
#ifndef UNIT_TEST
#include "isapnp.h"
#endif /* UNIT_TEST */
#include <search.h>
#ifndef UNIT_TEST
#define NDEBUG
#include <debug.h>
@ -26,6 +30,8 @@ BOOLEAN ReadPortCreated = FALSE;
_Guarded_by_(BusSyncEvent)
LIST_ENTRY BusListHead;
#endif /* UNIT_TEST */
static PUCHAR Priority;
/* FUNCTIONS ******************************************************************/
@ -1166,6 +1172,8 @@ IsaPnpCreateReadPortDOResources(VOID)
return ResourceList;
}
#ifndef UNIT_TEST
static
CODE_SEG("PAGE")
NTSTATUS
@ -1604,4 +1612,6 @@ DriverEntry(
return STATUS_SUCCESS;
}
#endif /* UNIT_TEST */
/* EOF */

View file

@ -1 +1,5 @@
if(ISAPNP_ENABLE)
add_subdirectory(isapnp)
endif()
add_subdirectory(setuplib)

View file

@ -0,0 +1,23 @@
include_directories(
${REACTOS_SOURCE_DIR}/modules/rostests/apitests/include
${REACTOS_SOURCE_DIR}/drivers/bus/isapnp)
list(APPEND SOURCE
empty_card.c
isabus.c
res_card.c
tests.c)
list(APPEND PCH_SKIP_SOURCE
testlist.c)
add_executable(isapnp_unittest
${SOURCE}
${PCH_SKIP_SOURCE})
set_module_type(isapnp_unittest win32cui)
add_importlibs(isapnp_unittest msvcrt kernel32 ntdll)
add_pch(isapnp_unittest precomp.h "${PCH_SKIP_SOURCE}")
add_rostests_file(TARGET isapnp_unittest)

View file

@ -0,0 +1,60 @@
/*
* PROJECT: ReactOS API Tests
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Dummy card resource tests for the ISA PnP bus driver
* COPYRIGHT: Copyright 2024 Dmitry Borisov <di.sean@protonmail.com>
*/
/* INCLUDES *******************************************************************/
#include "precomp.h"
/* GLOBALS ********************************************************************/
static UCHAR DrvpTestPnpRom[] =
{
0x49, 0xF3, // Vendor ID 0xF349 'ROS'
0x55, 0x66, // Product ID 0x5566
0xFF, 0xFF, 0xFF, 0xFF, // Serial Number
0xFF, // Checksum (dummy)
0x0A, 0x10, 0x10, // PnP version 1.0, vendor version 1.0
0x82, 6, 0x00, // ANSI identifier 'Test 2'
'T', 'e', 's', 't', ' ', '2',
/* ********************* DEVICE 1 ********************* */
0x15, // Logical device ID
0x24, 0x08, // Vendor ID 0x0824 'BAD'
0x30, 0x00, // Product ID 0x3000
0x00,
0x82, 0xCC, 0xCC, // Long ANSI identifier to verify resource data bounds checking
/* **************************************************** */
0x79, // END
0xFF, // Checksum (dummy)
};
/* FUNCTIONS ******************************************************************/
VOID
DrvCreateCard2(
_In_ PISAPNP_CARD Card)
{
PISAPNP_CARD_LOGICAL_DEVICE LogDev;
IsaBusCreateCard(Card, DrvpTestPnpRom, sizeof(DrvpTestPnpRom), 1);
/* ********************* DEVICE 1 ********************* */
LogDev = &Card->LogDev[0];
/* Enable decodes */
LogDev->Registers[0x30] = 0x01;
/* No DMA is active */
LogDev->Registers[0x74] = 0x04;
LogDev->Registers[0x75] = 0x04;
}

View file

@ -0,0 +1,508 @@
/*
* PROJECT: ReactOS API Tests
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: ISA PnP bus register access helpers
* COPYRIGHT: Copyright 2024 Dmitry Borisov <di.sean@protonmail.com>
*/
/* INCLUDES *******************************************************************/
#include "precomp.h"
/* GLOBALS ********************************************************************/
PISAPNP_CARD IsapCard;
static PISAPNP_CARD IsapConfigureCard = NULL;
static ULONG IsapCardCount = 0;
static UCHAR IsapAddressLatch = 0;
/* PRIVATE FUNCTIONS **********************************************************/
static
inline
UCHAR
IsaBusNextLFSR(
_In_ UCHAR Lfsr,
_In_ UCHAR InputBit)
{
UCHAR NextLfsr = Lfsr >> 1;
NextLfsr |= (((Lfsr ^ NextLfsr) ^ InputBit)) << 7;
return NextLfsr;
}
static
VOID
IsaBusWriteAddressRegister(
_In_ UCHAR Value)
{
ULONG i;
IsapAddressLatch = Value;
for (i = 0; i < IsapCardCount; ++i)
{
PISAPNP_CARD Card = &IsapCard[i];
if (Card->State != IsaWaitForKey)
continue;
/* Reset the LFSR contents */
if (Card->Lfsr != Value)
{
Card->Lfsr = ISAPNP_LFSR_SEED;
Card->LfsrCount = 0;
continue;
}
/* Generate the next data pattern */
Card->Lfsr = IsaBusNextLFSR(Card->Lfsr, 0);
/* 32 bytes of the initiation key compared correctly */
if (++Card->LfsrCount == 32)
{
Card->State = IsaSleep;
}
}
}
static
VOID
IsaBusWriteDataRegister(
_In_ UCHAR Value)
{
ULONG i, j;
switch (IsapAddressLatch)
{
case ISAPNP_READPORT:
{
/* Update the address of the Read Data Port */
for (i = 0; i < IsapCardCount; ++i)
{
PISAPNP_CARD Card = &IsapCard[i];
if (Card->State != IsaIsolation)
continue;
Card->ReadDataPort = (PUCHAR)(((ULONG_PTR)Value << 2) | 3);
}
break;
}
case ISAPNP_CONFIGCONTROL:
{
if (Value & ISAPNP_CONFIG_WAIT_FOR_KEY)
{
IsapConfigureCard = NULL;
}
for (i = 0; i < IsapCardCount; ++i)
{
PISAPNP_CARD Card = &IsapCard[i];
if (Card->State != IsaWaitForKey)
{
if (Value & ISAPNP_CONFIG_RESET)
{
for (j = 0; j < Card->LogicalDevices; ++j)
{
PISAPNP_CARD_LOGICAL_DEVICE LogDev = &Card->LogDev[j];
LogDev->Registers[ISAPNP_ACTIVATE] = 0;
}
}
if (Value & ISAPNP_CONFIG_RESET_CSN)
{
Card->SelectNumberReg = 0;
}
}
if (Value & ISAPNP_CONFIG_WAIT_FOR_KEY)
{
Card->State = IsaWaitForKey;
}
}
break;
}
case ISAPNP_WAKE:
{
for (i = 0; i < IsapCardCount; ++i)
{
PISAPNP_CARD Card = &IsapCard[i];
if (Card->State == IsaWaitForKey)
continue;
if (Card->SelectNumberReg != Value)
{
if (Card->State == IsaConfgure || Card->State == IsaIsolation)
{
Card->State = IsaSleep;
if (IsapConfigureCard == Card)
{
IsapConfigureCard = NULL;
}
}
continue;
}
Card->RomIdx = 0;
Card->SerialIsolationIdx = 0;
if (Card->State == IsaSleep)
{
if (Value == 0)
{
Card->State = IsaIsolation;
Card->IsolationRead = 0;
}
else
{
Card->State = IsaConfgure;
/* Only one card can be in the configure state */
IsapConfigureCard = Card;
}
}
}
break;
}
case ISAPNP_CARDSELECTNUMBER:
{
ULONG CsnAssigned = 0;
/* Assign the CSN */
for (i = 0; i < IsapCardCount; ++i)
{
PISAPNP_CARD Card = &IsapCard[i];
if (Card->State != IsaIsolation)
continue;
ok(Value != 0, "The new CSN is zero\n");
ok(Card->SelectNumberReg != Value, "CSNs must be assigned sequentially");
Card->State = IsaConfgure;
Card->SelectNumberReg = Value;
/* Only one card can be in the configure state */
IsapConfigureCard = Card;
++CsnAssigned;
ok_eq_ulong(CsnAssigned, 1UL);
}
break;
}
case ISAPNP_LOGICALDEVICENUMBER:
{
ok(IsapConfigureCard != NULL, "Invalid write to a LDN register\n");
if (IsapConfigureCard != NULL)
{
ok(IsapConfigureCard->LogicalDevices != 0, "Write to a read-only register\n");
ok(Value < IsapConfigureCard->LogicalDevices, "Invalid write to a LDN register\n");
IsapConfigureCard->DeviceNumberReg = Value;
}
break;
}
case ISAPNP_ACTIVATE:
{
Value &= 0x01;
goto WriteDeviceRegister;
}
case ISAPNP_IORANGECHECK:
{
Value &= 0x03;
goto WriteDeviceRegister;
}
case ISAPNP_SERIALISOLATION:
case ISAPNP_RESOURCEDATA:
case ISAPNP_STATUS:
{
ok(FALSE, "Write to a read-only register %02x\n", IsapAddressLatch);
break;
}
default:
{
if (IsapAddressLatch >= 0x40)
{
PISAPNP_CARD_LOGICAL_DEVICE LogDev;
WriteDeviceRegister:
ok(IsapConfigureCard != NULL, "Invalid write to device register\n");
if (IsapConfigureCard != NULL)
{
LogDev = &IsapConfigureCard->LogDev[IsapConfigureCard->DeviceNumberReg];
LogDev->Registers[IsapAddressLatch] = Value;
}
}
else
{
ok(FALSE, "Unexpected write to register %02x\n", IsapAddressLatch);
}
break;
}
}
}
static
UCHAR
IsaBusReadSerialIsolationRegister(
_In_ PUCHAR Port)
{
ULONG i, ResponseMap = 0, ListenMap = 0;
UCHAR Result = 0xFF;
for (i = 0; i < IsapCardCount; ++i)
{
PISAPNP_CARD Card = &IsapCard[i];
if (Card->State != IsaIsolation || Card->ReadDataPort != Port)
continue;
/* The hardware on each card expects 72 pairs of reads */
if (Card->SerialIsolationIdx == RTL_BITS_OF(ISAPNP_IDENTIFIER))
continue;
Card->IsolationRead ^= 1;
if (Card->IsolationRead)
{
if (Card->PnpRom[Card->SerialIsolationIdx / 8] & (1 << (Card->SerialIsolationIdx % 8)))
Card->SerialIdResponse = 0x55;
else
Card->SerialIdResponse = 0x00;
++Card->RomIdx;
++Card->SerialIsolationIdx;
}
else
{
Card->SerialIdResponse <<= 1;
if (Card->SerialIdResponse == 0xAA)
ResponseMap |= (1 << i);
else
ListenMap |= (1 << i);
}
if ((Card->SerialIdResponse > Result) || (Result == 0xFF))
Result = Card->SerialIdResponse;
}
/* Release passive cards from the isolation state */
if (ResponseMap != 0 && ListenMap != 0)
{
for (i = 0; i < RTL_BITS_OF(ListenMap); ++i)
{
if (ListenMap & (1 << i))
{
PISAPNP_CARD Card = &IsapCard[i];
Card->State = IsaSleep;
}
}
}
return Result;
}
static
UCHAR
IsaBusReadDataPortRegister(
_In_ PUCHAR Port)
{
if (IsapAddressLatch == ISAPNP_SERIALISOLATION)
return IsaBusReadSerialIsolationRegister(Port);
if (IsapConfigureCard == NULL || IsapConfigureCard->ReadDataPort != Port)
return 0xFF;
switch (IsapAddressLatch)
{
case ISAPNP_RESOURCEDATA:
{
if (IsapConfigureCard->RomIdx >= IsapConfigureCard->RomSize)
break;
/* The resource data register may return an invalid identifier checksum byte */
if (IsapConfigureCard->RomIdx == FIELD_OFFSET(ISAPNP_IDENTIFIER, Checksum))
{
++IsapConfigureCard->RomIdx;
break;
}
return IsapConfigureCard->PnpRom[IsapConfigureCard->RomIdx++];
}
case ISAPNP_STATUS:
return 0x01; /* Resource data byte available */
case ISAPNP_CARDSELECTNUMBER:
return IsapConfigureCard->SelectNumberReg;
case ISAPNP_LOGICALDEVICENUMBER:
return IsapConfigureCard->DeviceNumberReg;
case ISAPNP_ACTIVATE:
case ISAPNP_IORANGECHECK:
goto ReadDeviceRegister;
default:
{
if (IsapAddressLatch >= 0x40)
{
PISAPNP_CARD_LOGICAL_DEVICE LogDev;
ReadDeviceRegister:
LogDev = &IsapConfigureCard->LogDev[IsapConfigureCard->DeviceNumberReg];
return LogDev->Registers[IsapAddressLatch];
}
else
{
ok(FALSE, "Unexpected read from register %02x\n", IsapAddressLatch);
}
break;
}
}
return 0xFF;
}
static
UCHAR
IsaBusPnpChecksum(
_In_ PISAPNP_IDENTIFIER Identifier)
{
UCHAR i, j, Lfsr;
Lfsr = ISAPNP_LFSR_SEED;
for (i = 0; i < FIELD_OFFSET(ISAPNP_IDENTIFIER, Checksum); ++i)
{
UCHAR Byte = ((PUCHAR)Identifier)[i];
for (j = 0; j < RTL_BITS_OF(Byte); ++j)
{
Lfsr = IsaBusNextLFSR(Lfsr, Byte);
Byte >>= 1;
}
}
return Lfsr;
}
static
UCHAR
IsaBusResourceDataChecksum(
_In_ PUCHAR PnpRom,
_In_ ULONG RomSize)
{
UNREFERENCED_PARAMETER(PnpRom);
UNREFERENCED_PARAMETER(RomSize);
/* This means "Checksummed properly" */
return 0x00;
}
static
VOID
IsaBusPlugInCard(
_Inout_ PISAPNP_CARD Card)
{
Card->State = IsaWaitForKey;
Card->Lfsr = ISAPNP_LFSR_SEED;
Card->LfsrCount = 0;
Card->SelectNumberReg = 0;
Card->ReadDataPort = NULL;
}
/* PUBLIC FUNCTIONS ***********************************************************/
VOID
IsaBusCreateCard(
_Inout_ PISAPNP_CARD Card,
_In_ PVOID PnpRom,
_In_ ULONG RomSize,
_In_ ULONG LogicalDevices)
{
Card->RomSize = RomSize;
Card->PnpRom = PnpRom;
Card->PnpRom[FIELD_OFFSET(ISAPNP_IDENTIFIER, Checksum)] = IsaBusPnpChecksum(PnpRom);
Card->PnpRom[RomSize - 1] = IsaBusResourceDataChecksum(PnpRom, RomSize);
Card->LogicalDevices = LogicalDevices;
IsaBusPlugInCard(Card);
++IsapCardCount;
}
VOID
NTAPI
WRITE_PORT_UCHAR(
_In_ PUCHAR Port,
_In_ UCHAR Value)
{
switch ((ULONG_PTR)Port)
{
case 0x279:
IsaBusWriteAddressRegister(Value);
break;
case 0xA79:
IsaBusWriteDataRegister(Value);
break;
default:
ok(FALSE, "Unexpected write to port %p %02x\n", Port, Value);
break;
}
}
UCHAR
NTAPI
READ_PORT_UCHAR(
_In_ PUCHAR Port)
{
UCHAR Result;
/* We can write only to NT Read Data Ports */
switch ((ULONG_PTR)Port)
{
case 0x2F4 | 3:
Result = IsaBusReadDataPortRegister(Port);
break;
/* Indicate that the Read Data Port is in conflict */
case 0x274 | 3:
case 0x3E4 | 3:
case 0x204 | 3:
case 0x2E4 | 3:
case 0x354 | 3:
Result = 0x00;
break;
default:
ok(FALSE, "Unexpected read from port %p\n", Port);
Result = 0xFF;
break;
}
return Result;
}

View file

@ -0,0 +1,409 @@
/*
* PROJECT: ReactOS API Tests
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Precompiled header for isapnp_unittest
* COPYRIGHT: Copyright 2024 Dmitry Borisov <di.sean@protonmail.com>
*/
#pragma once
#include <apitest.h>
#define WIN32_NO_STATUS
#include <ndk/rtlfuncs.h>
typedef PVOID PDEVICE_OBJECT;
#define UNIT_TEST
#include <isapnphw.h>
#include <isapnpres.h>
/* KERNEL DEFINITIONS (MOCK) **************************************************/
#define PAGED_CODE()
#define CODE_SEG(segment)
#define DPRINT(...) do { if (0) { trace(__VA_ARGS__); } } while (0)
#define DPRINT1(...) do { if (0) { trace(__VA_ARGS__); } } while (0)
#define KeStallExecutionProcessor(MicroSeconds)
FORCEINLINE
PVOID
ExAllocatePoolWithTag(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
{
PULONG_PTR Mem = HeapAlloc(GetProcessHeap(), 0, NumberOfBytes + 2 * sizeof(PVOID));
if (Mem == NULL)
return NULL;
Mem[0] = NumberOfBytes;
Mem[1] = Tag;
return (PVOID)(Mem + 2);
}
FORCEINLINE
PVOID
ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
{
PVOID Result = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
if (Result != NULL)
RtlZeroMemory(Result, NumberOfBytes);
return Result;
}
FORCEINLINE
VOID
ExFreePoolWithTag(PVOID MemPtr, ULONG Tag)
{
PULONG_PTR Mem = MemPtr;
Mem -= 2;
ok(Mem[1] == Tag, "Tag is %lx, expected %lx\n", Tag, Mem[1]);
HeapFree(GetProcessHeap(), 0, Mem);
}
FORCEINLINE
SIZE_T
GetPoolAllocSize(PVOID MemPtr)
{
PVOID* Mem = MemPtr;
Mem -= 2;
return (SIZE_T)Mem[0];
}
/* ISAPNP DRIVER DEFINITIONS (MOCK) *******************************************/
#define TAG_ISAPNP 'pasI'
typedef struct _ISAPNP_FDO_EXTENSION
{
LIST_ENTRY DeviceListHead;
ULONG DeviceCount;
ULONG Cards;
PUCHAR ReadDataPort;
} ISAPNP_FDO_EXTENSION, *PISAPNP_FDO_EXTENSION;
typedef struct _ISAPNP_PDO_EXTENSION
{
PISAPNP_LOGICAL_DEVICE IsaPnpDevice;
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
PCM_RESOURCE_LIST ResourceList;
ULONG ResourceListSize;
} ISAPNP_PDO_EXTENSION, *PISAPNP_PDO_EXTENSION;
/* TEST DEFINITIONS ***********************************************************/
typedef enum _ISAPNP_STATE
{
IsaWaitForKey = 0,
IsaSleep = 1,
IsaIsolation = 2,
IsaConfgure = 3
} ISAPNP_STATE;
typedef struct _ISAPNP_CARD_LOGICAL_DEVICE
{
UCHAR Registers[0xFF];
} ISAPNP_CARD_LOGICAL_DEVICE, *PISAPNP_CARD_LOGICAL_DEVICE;
#define TEST_MAX_SUPPORTED_DEVICES 7
typedef struct _ISAPNP_CARD
{
ISAPNP_STATE State;
UCHAR LfsrCount;
UCHAR Lfsr;
UCHAR SelectNumberReg;
UCHAR DeviceNumberReg;
UCHAR SerialIsolationIdx;
UCHAR SerialIdResponse;
UCHAR IsolationRead;
PUCHAR PnpRom;
PUCHAR ReadDataPort;
ULONG RomIdx;
ULONG RomSize;
ULONG LogicalDevices;
ISAPNP_CARD_LOGICAL_DEVICE LogDev[TEST_MAX_SUPPORTED_DEVICES];
} ISAPNP_CARD, *PISAPNP_CARD;
UCHAR
NTAPI
READ_PORT_UCHAR(
_In_ PUCHAR Port);
VOID
NTAPI
WRITE_PORT_UCHAR(
_In_ PUCHAR Port,
_In_ UCHAR Value);
VOID
IsaBusCreateCard(
_Inout_ PISAPNP_CARD Card,
_In_ PVOID PnpRom,
_In_ ULONG RomSize,
_In_ ULONG LogicalDevices);
VOID
DrvCreateCard1(
_In_ PISAPNP_CARD Card);
VOID
DrvTestCard1Dev1Resources(
_In_ PCM_RESOURCE_LIST ResourceList,
_In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
VOID
DrvTestCard1Dev2Resources(
_In_ PCM_RESOURCE_LIST ResourceList,
_In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
VOID
DrvTestCard1Dev3Resources(
_In_ PCM_RESOURCE_LIST ResourceList,
_In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
VOID
DrvTestCard1Dev4Resources(
_In_ PCM_RESOURCE_LIST ResourceList,
_In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
VOID
DrvTestCard1Dev5Resources(
_In_ PCM_RESOURCE_LIST ResourceList,
_In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
VOID
DrvTestCard1Dev6Resources(
_In_ PCM_RESOURCE_LIST ResourceList,
_In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
VOID
DrvTestCard1Dev7Resources(
_In_ PCM_RESOURCE_LIST ResourceList,
_In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
PCM_RESOURCE_LIST
DrvTestCard1Dev6CreateConfigurationResources(VOID);
VOID
DrvTestCard1Dev6ConfigurationResult(
_In_ PISAPNP_CARD_LOGICAL_DEVICE LogDev);
VOID
DrvCreateCard2(
_In_ PISAPNP_CARD Card);
#define expect_resource_list_header(ResourceList, ExpectedIface, ExpectedCount) \
do { \
ok_eq_int((ResourceList)->List[0].InterfaceType, (ExpectedIface)); \
ok_eq_ulong((ResourceList)->List[0].BusNumber, 0UL); \
ok_eq_int((ResourceList)->List[0].PartialResourceList.Version, 1); /* 0 */ \
ok_eq_int((ResourceList)->List[0].PartialResourceList.Revision, 1); /* 0x3000 */ \
ok_eq_ulong((ResourceList)->List[0].PartialResourceList.Count, (ExpectedCount)); \
} while (0)
#define expect_requirements_list_header(ReqList, ExpectedIface, ExpectedCount) \
do { \
ok_eq_int((ReqList)->InterfaceType, (ExpectedIface)); \
ok_eq_ulong((ReqList)->BusNumber, 0UL); \
ok_eq_ulong((ReqList)->SlotNumber, 0UL); \
ok_eq_ulong((ReqList)->AlternativeLists, (ExpectedCount)); \
} while (0)
#define expect_alt_list_header(AltList, ExpectedCount) \
do { \
ok_eq_int((AltList)->Version, 1); \
ok_eq_int((AltList)->Revision, 1); \
ok_eq_ulong((AltList)->Count, (ExpectedCount)); \
} while (0)
#define expect_port_req(Desc, ExpectedOption, ExpectedFlags, ExpectedShare, \
ExpectedLength, ExpectedAlign, ExpectedMin, ExpectedMax) \
do { \
ok((Desc)->Type == CmResourceTypePort, \
"Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypePort); \
ok((Desc)->Option == (ExpectedOption), \
"Desc->Option = %u, expected %u\n", (Desc)->Option, (ExpectedOption)); \
ok((Desc)->Flags == (ExpectedFlags), \
"Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags)); \
ok((Desc)->ShareDisposition == (ExpectedShare), \
"Desc->ShareDisposition = %u, expected %u\n", \
(Desc)->ShareDisposition, (ExpectedShare)); \
ok((Desc)->u.Port.Length == (ExpectedLength), \
"Desc->u.Port.Length = %lx, expected %lx\n", \
(Desc)->u.Port.Length, (ExpectedLength)); \
ok((Desc)->u.Port.Alignment == (ExpectedAlign), \
"Desc->u.Port.Alignment = %lu, expected %lu\n", \
(Desc)->u.Port.Alignment, (ExpectedAlign)); \
ok((Desc)->u.Port.MinimumAddress.QuadPart == (ExpectedMin), \
"Desc->u.Port.MinimumAddress = 0x%I64x, expected 0x%I64x\n", \
(Desc)->u.Port.MinimumAddress.QuadPart, (ExpectedMin)); \
ok((Desc)->u.Port.MaximumAddress.QuadPart == (ExpectedMax), \
"Desc->u.Port.MaximumAddress = 0x%I64x, expected 0x%I64x\n", \
(Desc)->u.Port.MaximumAddress.QuadPart, (ExpectedMax)); \
} while (0)
#define expect_irq_req(Desc, ExpectedOption, ExpectedFlags, ExpectedShare, \
ExpectedMin, ExpectedMax) \
do { \
ok((Desc)->Type == CmResourceTypeInterrupt, \
"Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeInterrupt); \
ok((Desc)->Option == (ExpectedOption), \
"Desc->Option = %u, expected %u\n", (Desc)->Option, (ExpectedOption)); \
ok((Desc)->Flags == (ExpectedFlags), \
"Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags)); \
ok((Desc)->ShareDisposition == (ExpectedShare), \
"Desc->ShareDisposition = %u, expected %u\n", \
(Desc)->ShareDisposition, (ExpectedShare)); \
ok((Desc)->u.Interrupt.MinimumVector == (ExpectedMin), \
"Desc->u.Interrupt.MinimumVector = %lu, expected %lu\n", \
(Desc)->u.Interrupt.MinimumVector, (ExpectedMin)); \
ok((Desc)->u.Interrupt.MaximumVector == (ExpectedMax), \
"Desc->u.Interrupt.MaximumVector = %lu, expected %lu\n", \
(Desc)->u.Interrupt.MaximumVector, (ExpectedMax)); \
} while (0)
#define expect_dma_req(Desc, ExpectedOption, ExpectedFlags, ExpectedShare, \
ExpectedMin, ExpectedMax) \
do { \
ok((Desc)->Type == CmResourceTypeDma, \
"Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeDma); \
ok((Desc)->Option == (ExpectedOption), \
"Desc->Option = %u, expected %u\n", (Desc)->Option, (ExpectedOption)); \
ok((Desc)->Flags == (ExpectedFlags), \
"Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags)); \
ok((Desc)->ShareDisposition == (ExpectedShare), \
"Desc->ShareDisposition = %u, expected %u\n", \
(Desc)->ShareDisposition, (ExpectedShare)); \
ok((Desc)->u.Dma.MinimumChannel == (ExpectedMin), \
"Desc->u.Dma.MinimumChannel = %lu, expected %lu\n", \
(Desc)->u.Dma.MinimumChannel, (ExpectedMin)); \
ok((Desc)->u.Dma.MaximumChannel == (ExpectedMax), \
"Desc->u.Dma.MaximumChannel = %lu, expected %lu\n", \
(Desc)->u.Dma.MaximumChannel, (ExpectedMax)); \
} while (0)
#define expect_mem_req(Desc, ExpectedOption, ExpectedFlags, ExpectedShare, \
ExpectedLength, ExpectedAlign, ExpectedMin, ExpectedMax) \
do { \
ok((Desc)->Type == CmResourceTypeMemory, \
"Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeMemory); \
ok((Desc)->Option == (ExpectedOption), \
"Desc->Option = %u, expected %u\n", (Desc)->Option, (ExpectedOption)); \
ok((Desc)->Flags == (ExpectedFlags), \
"Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags)); \
ok((Desc)->ShareDisposition == (ExpectedShare), \
"Desc->ShareDisposition = %u, expected %u\n", \
(Desc)->ShareDisposition, (ExpectedShare)); \
ok((Desc)->u.Memory.Length == (ExpectedLength), \
"Desc->u.Memory.Length = %lx, expected %lx\n", \
(Desc)->u.Memory.Length, (ExpectedLength)); \
ok((Desc)->u.Memory.Alignment == (ExpectedAlign), \
"Desc->u.Memory.Alignment = %lx, expected %lx\n", \
(Desc)->u.Memory.Alignment, (ExpectedAlign)); \
ok((Desc)->u.Memory.MinimumAddress.QuadPart == (ExpectedMin), \
"Desc->u.Memory.MinimumAddress = 0x%I64x, expected 0x%I64x\n", \
(Desc)->u.Memory.MinimumAddress.QuadPart, (ExpectedMin)); \
ok((Desc)->u.Memory.MaximumAddress.QuadPart == (ExpectedMax), \
"Desc->u.Memory.MaximumAddress = 0x%I64x, expected 0x%I64x\n", \
(Desc)->u.Memory.MaximumAddress.QuadPart, (ExpectedMax)); \
} while (0)
#define expect_cfg_req(Desc, ExpectedOption, ExpectedFlags, ExpectedShare, \
ExpectedPriority, ExpectedRes1, ExpectedRes2) \
do { \
ok((Desc)->Type == CmResourceTypeConfigData, \
"Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeConfigData); \
ok((Desc)->Option == (ExpectedOption), \
"Desc->Option = %u, expected %u\n", (Desc)->Option, (ExpectedOption)); \
ok((Desc)->Flags == (ExpectedFlags), \
"Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags)); \
ok((Desc)->ShareDisposition == (ExpectedShare), \
"Desc->ShareDisposition = %u, expected %u\n", \
(Desc)->ShareDisposition, (ExpectedShare)); \
ok((Desc)->u.ConfigData.Priority == (ExpectedPriority), \
"Desc->u.ConfigData.Priority = %lx, expected %lx\n", \
(Desc)->u.ConfigData.Priority, (ExpectedPriority)); \
ok((Desc)->u.ConfigData.Reserved1 == (ExpectedRes1), \
"Desc->u.ConfigData.Reserved1 = %lx, expected %lx\n", \
(Desc)->u.ConfigData.Reserved2, (ExpectedRes1)); \
ok((Desc)->u.ConfigData.Reserved2 == (ExpectedRes2), \
"Desc->u.ConfigData.Reserved2 = %lx, expected %lx\n", \
(Desc)->u.ConfigData.Reserved2, (ExpectedRes2)); \
} while (0)
#define expect_port_res(Desc, ExpectedFlags, ExpectedShare, ExpectedLength, ExpectedStart) \
do { \
ok((Desc)->Type == CmResourceTypePort, \
"Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypePort); \
ok((Desc)->Flags == (ExpectedFlags), \
"Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags)); \
ok((Desc)->ShareDisposition == (ExpectedShare), \
"Desc->ShareDisposition = %u, expected %u\n", \
(Desc)->ShareDisposition, (ExpectedShare)); \
ok((Desc)->u.Port.Length == (ExpectedLength), \
"Desc->u.Port.Length = %lx, expected %lx\n", \
(Desc)->u.Port.Length, (ExpectedLength)); \
ok((Desc)->u.Port.Start.QuadPart == (ExpectedStart), \
"Desc->u.Port.Start = 0x%I64x, expected 0x%I64x\n", \
(Desc)->u.Port.Start.QuadPart, (ExpectedStart)); \
} while (0)
#define expect_irq_res(Desc, ExpectedFlags, ExpectedShare, \
ExpectedLevel, ExpectedVector, ExpectedAffinity) \
do { \
ok((Desc)->Type == CmResourceTypeInterrupt, \
"Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeInterrupt); \
ok((Desc)->Flags == (ExpectedFlags), \
"Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags)); \
ok((Desc)->ShareDisposition == (ExpectedShare), \
"Desc->ShareDisposition = %u, expected %u\n", \
(Desc)->ShareDisposition, (ExpectedShare)); \
ok((Desc)->u.Interrupt.Level == (ExpectedLevel), \
"Desc->u.Interrupt.Level = %lu\n", (Desc)->u.Interrupt.Level); \
ok((Desc)->u.Interrupt.Vector == (ExpectedVector), \
"Desc->u.Interrupt.Vector = %lu\n", (Desc)->u.Interrupt.Vector); \
ok((Desc)->u.Interrupt.Affinity == (ExpectedAffinity), \
"Desc->u.Interrupt.Affinity = %Ix\n", (Desc)->u.Interrupt.Affinity); \
} while (0)
#define expect_dma_res(Desc, ExpectedFlags, ExpectedShare, ExpectedChannel) \
do { \
ok((Desc)->Type == CmResourceTypeDma, \
"Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeDma); \
ok((Desc)->Flags == (ExpectedFlags), \
"Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags)); \
ok((Desc)->ShareDisposition == (ExpectedShare), \
"Desc->ShareDisposition = %u, expected %u\n", \
(Desc)->ShareDisposition, (ExpectedShare)); \
ok((Desc)->u.Dma.Channel == (ExpectedChannel), \
"Desc->u.Dma.Channel = %lu, expected %lu\n", \
(Desc)->u.Dma.Channel, (ExpectedChannel)); \
ok((Desc)->u.Dma.Port == 0ul, \
"Desc->u.Dma.Port = %lu, expected %lu\n", \
(Desc)->u.Dma.Port, 0ul); \
ok((Desc)->u.Dma.Reserved1 == 0ul, \
"Desc->u.Dma.Reserved1 = %lx, expected 0\n", (Desc)->u.Dma.Reserved1); \
} while (0)
#define expect_mem_res(Desc, ExpectedFlags, ExpectedShare, ExpectedLength, ExpectedStart) \
do { \
ok((Desc)->Type == CmResourceTypeMemory, \
"Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeMemory); \
ok((Desc)->Flags == (ExpectedFlags), \
"Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags)); \
ok((Desc)->ShareDisposition == (ExpectedShare), \
"Desc->ShareDisposition = %u, expected %u\n", \
(Desc)->ShareDisposition, (ExpectedShare)); \
ok((Desc)->u.Memory.Length == (ExpectedLength), \
"Desc->u.Memory.Length = %lx, expected %lx\n", \
(Desc)->u.Memory.Length, (ExpectedLength)); \
ok((Desc)->u.Memory.Start.QuadPart == (ExpectedStart), \
"Desc->u.Memory.Start = 0x%I64x, expected 0x%I64x\n", \
(Desc)->u.Memory.Start.QuadPart, (ExpectedStart)); \
} while (0)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,17 @@
/*
* PROJECT: ReactOS API Tests
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Test list for the ISA PnP bus driver
* COPYRIGHT: Copyright 2024 Dmitry Borisov <di.sean@protonmail.com>
*/
#define STANDALONE
#include <apitest.h>
extern void func_Resources(void);
const struct test winetest_testlist[] =
{
{ "Resources", func_Resources },
{ 0, 0 }
};

View file

@ -0,0 +1,486 @@
/*
* PROJECT: ReactOS API Tests
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Unit Tests for the ISA PnP bus driver (device discovery and resource tests)
* COPYRIGHT: Copyright 2024 Dmitry Borisov <di.sean@protonmail.com>
*/
/* INCLUDES *******************************************************************/
#include "precomp.h"
#include "../../../../drivers/bus/isapnp/isapnp.c"
#include "../../../../drivers/bus/isapnp/hardware.c"
/* GLOBALS ********************************************************************/
static const ULONG DrvpIsaBusPorts[] = { 0xA79, 0x279 };
static const ULONG DrvpIsaBusReadDataPorts[] = { 0x274, 0x3E4, 0x204, 0x2E4, 0x354, 0x2F4 };
extern PISAPNP_CARD IsapCard;
#define TEST_RDP_IO_BASE ((PUCHAR)(0x2F4 | 3))
/* FUNCTIONS ******************************************************************/
static
VOID
DrvFlushDeviceConfig(
_In_ PISAPNP_CARD_LOGICAL_DEVICE LogDev)
{
UCHAR MemControl[8];
/*
* Save the memory control registers
* since we would need the correct values for the configuration process.
*/
MemControl[0] = LogDev->Registers[0x42];
MemControl[1] = LogDev->Registers[0x4A];
MemControl[2] = LogDev->Registers[0x52];
MemControl[3] = LogDev->Registers[0x5A];
MemControl[4] = LogDev->Registers[0x7A];
MemControl[5] = LogDev->Registers[0x84];
MemControl[6] = LogDev->Registers[0x94];
MemControl[7] = LogDev->Registers[0xA4];
/* Fill the whole configuration area with 0xCC for testing purposes */
RtlFillMemory(&LogDev->Registers[0x40], sizeof(LogDev->Registers) - 0x40, 0xCC);
/* Restore saved registers */
LogDev->Registers[0x42] = MemControl[0];
LogDev->Registers[0x4A] = MemControl[1];
LogDev->Registers[0x52] = MemControl[2];
LogDev->Registers[0x5A] = MemControl[3];
LogDev->Registers[0x7A] = MemControl[4];
LogDev->Registers[0x84] = MemControl[5];
LogDev->Registers[0x94] = MemControl[6];
LogDev->Registers[0xA4] = MemControl[7];
}
static
BOOLEAN
DrvCreateCards(VOID)
{
PISAPNP_CARD Card;
/* Create 2 cards */
IsapCard = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*IsapCard) * 2);
if (!IsapCard)
return FALSE;
Card = IsapCard;
DrvCreateCard1(Card++);
DrvCreateCard2(Card++);
return TRUE;
}
static
BOOLEAN
DrvTestIsolation(VOID)
{
UCHAR Cards;
/* Run the isolation protocol on an empty bus */
Cards = IsaHwTryReadDataPort(TEST_RDP_IO_BASE);
ok_eq_int(Cards, 0);
IsaHwWaitForKey();
if (!DrvCreateCards())
{
skip("No memory\n");
return FALSE;
}
/* Another bus that contains 2 cards */
Cards = IsaHwTryReadDataPort(TEST_RDP_IO_BASE);
ok_eq_int(Cards, 2);
return TRUE;
}
static
VOID
DrvTestResources(VOID)
{
ISAPNP_FDO_EXTENSION FdoExt = { 0 };
PISAPNP_CARD_LOGICAL_DEVICE LogDev;
PLIST_ENTRY Entry;
ULONG i;
/* Our cards were isolated via DrvTestIsolation() */
FdoExt.Cards = 2;
FdoExt.ReadDataPort = TEST_RDP_IO_BASE;
InitializeListHead(&FdoExt.DeviceListHead);
/* Enumerate all logical devices on the bus */
IsaHwFillDeviceList(&FdoExt);
IsaHwWaitForKey();
for (Entry = FdoExt.DeviceListHead.Flink, i = 0;
Entry != &FdoExt.DeviceListHead;
Entry = Entry->Flink)
{
ISAPNP_PDO_EXTENSION PdoExt = { 0 };
PCM_RESOURCE_LIST ResourceList;
PIO_RESOURCE_REQUIREMENTS_LIST ReqList;
PdoExt.IsaPnpDevice = CONTAINING_RECORD(Entry, ISAPNP_LOGICAL_DEVICE, DeviceLink);
/* Create the resource lists */
IsaPnpCreateLogicalDeviceRequirements(&PdoExt);
IsaPnpCreateLogicalDeviceResources(&PdoExt);
ReqList = PdoExt.RequirementsList;
ResourceList = PdoExt.ResourceList;
/* Process each discovered logical device */
switch (i++)
{
case 0:
{
DrvTestCard1Dev1Resources(ResourceList, ReqList);
LogDev = &IsapCard[0].LogDev[0];
ok_eq_int(LogDev->Registers[0x30], 0x00);
break;
}
case 1:
{
DrvTestCard1Dev2Resources(ResourceList, ReqList);
LogDev = &IsapCard[0].LogDev[1];
ok_eq_int(LogDev->Registers[0x30], 0x00);
break;
}
case 2:
{
DrvTestCard1Dev3Resources(ResourceList, ReqList);
LogDev = &IsapCard[0].LogDev[2];
ok_eq_int(LogDev->Registers[0x30], 0x00);
break;
}
case 3:
{
DrvTestCard1Dev4Resources(ResourceList, ReqList);
LogDev = &IsapCard[0].LogDev[3];
ok_eq_int(LogDev->Registers[0x30], 0x00);
break;
}
case 4:
{
DrvTestCard1Dev5Resources(ResourceList, ReqList);
LogDev = &IsapCard[0].LogDev[4];
ok_eq_int(LogDev->Registers[0x30], 0x00);
break;
}
case 5:
{
DrvTestCard1Dev6Resources(ResourceList, ReqList);
/* Card 1, logical device 6 */
LogDev = &IsapCard[0].LogDev[5];
/* Should be activated only after configuration */
ok_eq_int(LogDev->Registers[0x30], 0x00);
/* I/O configuration test */
{
NTSTATUS Status;
DrvFlushDeviceConfig(LogDev);
/* Assume that this device comes up with I/O range check logic enabled */
LogDev->Registers[0x31] = 0x02;
/* Create new resources */
ResourceList = DrvTestCard1Dev6CreateConfigurationResources();
if (ResourceList == NULL)
{
skip("No ResourceList\n");
break;
}
/* Assign resources to the device */
{
IsaHwWakeDevice(PdoExt.IsaPnpDevice);
Status = IsaHwConfigureDevice(&FdoExt, PdoExt.IsaPnpDevice, ResourceList);
ok_eq_hex(Status, STATUS_SUCCESS);
IsaHwActivateDevice(&FdoExt, PdoExt.IsaPnpDevice);
IsaHwWaitForKey();
}
DrvTestCard1Dev6ConfigurationResult(LogDev);
/* I/O range check must be disabled */
ok_eq_int(LogDev->Registers[0x31], 0x00);
/* Verify device activation */
ok_eq_int(LogDev->Registers[0x30], 0x01);
}
break;
}
case 6:
{
DrvTestCard1Dev7Resources(ResourceList, ReqList);
LogDev = &IsapCard[0].LogDev[6];
ok_eq_int(LogDev->Registers[0x30], 0x00);
break;
}
default:
break;
}
}
ok(i == 7, "Some devices not tested\n");
}
/*
* FullList Count 1
* List #0 Iface 0 Bus #0 Ver.0 Rev.3000 Count 2
* [1:10] IO: Start 0:A79, Len 1
* [1:10] IO: Start 0:279, Len 1
*/
static
VOID
DrvTestReadDataPortQueryResources(VOID)
{
PCM_RESOURCE_LIST ResourceList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
ULONG i;
ResourceList = IsaPnpCreateReadPortDOResources();
ok(ResourceList != NULL, "ResourceList is NULL\n");
if (ResourceList == NULL)
{
skip("No ResourceList\n");
return;
}
expect_resource_list_header(ResourceList, Internal, 2UL);
Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0];
for (i = 0; i < RTL_NUMBER_OF(DrvpIsaBusPorts); ++i)
{
expect_port_res(Descriptor,
CM_RESOURCE_PORT_16_BIT_DECODE,
CmResourceShareDeviceExclusive,
1ul,
(ULONG64)DrvpIsaBusPorts[i]);
Descriptor++;
}
/*********************************************************/
ok_eq_size(GetPoolAllocSize(ResourceList), (ULONG_PTR)Descriptor - (ULONG_PTR)ResourceList);
}
/*
* Interface 0 Bus 0 Slot 0 AlternativeLists 1
*
* AltList, AltList->Count 10 Ver.1 Rev.1
* [0:1:10] IO: Min 0:A79, Max 0:A79, Align 1 Len 1
* [8:1:10] IO: Min 0:0, Max 0:0, Align 1 Len 0
* [0:1:10] IO: Min 0:279, Max 0:279, Align 1 Len 1
* [8:1:10] IO: Min 0:0, Max 0:0, Align 1 Len 0
* [0:1:10] IO: Min 0:274, Max 0:277, Align 1 Len 4
* [8:1:10] IO: Min 0:0, Max 0:0, Align 1 Len 0
* [0:1:10] IO: Min 0:3E4, Max 0:3E7, Align 1 Len 4
* [8:1:10] IO: Min 0:0, Max 0:0, Align 1 Len 0
* [0:1:10] IO: Min 0:204, Max 0:207, Align 1 Len 4
* [8:1:10] IO: Min 0:0, Max 0:0, Align 1 Len 0
* [0:1:10] IO: Min 0:2E4, Max 0:2E7, Align 1 Len 4
* [8:1:10] IO: Min 0:0, Max 0:0, Align 1 Len 0
* [0:1:10] IO: Min 0:354, Max 0:357, Align 1 Len 4
* [8:1:10] IO: Min 0:0, Max 0:0, Align 1 Len 0
* [0:1:10] IO: Min 0:2F4, Max 0:2F7, Align 1 Len 4
* [8:1:10] IO: Min 0:0, Max 0:0, Align 1 Len 0
*/
static
VOID
DrvTestReadDataPortQueryResourcesRequirementsForEnum(VOID)
{
PIO_RESOURCE_REQUIREMENTS_LIST ReqList;
PIO_RESOURCE_DESCRIPTOR Descriptor;
ULONG i;
ReqList = IsaPnpCreateReadPortDORequirements(0);
ok(ReqList != NULL, "ReqList is NULL\n");
if (ReqList == NULL)
{
skip("No ReqList\n");
return;
}
expect_requirements_list_header(ReqList, Internal, 1UL);
expect_alt_list_header(&ReqList->List[0], 16UL);
Descriptor = &ReqList->List[0].Descriptors[0];
for (i = 0; i < RTL_NUMBER_OF(DrvpIsaBusPorts) * 2; ++i)
{
if ((i % 2) == 0)
{
expect_port_req(Descriptor,
0,
CM_RESOURCE_PORT_16_BIT_DECODE,
CmResourceShareDeviceExclusive,
1ul,
1ul,
(ULONG64)DrvpIsaBusPorts[i / 2],
(ULONG64)DrvpIsaBusPorts[i / 2]);
}
else
{
expect_port_req(Descriptor,
IO_RESOURCE_ALTERNATIVE,
CM_RESOURCE_PORT_16_BIT_DECODE,
CmResourceShareDeviceExclusive,
0ul,
1ul,
0ull,
0ull);
}
Descriptor++;
}
for (i = 0; i < RTL_NUMBER_OF(DrvpIsaBusReadDataPorts) * 2; ++i)
{
if ((i % 2) == 0)
{
expect_port_req(Descriptor,
0,
CM_RESOURCE_PORT_16_BIT_DECODE,
CmResourceShareDeviceExclusive,
4ul,
1ul,
(ULONG64)DrvpIsaBusReadDataPorts[i / 2],
(ULONG64)(DrvpIsaBusReadDataPorts[i / 2]) + 4 - 1);
}
else
{
expect_port_req(Descriptor,
IO_RESOURCE_ALTERNATIVE,
CM_RESOURCE_PORT_16_BIT_DECODE,
CmResourceShareDeviceExclusive,
0ul,
1ul,
0ull,
0ull);
}
Descriptor++;
}
/*********************************************************/
ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList));
ok_int(ReqList->ListSize, (ULONG_PTR)Descriptor - (ULONG_PTR)ReqList);
}
/*
* Interface 0 Bus 0 Slot 0 AlternativeLists 1
*
* AltList, AltList->Count A Ver.1 Rev.1
* [0:1:10] IO: Min 0:A79, Max 0:A79, Align 1 Len 1
* [8:1:10] IO: Min 0:0, Max 0:0, Align 1 Len 0
* [0:1:10] IO: Min 0:279, Max 0:279, Align 1 Len 1
* [8:1:10] IO: Min 0:0, Max 0:0, Align 1 Len 0
* [8:1:10] IO: Min 0:274, Max 0:277, Align 1 Len 4
* [8:1:10] IO: Min 0:3E4, Max 0:3E7, Align 1 Len 4
* [8:1:10] IO: Min 0:204, Max 0:207, Align 1 Len 4
* [8:1:10] IO: Min 0:2E4, Max 0:2E7, Align 1 Len 4
* [0:1:10] IO: Min 0:354, Max 0:357, Align 1 Len 4 <-- selected (4th range)
* [8:1:10] IO: Min 0:2F4, Max 0:2F7, Align 1 Len 4
*/
static
VOID
DrvTestReadDataPortQueryResourcesRequirementsForRebalance(VOID)
{
PIO_RESOURCE_REQUIREMENTS_LIST ReqList;
PIO_RESOURCE_DESCRIPTOR Descriptor;
ULONG i;
/* Select the 4th I/O range in the list */
#define RDP_INDEX 4
ReqList = IsaPnpCreateReadPortDORequirements(DrvpIsaBusReadDataPorts[RDP_INDEX]);
ok(ReqList != NULL, "ReqList is NULL\n");
if (ReqList == NULL)
{
skip("No ReqList\n");
return;
}
expect_requirements_list_header(ReqList, Internal, 1UL);
expect_alt_list_header(&ReqList->List[0], 10UL);
Descriptor = &ReqList->List[0].Descriptors[0];
for (i = 0; i < RTL_NUMBER_OF(DrvpIsaBusPorts) * 2; ++i)
{
if ((i % 2) == 0)
{
expect_port_req(Descriptor,
0,
CM_RESOURCE_PORT_16_BIT_DECODE,
CmResourceShareDeviceExclusive,
1ul,
1ul,
(ULONG64)DrvpIsaBusPorts[i / 2],
(ULONG64)DrvpIsaBusPorts[i / 2]);
}
else
{
expect_port_req(Descriptor,
IO_RESOURCE_ALTERNATIVE,
CM_RESOURCE_PORT_16_BIT_DECODE,
CmResourceShareDeviceExclusive,
0ul,
1ul,
0ull,
0ull);
}
Descriptor++;
}
for (i = 0; i < RTL_NUMBER_OF(DrvpIsaBusReadDataPorts); ++i)
{
expect_port_req(Descriptor,
(i == RDP_INDEX) ? 0 : IO_RESOURCE_ALTERNATIVE,
CM_RESOURCE_PORT_16_BIT_DECODE,
CmResourceShareDeviceExclusive,
4ul,
1ul,
(ULONG64)DrvpIsaBusReadDataPorts[i],
(ULONG64)(DrvpIsaBusReadDataPorts[i]) + 4 - 1);
Descriptor++;
}
/*********************************************************/
ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList));
ok_int(ReqList->ListSize, (ULONG_PTR)Descriptor - (ULONG_PTR)ReqList);
}
START_TEST(Resources)
{
DrvTestReadDataPortQueryResources();
DrvTestReadDataPortQueryResourcesRequirementsForEnum();
DrvTestReadDataPortQueryResourcesRequirementsForRebalance();
if (DrvTestIsolation())
{
DrvTestResources();
}
}