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