mirror of
https://github.com/reactos/reactos.git
synced 2024-09-22 10:37:10 +00:00
b36d9bd9c1
CORE-18562
487 lines
15 KiB
C
487 lines
15 KiB
C
/*
|
|
* 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();
|
|
}
|
|
}
|