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