1 /*
2  * PROJECT:     ReactOS API Tests
3  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:     Unit Tests for acpi!Bus_PDO_QueryResourceRequirements
5  * COPYRIGHT:   Copyright 2017-2020 Thomas Faber (thomas.faber@reactos.org)
6  */
7 
8 #include <apitest.h>
9 
10 #define WIN32_NO_STATUS
11 #include <ndk/rtlfuncs.h>
12 #define UNIT_TEST
13 #include <acpi.h>
14 
15 /* Kernel definitions (copied) */
16 #define IO_RESOURCE_PREFERRED             0x01
17 #define IO_RESOURCE_DEFAULT               0x02
18 #define IO_RESOURCE_ALTERNATIVE           0x08
19 
20 typedef struct _IO_RESOURCE_DESCRIPTOR {
21   UCHAR Option;
22   UCHAR Type;
23   UCHAR ShareDisposition;
24   UCHAR Spare1;
25   USHORT Flags;
26   USHORT Spare2;
27   union {
28     struct {
29       ULONG Length;
30       ULONG Alignment;
31       PHYSICAL_ADDRESS MinimumAddress;
32       PHYSICAL_ADDRESS MaximumAddress;
33     } Port;
34     struct {
35       ULONG Length;
36       ULONG Alignment;
37       PHYSICAL_ADDRESS MinimumAddress;
38       PHYSICAL_ADDRESS MaximumAddress;
39     } Memory;
40     struct {
41       ULONG MinimumVector;
42       ULONG MaximumVector;
43     } Interrupt;
44     struct {
45       ULONG MinimumChannel;
46       ULONG MaximumChannel;
47     } Dma;
48     struct {
49       ULONG Length;
50       ULONG Alignment;
51       PHYSICAL_ADDRESS MinimumAddress;
52       PHYSICAL_ADDRESS MaximumAddress;
53     } Generic;
54     struct {
55       ULONG Data[3];
56     } DevicePrivate;
57     struct {
58       ULONG Length;
59       ULONG MinBusNumber;
60       ULONG MaxBusNumber;
61       ULONG Reserved;
62     } BusNumber;
63     struct {
64       ULONG Priority;
65       ULONG Reserved1;
66       ULONG Reserved2;
67     } ConfigData;
68   } u;
69 } IO_RESOURCE_DESCRIPTOR, *PIO_RESOURCE_DESCRIPTOR;
70 
71 typedef struct _IO_RESOURCE_LIST {
72   USHORT Version;
73   USHORT Revision;
74   ULONG Count;
75   IO_RESOURCE_DESCRIPTOR Descriptors[1];
76 } IO_RESOURCE_LIST, *PIO_RESOURCE_LIST;
77 
78 typedef struct _IO_RESOURCE_REQUIREMENTS_LIST {
79   ULONG ListSize;
80   INTERFACE_TYPE InterfaceType;
81   ULONG BusNumber;
82   ULONG SlotNumber;
83   ULONG Reserved[3];
84   ULONG AlternativeLists;
85   IO_RESOURCE_LIST List[1];
86 } IO_RESOURCE_REQUIREMENTS_LIST, *PIO_RESOURCE_REQUIREMENTS_LIST;
87 
88 /* Kernel definitions (mock) */
89 #define PAGED_CODE()
90 #define DPRINT1(...) do { if (0) DbgPrint(__VA_ARGS__); } while (0)
91 
92 typedef struct _IRP
93 {
94     IO_STATUS_BLOCK IoStatus;
95 } IRP, *PIRP;
96 
97 #define PagedPool 1
98 static
99 PVOID
100 ExAllocatePoolWithTag(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
101 {
102     PVOID *Mem;
103 
104     Mem = HeapAlloc(GetProcessHeap(), 0, NumberOfBytes + 2 * sizeof(PVOID));
105     Mem[0] = (PVOID)NumberOfBytes;
106     Mem[1] = (PVOID)(ULONG_PTR)Tag;
107     return Mem + 2;
108 }
109 
110 static
111 VOID
112 ExFreePoolWithTag(PVOID MemPtr, ULONG Tag)
113 {
114     PVOID *Mem = MemPtr;
115 
116     Mem -= 2;
117     ok(Mem[1] == (PVOID)(ULONG_PTR)Tag, "Tag is %lx, expected %p\n", Tag, Mem[1]);
118     HeapFree(GetProcessHeap(), 0, Mem);
119 }
120 
121 static
122 SIZE_T
123 GetPoolAllocSize(PVOID MemPtr)
124 {
125     PVOID *Mem = MemPtr;
126 
127     Mem -= 2;
128     return (SIZE_T)Mem[0];
129 }
130 
131 /* ACPI driver definitions */
132 typedef struct _PDO_DEVICE_DATA
133 {
134     HANDLE AcpiHandle;
135     PWCHAR HardwareIDs;
136 } PDO_DEVICE_DATA, *PPDO_DEVICE_DATA;
137 
138 /* ACPICA functions (mock) */
139 static BOOLEAN AcpiCallExpected;
140 static ACPI_HANDLE CorrectHandle = &CorrectHandle;
141 static ACPI_BUFFER CurrentBuffer;
142 static ACPI_BUFFER PossibleBuffer;
143 
144 ACPI_STATUS
145 AcpiGetCurrentResources (
146     ACPI_HANDLE             Device,
147     ACPI_BUFFER             *RetBuffer)
148 {
149     ok(AcpiCallExpected, "Unexpected call to AcpiGetCurrentResources\n");
150     ok(Device == CorrectHandle, "Device = %p, expected %p\n", Device, CorrectHandle);
151     if (RetBuffer->Length < CurrentBuffer.Length)
152     {
153         RetBuffer->Length = CurrentBuffer.Length;
154         return AE_BUFFER_OVERFLOW;
155     }
156     RetBuffer->Length = CurrentBuffer.Length;
157     CopyMemory(RetBuffer->Pointer, CurrentBuffer.Pointer, CurrentBuffer.Length);
158     return AE_OK;
159 }
160 
161 ACPI_STATUS
162 AcpiGetPossibleResources (
163     ACPI_HANDLE             Device,
164     ACPI_BUFFER             *RetBuffer)
165 {
166     ok(AcpiCallExpected, "Unexpected call to AcpiGetPossibleResources\n");
167     ok(Device == CorrectHandle, "Device = %p, expected %p\n", Device, CorrectHandle);
168     if (RetBuffer->Length < PossibleBuffer.Length)
169     {
170         RetBuffer->Length = PossibleBuffer.Length;
171         return AE_BUFFER_OVERFLOW;
172     }
173     RetBuffer->Length = PossibleBuffer.Length;
174     CopyMemory(RetBuffer->Pointer, PossibleBuffer.Pointer, PossibleBuffer.Length);
175     return AE_OK;
176 }
177 
178 #include "../../../../drivers/bus/acpi/buspdo.c"
179 
180 /* ACPI_RESOURCE builder helpers */
181 #define MAKE_IRQ(Resource, _DescriptorLength, _Triggering, _Polarity, _Shareable, _WakeCapable) \
182     do {                                                                                        \
183     Resource->Data.Irq.DescriptorLength = _DescriptorLength;                                    \
184     Resource->Data.Irq.Triggering = _Triggering;                                                \
185     Resource->Data.Irq.Polarity = _Polarity;                                                    \
186     Resource->Data.Irq.Shareable = _Shareable;                                                  \
187     Resource->Data.Irq.WakeCapable = _WakeCapable;                                              \
188     } while (0)
189 
190 /* IO_RESOURCE_DESCRIPTOR expectations */
191 #define expect_irq(Desc, ExpectedOption, ExpectedShare, ExpectedMin, ExpectedMax)                                                       \
192     do {                                                                                                                                \
193     ok((Desc)->Option == ExpectedOption, "Desc->Option = %u\n", (Desc)->Option);                                                        \
194     ok((Desc)->Type == CmResourceTypeInterrupt, "Desc->Type = %u\n", (Desc)->Type);                                                     \
195     ok((Desc)->ShareDisposition == ExpectedShare, "Desc->ShareDisposition = %u\n", (Desc)->ShareDisposition);                           \
196     ok((Desc)->u.Interrupt.MinimumVector == ExpectedMin, "Desc->u.Interrupt.MinimumVector = %lu\n", (Desc)->u.Interrupt.MinimumVector); \
197     ok((Desc)->u.Interrupt.MaximumVector == ExpectedMax, "Desc->u.Interrupt.MaximumVector = %lu\n", (Desc)->u.Interrupt.MaximumVector); \
198     } while (0)
199 
200 #define expect_port(Desc, ExpectedOption, ExpectedShare, ExpectedLength, ExpectedAlign, ExpectedMin, ExpectedMax)                                   \
201     do {                                                                                                                                            \
202     ok((Desc)->Option == ExpectedOption, "Desc->Option = %u\n", (Desc)->Option);                                                                    \
203     ok((Desc)->Type == CmResourceTypePort, "Desc->Type = %u\n", (Desc)->Type);                                                                      \
204     ok((Desc)->ShareDisposition == ExpectedShare, "Desc->ShareDisposition = %u\n", (Desc)->ShareDisposition);                                       \
205     ok((Desc)->u.Port.Length == ExpectedLength, "Desc->u.Port.Length = %lu\n", (Desc)->u.Port.Length);                                              \
206     ok((Desc)->u.Port.Alignment == ExpectedAlign, "Desc->u.Port.Alignment = %lu\n", (Desc)->u.Port.Alignment);                                      \
207     ok((Desc)->u.Port.MinimumAddress.QuadPart == ExpectedMin, "Desc->u.Port.MinimumAddress = 0x%I64x\n", (Desc)->u.Port.MinimumAddress.QuadPart);   \
208     ok((Desc)->u.Port.MaximumAddress.QuadPart == ExpectedMax, "Desc->u.Port.MaximumAddress = 0x%I64x\n", (Desc)->u.Port.MaximumAddress.QuadPart);   \
209     } while (0)
210 
211 START_TEST(Bus_PDO_QueryResourceRequirements)
212 {
213     NTSTATUS Status;
214     PDO_DEVICE_DATA DeviceData;
215     IRP Irp;
216     ACPI_RESOURCE ResourcesBuffer[20];
217     ACPI_RESOURCE *Resource;
218     PIO_RESOURCE_REQUIREMENTS_LIST ReqList;
219     PIO_RESOURCE_LIST ReqList2;
220 
221     /* Invalid AcpiHandle */
222     AcpiCallExpected = FALSE;
223     Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
224     DeviceData.AcpiHandle = NULL;
225     Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
226     ok(Status == STATUS_WAIT_0 + 17, "Status = 0x%lx\n", Status);
227 
228     /* PCI Bus device */
229     AcpiCallExpected = FALSE;
230     Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
231     DeviceData.AcpiHandle = CorrectHandle;
232     DeviceData.HardwareIDs = L"PNP0A03\0";
233     Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
234     ok(Status == STATUS_WAIT_0 + 17, "Status = 0x%lx\n", Status);
235 
236     /* PCI Bus device #2 */
237     AcpiCallExpected = FALSE;
238     Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
239     DeviceData.AcpiHandle = CorrectHandle;
240     DeviceData.HardwareIDs = L"PNP0A08\0";
241     Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
242     ok(Status == STATUS_WAIT_0 + 17, "Status = 0x%lx\n", Status);
243 
244     /* Empty buffer */
245     AcpiCallExpected = TRUE;
246     Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
247     DeviceData.AcpiHandle = CorrectHandle;
248     DeviceData.HardwareIDs = L"PNP0501\0";
249     Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
250     ok(Status == STATUS_WAIT_0 + 17, "Status = 0x%lx\n", Status);
251 
252     /* Simple single-resource list */
253     AcpiCallExpected = TRUE;
254     Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
255     Irp.IoStatus.Information = 0;
256     DeviceData.AcpiHandle = CorrectHandle;
257     DeviceData.HardwareIDs = L"PNP0501\0";
258     Resource = ResourcesBuffer;
259     Resource->Type = ACPI_RESOURCE_TYPE_IRQ;
260     Resource->Length = sizeof(*Resource);
261     MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE);
262     Resource->Data.Irq.InterruptCount = 1;
263     Resource->Data.Irq.Interrupts[0] = 7;
264     Resource = ACPI_NEXT_RESOURCE(Resource);
265     Resource->Type = ACPI_RESOURCE_TYPE_END_TAG;
266     Resource->Length = 0;
267     Resource++;
268     PossibleBuffer.Pointer = ResourcesBuffer;
269     PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer;
270     Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
271     ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
272     ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", Irp.IoStatus.Status);
273     ReqList = (PVOID)Irp.IoStatus.Information;
274     ok(ReqList != NULL, "ReqList is NULL\n");
275     if (ReqList == NULL)
276     {
277         skip("No ReqList\n");
278         return;
279     }
280     ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", ReqList->InterfaceType);
281     ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber);
282     ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber);
283     ok(ReqList->AlternativeLists == 1, "AlternativeLists = %lu\n", ReqList->AlternativeLists);
284     ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", ReqList->List[0].Version);
285     ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", ReqList->List[0].Revision);
286     ok(ReqList->List[0].Count == 1, "List[0].Count = %lu\n", ReqList->List[0].Count);
287     expect_irq(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, CmResourceShareDeviceExclusive, 7, 7);
288     ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList));
289     ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList->List[0].Descriptors[1] - (ULONG_PTR)ReqList);
290     ExFreePoolWithTag(ReqList, 'RpcA');
291 
292     /* Two IRQs */
293     AcpiCallExpected = TRUE;
294     Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
295     Irp.IoStatus.Information = 0;
296     DeviceData.AcpiHandle = CorrectHandle;
297     DeviceData.HardwareIDs = L"PNP0501\0";
298     Resource = ResourcesBuffer;
299     Resource->Type = ACPI_RESOURCE_TYPE_IRQ;
300     Resource->Length = FIELD_OFFSET(ACPI_RESOURCE, Data) + FIELD_OFFSET(ACPI_RESOURCE_IRQ, Interrupts[2]);
301     MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE);
302     Resource->Data.Irq.InterruptCount = 2;
303     Resource->Data.Irq.Interrupts[0] = 3;
304     Resource->Data.Irq.Interrupts[1] = 7;
305     Resource = ACPI_NEXT_RESOURCE(Resource);
306     Resource->Type = ACPI_RESOURCE_TYPE_END_TAG;
307     Resource->Length = 0;
308     Resource++;
309     PossibleBuffer.Pointer = ResourcesBuffer;
310     PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer;
311     Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
312     ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
313     ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", Irp.IoStatus.Status);
314     ReqList = (PVOID)Irp.IoStatus.Information;
315     ok(ReqList != NULL, "ReqList is NULL\n");
316     if (ReqList == NULL)
317     {
318         skip("No ReqList\n");
319         return;
320     }
321     ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", ReqList->InterfaceType);
322     ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber);
323     ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber);
324     ok(ReqList->AlternativeLists == 1, "AlternativeLists = %lu\n", ReqList->AlternativeLists);
325     ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", ReqList->List[0].Version);
326     ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", ReqList->List[0].Revision);
327     ok(ReqList->List[0].Count == 2, "List[0].Count = %lu\n", ReqList->List[0].Count);
328     expect_irq(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, CmResourceShareDeviceExclusive, 3, 3);
329     expect_irq(&ReqList->List[0].Descriptors[1], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 7, 7);
330     ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList));
331     ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList->List[0].Descriptors[2] - (ULONG_PTR)ReqList);
332     ExFreePoolWithTag(ReqList, 'RpcA');
333 
334     /* Port */
335     AcpiCallExpected = TRUE;
336     Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
337     Irp.IoStatus.Information = 0;
338     DeviceData.AcpiHandle = CorrectHandle;
339     DeviceData.HardwareIDs = L"PNP0501\0";
340     Resource = ResourcesBuffer;
341     Resource->Type = ACPI_RESOURCE_TYPE_IO;
342     Resource->Length = sizeof(*Resource);
343     Resource->Data.Io.IoDecode = ACPI_DECODE_16;
344     Resource->Data.Io.Alignment = 8;
345     Resource->Data.Io.AddressLength = 8;
346     Resource->Data.Io.Minimum = 0x3F8;
347     Resource->Data.Io.Maximum = 0x3F8;
348     Resource = ACPI_NEXT_RESOURCE(Resource);
349     Resource->Type = ACPI_RESOURCE_TYPE_END_TAG;
350     Resource->Length = 0;
351     Resource++;
352     PossibleBuffer.Pointer = ResourcesBuffer;
353     PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer;
354     Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
355     ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
356     ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", Irp.IoStatus.Status);
357     ReqList = (PVOID)Irp.IoStatus.Information;
358     ok(ReqList != NULL, "ReqList is NULL\n");
359     if (ReqList == NULL)
360     {
361         skip("No ReqList\n");
362         return;
363     }
364     ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", ReqList->InterfaceType);
365     ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber);
366     ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber);
367     ok(ReqList->AlternativeLists == 1, "AlternativeLists = %lu\n", ReqList->AlternativeLists);
368     ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", ReqList->List[0].Version);
369     ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", ReqList->List[0].Revision);
370     ok(ReqList->List[0].Count == 1, "List[0].Count = %lu\n", ReqList->List[0].Count);
371     expect_port(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, CmResourceShareDriverExclusive, 8, 8, 0x3F8, 0x3FF);
372     ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList));
373     ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList->List[0].Descriptors[1] - (ULONG_PTR)ReqList);
374     ExFreePoolWithTag(ReqList, 'RpcA');
375 
376     /* Port + two IRQs */
377     AcpiCallExpected = TRUE;
378     Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
379     Irp.IoStatus.Information = 0;
380     DeviceData.AcpiHandle = CorrectHandle;
381     DeviceData.HardwareIDs = L"PNP0501\0";
382     Resource = ResourcesBuffer;
383     Resource->Type = ACPI_RESOURCE_TYPE_IO;
384     Resource->Length = sizeof(*Resource);
385     Resource->Data.Io.IoDecode = ACPI_DECODE_16;
386     Resource->Data.Io.Alignment = 8;
387     Resource->Data.Io.AddressLength = 8;
388     Resource->Data.Io.Minimum = 0x3F8;
389     Resource->Data.Io.Maximum = 0x3F8;
390     Resource = ACPI_NEXT_RESOURCE(Resource);
391     Resource->Type = ACPI_RESOURCE_TYPE_IRQ;
392     Resource->Length = FIELD_OFFSET(ACPI_RESOURCE, Data) + FIELD_OFFSET(ACPI_RESOURCE_IRQ, Interrupts[2]);
393     MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE);
394     Resource->Data.Irq.InterruptCount = 2;
395     Resource->Data.Irq.Interrupts[0] = 3;
396     Resource->Data.Irq.Interrupts[1] = 7;
397     Resource = ACPI_NEXT_RESOURCE(Resource);
398     Resource->Type = ACPI_RESOURCE_TYPE_END_TAG;
399     Resource->Length = 0;
400     Resource++;
401     PossibleBuffer.Pointer = ResourcesBuffer;
402     PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer;
403     Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
404     ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
405     ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", Irp.IoStatus.Status);
406     ReqList = (PVOID)Irp.IoStatus.Information;
407     ok(ReqList != NULL, "ReqList is NULL\n");
408     if (ReqList == NULL)
409     {
410         skip("No ReqList\n");
411         return;
412     }
413     ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", ReqList->InterfaceType);
414     ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber);
415     ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber);
416     ok(ReqList->AlternativeLists == 1, "AlternativeLists = %lu\n", ReqList->AlternativeLists);
417     ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", ReqList->List[0].Version);
418     ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", ReqList->List[0].Revision);
419     ok(ReqList->List[0].Count == 3, "List[0].Count = %lu\n", ReqList->List[0].Count);
420     expect_port(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, CmResourceShareDriverExclusive, 8, 8, 0x3F8, 0x3FF);
421     expect_irq(&ReqList->List[0].Descriptors[1], IO_RESOURCE_PREFERRED, CmResourceShareDeviceExclusive, 3, 3);
422     expect_irq(&ReqList->List[0].Descriptors[2], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 7, 7);
423     ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList));
424     ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList->List[0].Descriptors[3] - (ULONG_PTR)ReqList);
425     ExFreePoolWithTag(ReqList, 'RpcA');
426 
427     /* Multiple alternatives for ports + IRQs (VMware COM port, simplified) */
428     AcpiCallExpected = TRUE;
429     Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
430     Irp.IoStatus.Information = 0;
431     DeviceData.AcpiHandle = CorrectHandle;
432     DeviceData.HardwareIDs = L"PNP0501\0";
433     Resource = ResourcesBuffer;
434     Resource->Type = ACPI_RESOURCE_TYPE_START_DEPENDENT;
435     Resource->Length = sizeof(*Resource);
436 
437     Resource = ACPI_NEXT_RESOURCE(Resource);
438     Resource->Type = ACPI_RESOURCE_TYPE_IO;
439     Resource->Length = sizeof(*Resource);
440     Resource->Data.Io.IoDecode = ACPI_DECODE_16;
441     Resource->Data.Io.Alignment = 8;
442     Resource->Data.Io.AddressLength = 8;
443     Resource->Data.Io.Minimum = 0x3E8;
444     Resource->Data.Io.Maximum = 0x3E8;
445 
446     Resource = ACPI_NEXT_RESOURCE(Resource);
447     Resource->Type = ACPI_RESOURCE_TYPE_IRQ;
448     Resource->Length = FIELD_OFFSET(ACPI_RESOURCE, Data) + FIELD_OFFSET(ACPI_RESOURCE_IRQ, Interrupts[5]);
449     MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE);
450     Resource->Data.Irq.InterruptCount = 5;
451     Resource->Data.Irq.Interrupts[0] = 3;
452     Resource->Data.Irq.Interrupts[1] = 4;
453     Resource->Data.Irq.Interrupts[2] = 5;
454     Resource->Data.Irq.Interrupts[3] = 6;
455     Resource->Data.Irq.Interrupts[4] = 7;
456 
457     Resource = ACPI_NEXT_RESOURCE(Resource);
458     Resource->Type = ACPI_RESOURCE_TYPE_START_DEPENDENT;
459     Resource->Length = sizeof(*Resource);
460 
461     Resource = ACPI_NEXT_RESOURCE(Resource);
462     Resource->Type = ACPI_RESOURCE_TYPE_IO;
463     Resource->Length = sizeof(*Resource);
464     Resource->Data.Io.IoDecode = ACPI_DECODE_16;
465     Resource->Data.Io.Alignment = 8;
466     Resource->Data.Io.AddressLength = 8;
467     Resource->Data.Io.Minimum = 0x2E8;
468     Resource->Data.Io.Maximum = 0x2E8;
469 
470     Resource = ACPI_NEXT_RESOURCE(Resource);
471     Resource->Type = ACPI_RESOURCE_TYPE_IRQ;
472     Resource->Length = FIELD_OFFSET(ACPI_RESOURCE, Data) + FIELD_OFFSET(ACPI_RESOURCE_IRQ, Interrupts[5]);
473     MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE);
474     Resource->Data.Irq.InterruptCount = 5;
475     Resource->Data.Irq.Interrupts[0] = 3;
476     Resource->Data.Irq.Interrupts[1] = 4;
477     Resource->Data.Irq.Interrupts[2] = 5;
478     Resource->Data.Irq.Interrupts[3] = 6;
479     Resource->Data.Irq.Interrupts[4] = 7;
480 
481     Resource = ACPI_NEXT_RESOURCE(Resource);
482     Resource->Type = ACPI_RESOURCE_TYPE_END_DEPENDENT;
483     Resource->Length = sizeof(*Resource);
484 
485     Resource = ACPI_NEXT_RESOURCE(Resource);
486     Resource->Type = ACPI_RESOURCE_TYPE_END_TAG;
487     Resource->Length = 0;
488     Resource++;
489     PossibleBuffer.Pointer = ResourcesBuffer;
490     PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer;
491     Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
492     ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
493     ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", Irp.IoStatus.Status);
494     ReqList = (PVOID)Irp.IoStatus.Information;
495     ok(ReqList != NULL, "ReqList is NULL\n");
496     if (ReqList == NULL)
497     {
498         skip("No ReqList\n");
499         return;
500     }
501     ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", ReqList->InterfaceType);
502     ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber);
503     ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber);
504     ok(ReqList->AlternativeLists == 2, "AlternativeLists = %lu\n", ReqList->AlternativeLists);
505     ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", ReqList->List[0].Version);
506     ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", ReqList->List[0].Revision);
507     ok(ReqList->List[0].Count == 6, "List[0].Count = %lu\n", ReqList->List[0].Count);
508     expect_port(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, CmResourceShareDriverExclusive, 8, 8, 0x3E8, 0x3EF);
509     expect_irq(&ReqList->List[0].Descriptors[1], IO_RESOURCE_PREFERRED, CmResourceShareDeviceExclusive, 3, 3);
510     expect_irq(&ReqList->List[0].Descriptors[2], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 4, 4);
511     expect_irq(&ReqList->List[0].Descriptors[3], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 5, 5);
512     expect_irq(&ReqList->List[0].Descriptors[4], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 6, 6);
513     expect_irq(&ReqList->List[0].Descriptors[5], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 7, 7);
514     ReqList2 = (PVOID)&ReqList->List[0].Descriptors[6];
515     if (ReqList->ListSize > (ULONG_PTR)ReqList2 - (ULONG_PTR)ReqList)
516     {
517         ok(ReqList2->Version == 1, "List[1].Version = %u\n", ReqList->List[0].Version);
518         ok(ReqList2->Revision == 1, "List[1].Revision = %u\n", ReqList->List[0].Revision);
519         ok(ReqList2->Count == 6, "List[1].Count = %lu\n", ReqList->List[0].Count);
520         expect_port(&ReqList2->Descriptors[0], IO_RESOURCE_PREFERRED, CmResourceShareDriverExclusive, 8, 8, 0x2E8, 0x2EF);
521         expect_irq(&ReqList2->Descriptors[1], IO_RESOURCE_PREFERRED, CmResourceShareDeviceExclusive, 3, 3);
522         expect_irq(&ReqList2->Descriptors[2], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 4, 4);
523         expect_irq(&ReqList2->Descriptors[3], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 5, 5);
524         expect_irq(&ReqList2->Descriptors[4], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 6, 6);
525         expect_irq(&ReqList2->Descriptors[5], IO_RESOURCE_ALTERNATIVE, CmResourceShareDeviceExclusive, 7, 7);
526     }
527     ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList));
528     ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList2->Descriptors[6] - (ULONG_PTR)ReqList);
529     ExFreePoolWithTag(ReqList, 'RpcA');
530 }
531