1 #ifndef UNIT_TEST
2 #include "precomp.h"
3
4 #include <initguid.h>
5 #include <poclass.h>
6
7 #define NDEBUG
8 #include <debug.h>
9
10 #ifdef ALLOC_PRAGMA
11 #pragma alloc_text (PAGE, Bus_PDO_PnP)
12 #pragma alloc_text (PAGE, Bus_PDO_QueryDeviceCaps)
13 #pragma alloc_text (PAGE, Bus_PDO_QueryDeviceId)
14 #pragma alloc_text (PAGE, Bus_PDO_QueryDeviceText)
15 #pragma alloc_text (PAGE, Bus_PDO_QueryResources)
16 #pragma alloc_text (PAGE, Bus_PDO_QueryResourceRequirements)
17 #pragma alloc_text (PAGE, Bus_PDO_QueryDeviceRelations)
18 #pragma alloc_text (PAGE, Bus_PDO_QueryBusInformation)
19 #pragma alloc_text (PAGE, Bus_GetDeviceCapabilities)
20 #endif
21
22 NTSTATUS
Bus_PDO_PnP(PDEVICE_OBJECT DeviceObject,PIRP Irp,PIO_STACK_LOCATION IrpStack,PPDO_DEVICE_DATA DeviceData)23 Bus_PDO_PnP (
24 PDEVICE_OBJECT DeviceObject,
25 PIRP Irp,
26 PIO_STACK_LOCATION IrpStack,
27 PPDO_DEVICE_DATA DeviceData
28 )
29 {
30 NTSTATUS status;
31 POWER_STATE state;
32 struct acpi_device *device = NULL;
33
34 PAGED_CODE ();
35
36 if (DeviceData->AcpiHandle)
37 acpi_bus_get_device(DeviceData->AcpiHandle, &device);
38
39 //
40 // NB: Because we are a bus enumerator, we have no one to whom we could
41 // defer these irps. Therefore we do not pass them down but merely
42 // return them.
43 //
44
45 switch (IrpStack->MinorFunction) {
46
47 case IRP_MN_START_DEVICE:
48 //
49 // Here we do what ever initialization and ``turning on'' that is
50 // required to allow others to access this device.
51 // Power up the device.
52 //
53 if (DeviceData->AcpiHandle && acpi_bus_power_manageable(DeviceData->AcpiHandle) &&
54 !ACPI_SUCCESS(acpi_bus_set_power(DeviceData->AcpiHandle, ACPI_STATE_D0)))
55 {
56 DPRINT1("Device %x failed to start!\n", DeviceData->AcpiHandle);
57 status = STATUS_UNSUCCESSFUL;
58 break;
59 }
60
61 DeviceData->InterfaceName.Length = 0;
62 status = STATUS_SUCCESS;
63
64 if (!device)
65 {
66 status = IoRegisterDeviceInterface(DeviceData->Common.Self,
67 &GUID_DEVICE_SYS_BUTTON,
68 NULL,
69 &DeviceData->InterfaceName);
70 }
71 else if (device->flags.hardware_id &&
72 strstr(device->pnp.hardware_id, ACPI_THERMAL_HID))
73 {
74 status = IoRegisterDeviceInterface(DeviceData->Common.Self,
75 &GUID_DEVICE_THERMAL_ZONE,
76 NULL,
77 &DeviceData->InterfaceName);
78 }
79 else if (device->flags.hardware_id &&
80 strstr(device->pnp.hardware_id, ACPI_FAN_HID))
81 {
82 status = IoRegisterDeviceInterface(DeviceData->Common.Self,
83 &GUID_DEVICE_FAN,
84 NULL,
85 &DeviceData->InterfaceName);
86 }
87 else if (device->flags.hardware_id &&
88 strstr(device->pnp.hardware_id, ACPI_BUTTON_HID_LID))
89 {
90 status = IoRegisterDeviceInterface(DeviceData->Common.Self,
91 &GUID_DEVICE_LID,
92 NULL,
93 &DeviceData->InterfaceName);
94 }
95 else if (device->flags.hardware_id &&
96 strstr(device->pnp.hardware_id, ACPI_PROCESSOR_HID))
97 {
98 status = IoRegisterDeviceInterface(DeviceData->Common.Self,
99 &GUID_DEVICE_PROCESSOR,
100 NULL,
101 &DeviceData->InterfaceName);
102 }
103
104 /* Failure to register an interface is not a fatal failure so don't return a failure status */
105 if (NT_SUCCESS(status) && DeviceData->InterfaceName.Length != 0)
106 IoSetDeviceInterfaceState(&DeviceData->InterfaceName, TRUE);
107
108 state.DeviceState = PowerDeviceD0;
109 PoSetPowerState(DeviceData->Common.Self, DevicePowerState, state);
110 DeviceData->Common.DevicePowerState = PowerDeviceD0;
111 SET_NEW_PNP_STATE(DeviceData->Common, Started);
112 status = STATUS_SUCCESS;
113 break;
114
115 case IRP_MN_STOP_DEVICE:
116
117 if (DeviceData->InterfaceName.Length != 0)
118 IoSetDeviceInterfaceState(&DeviceData->InterfaceName, FALSE);
119
120 //
121 // Here we shut down the device and give up and unmap any resources
122 // we acquired for the device.
123 //
124 if (DeviceData->AcpiHandle && acpi_bus_power_manageable(DeviceData->AcpiHandle) &&
125 !ACPI_SUCCESS(acpi_bus_set_power(DeviceData->AcpiHandle, ACPI_STATE_D3)))
126 {
127 DPRINT1("Device %x failed to stop!\n", DeviceData->AcpiHandle);
128 status = STATUS_UNSUCCESSFUL;
129 break;
130 }
131
132 state.DeviceState = PowerDeviceD3;
133 PoSetPowerState(DeviceData->Common.Self, DevicePowerState, state);
134 DeviceData->Common.DevicePowerState = PowerDeviceD3;
135 SET_NEW_PNP_STATE(DeviceData->Common, Stopped);
136 status = STATUS_SUCCESS;
137 break;
138
139
140 case IRP_MN_QUERY_STOP_DEVICE:
141
142 //
143 // No reason here why we can't stop the device.
144 // If there were a reason we should speak now, because answering success
145 // here may result in a stop device irp.
146 //
147
148 SET_NEW_PNP_STATE(DeviceData->Common, StopPending);
149 status = STATUS_SUCCESS;
150 break;
151
152 case IRP_MN_CANCEL_STOP_DEVICE:
153
154 //
155 // The stop was canceled. Whatever state we set, or resources we put
156 // on hold in anticipation of the forthcoming STOP device IRP should be
157 // put back to normal. Someone, in the long list of concerned parties,
158 // has failed the stop device query.
159 //
160
161 //
162 // First check to see whether you have received cancel-stop
163 // without first receiving a query-stop. This could happen if someone
164 // above us fails a query-stop and passes down the subsequent
165 // cancel-stop.
166 //
167
168 if (StopPending == DeviceData->Common.DevicePnPState)
169 {
170 //
171 // We did receive a query-stop, so restore.
172 //
173 RESTORE_PREVIOUS_PNP_STATE(DeviceData->Common);
174 }
175 status = STATUS_SUCCESS;// We must not fail this IRP.
176 break;
177
178 case IRP_MN_REMOVE_DEVICE:
179 //
180 // We handle REMOVE_DEVICE just like STOP_DEVICE. This is because
181 // the device is still physically present (or at least we don't know any better)
182 // so we have to retain the PDO after stopping and removing power from it.
183 //
184 if (DeviceData->InterfaceName.Length != 0)
185 IoSetDeviceInterfaceState(&DeviceData->InterfaceName, FALSE);
186
187 if (DeviceData->AcpiHandle && acpi_bus_power_manageable(DeviceData->AcpiHandle) &&
188 !ACPI_SUCCESS(acpi_bus_set_power(DeviceData->AcpiHandle, ACPI_STATE_D3)))
189 {
190 DPRINT1("Device %x failed to enter D3!\n", DeviceData->AcpiHandle);
191 state.DeviceState = PowerDeviceD3;
192 PoSetPowerState(DeviceData->Common.Self, DevicePowerState, state);
193 DeviceData->Common.DevicePowerState = PowerDeviceD3;
194 }
195
196 SET_NEW_PNP_STATE(DeviceData->Common, Stopped);
197 status = STATUS_SUCCESS;
198 break;
199
200 case IRP_MN_QUERY_REMOVE_DEVICE:
201 SET_NEW_PNP_STATE(DeviceData->Common, RemovalPending);
202 status = STATUS_SUCCESS;
203 break;
204
205 case IRP_MN_CANCEL_REMOVE_DEVICE:
206 if (RemovalPending == DeviceData->Common.DevicePnPState)
207 {
208 RESTORE_PREVIOUS_PNP_STATE(DeviceData->Common);
209 }
210 status = STATUS_SUCCESS;
211 break;
212
213 case IRP_MN_QUERY_CAPABILITIES:
214
215 //
216 // Return the capabilities of a device, such as whether the device
217 // can be locked or ejected..etc
218 //
219
220 status = Bus_PDO_QueryDeviceCaps(DeviceData, Irp);
221
222 break;
223
224 case IRP_MN_QUERY_ID:
225
226 // Query the IDs of the device
227 status = Bus_PDO_QueryDeviceId(DeviceData, Irp);
228
229 break;
230
231 case IRP_MN_QUERY_DEVICE_RELATIONS:
232
233 DPRINT("\tQueryDeviceRelation Type: %s\n",DbgDeviceRelationString(\
234 IrpStack->Parameters.QueryDeviceRelations.Type));
235
236 status = Bus_PDO_QueryDeviceRelations(DeviceData, Irp);
237
238 break;
239
240 case IRP_MN_QUERY_DEVICE_TEXT:
241
242 status = Bus_PDO_QueryDeviceText(DeviceData, Irp);
243
244 break;
245
246 case IRP_MN_QUERY_RESOURCES:
247
248 status = Bus_PDO_QueryResources(DeviceData, Irp);
249
250 break;
251
252 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
253
254 status = Bus_PDO_QueryResourceRequirements(DeviceData, Irp);
255
256 break;
257
258 case IRP_MN_QUERY_BUS_INFORMATION:
259
260 status = Bus_PDO_QueryBusInformation(DeviceData, Irp);
261
262 break;
263
264 case IRP_MN_QUERY_INTERFACE:
265
266 status = Bus_PDO_QueryInterface(DeviceData, Irp);
267
268 break;
269
270
271 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
272
273 //
274 // OPTIONAL for bus drivers.
275 // The PnP Manager sends this IRP to a device
276 // stack so filter and function drivers can adjust the
277 // resources required by the device, if appropriate.
278 //
279
280 //break;
281
282 //case IRP_MN_QUERY_PNP_DEVICE_STATE:
283
284 //
285 // OPTIONAL for bus drivers.
286 // The PnP Manager sends this IRP after the drivers for
287 // a device return success from the IRP_MN_START_DEVICE
288 // request. The PnP Manager also sends this IRP when a
289 // driver for the device calls IoInvalidateDeviceState.
290 //
291
292 // break;
293
294 //case IRP_MN_READ_CONFIG:
295 //case IRP_MN_WRITE_CONFIG:
296
297 //
298 // Bus drivers for buses with configuration space must handle
299 // this request for their child devices. Our devices don't
300 // have a config space.
301 //
302
303 // break;
304
305 //case IRP_MN_SET_LOCK:
306
307 // break;
308
309 default:
310
311 //
312 // For PnP requests to the PDO that we do not understand we should
313 // return the IRP WITHOUT setting the status or information fields.
314 // These fields may have already been set by a filter (eg acpi).
315 status = Irp->IoStatus.Status;
316
317 break;
318 }
319
320 Irp->IoStatus.Status = status;
321 IoCompleteRequest (Irp, IO_NO_INCREMENT);
322
323 return status;
324 }
325
326 NTSTATUS
Bus_PDO_QueryDeviceCaps(PPDO_DEVICE_DATA DeviceData,PIRP Irp)327 Bus_PDO_QueryDeviceCaps(
328 PPDO_DEVICE_DATA DeviceData,
329 PIRP Irp )
330 {
331
332 PIO_STACK_LOCATION stack;
333 PDEVICE_CAPABILITIES deviceCapabilities;
334 struct acpi_device *device = NULL;
335 ULONG i;
336
337 PAGED_CODE ();
338
339 if (DeviceData->AcpiHandle)
340 acpi_bus_get_device(DeviceData->AcpiHandle, &device);
341
342 stack = IoGetCurrentIrpStackLocation (Irp);
343
344 //
345 // Get the packet.
346 //
347 deviceCapabilities=stack->Parameters.DeviceCapabilities.Capabilities;
348
349 //
350 // Set the capabilities.
351 //
352
353 if (deviceCapabilities->Version != 1 ||
354 deviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES))
355 {
356 return STATUS_UNSUCCESSFUL;
357 }
358
359 deviceCapabilities->D1Latency = 0;
360 deviceCapabilities->D2Latency = 0;
361 deviceCapabilities->D3Latency = 0;
362
363 deviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
364 deviceCapabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;
365 deviceCapabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
366 deviceCapabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
367
368 for (i = 0; i < ACPI_D_STATE_COUNT && device; i++)
369 {
370 if (!device->power.states[i].flags.valid)
371 continue;
372
373 switch (i)
374 {
375 case ACPI_STATE_D0:
376 deviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
377 break;
378
379 case ACPI_STATE_D1:
380 deviceCapabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
381 deviceCapabilities->D1Latency = device->power.states[i].latency;
382 break;
383
384 case ACPI_STATE_D2:
385 deviceCapabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
386 deviceCapabilities->D2Latency = device->power.states[i].latency;
387 break;
388
389 case ACPI_STATE_D3:
390 deviceCapabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
391 deviceCapabilities->D3Latency = device->power.states[i].latency;
392 break;
393 }
394 }
395
396 // We can wake the system from D1
397 deviceCapabilities->DeviceWake = PowerDeviceD1;
398
399
400 deviceCapabilities->DeviceD1 =
401 (deviceCapabilities->DeviceState[PowerSystemSleeping1] == PowerDeviceD1) ? TRUE : FALSE;
402 deviceCapabilities->DeviceD2 =
403 (deviceCapabilities->DeviceState[PowerSystemSleeping2] == PowerDeviceD2) ? TRUE : FALSE;
404
405 deviceCapabilities->WakeFromD0 = FALSE;
406 deviceCapabilities->WakeFromD1 = TRUE; //Yes we can
407 deviceCapabilities->WakeFromD2 = FALSE;
408 deviceCapabilities->WakeFromD3 = FALSE;
409
410 if (device)
411 {
412 deviceCapabilities->LockSupported = device->flags.lockable;
413 deviceCapabilities->EjectSupported = device->flags.ejectable;
414 deviceCapabilities->HardwareDisabled = !device->status.enabled && !device->status.functional;
415 deviceCapabilities->Removable = device->flags.removable;
416 deviceCapabilities->SurpriseRemovalOK = device->flags.surprise_removal_ok;
417 deviceCapabilities->UniqueID = device->flags.unique_id;
418 deviceCapabilities->NoDisplayInUI = !device->status.show_in_ui;
419 deviceCapabilities->Address = device->pnp.bus_address;
420 }
421
422 if (!device ||
423 (device->flags.hardware_id &&
424 (strstr(device->pnp.hardware_id, ACPI_BUTTON_HID_LID) ||
425 strstr(device->pnp.hardware_id, ACPI_THERMAL_HID) ||
426 strstr(device->pnp.hardware_id, ACPI_PROCESSOR_HID))))
427 {
428 /* Allow ACPI to control the device if it is a lid button,
429 * a thermal zone, a processor, or a fixed feature button */
430 deviceCapabilities->RawDeviceOK = TRUE;
431 }
432
433 deviceCapabilities->SilentInstall = FALSE;
434 deviceCapabilities->UINumber = (ULONG)-1;
435
436 return STATUS_SUCCESS;
437
438 }
439
440 NTSTATUS
Bus_PDO_QueryDeviceId(PPDO_DEVICE_DATA DeviceData,PIRP Irp)441 Bus_PDO_QueryDeviceId(
442 PPDO_DEVICE_DATA DeviceData,
443 PIRP Irp )
444 {
445 PIO_STACK_LOCATION stack;
446 PWCHAR buffer, src;
447 WCHAR temp[256];
448 ULONG length, i;
449 NTSTATUS status = STATUS_SUCCESS;
450 struct acpi_device *Device;
451
452 PAGED_CODE ();
453
454 stack = IoGetCurrentIrpStackLocation (Irp);
455
456 switch (stack->Parameters.QueryId.IdType) {
457
458 case BusQueryDeviceID:
459
460 /* This is a REG_SZ value */
461
462 if (DeviceData->AcpiHandle)
463 {
464 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
465
466 if (strcmp(Device->pnp.hardware_id, "Processor") == 0)
467 {
468 length = wcslen(ProcessorIdString);
469 wcscpy(temp, ProcessorIdString);
470 }
471 else
472 {
473 length = swprintf(temp,
474 L"ACPI\\%hs",
475 Device->pnp.hardware_id);
476 }
477 }
478 else
479 {
480 /* We know it's a fixed feature button because
481 * these are direct children of the ACPI root device
482 * and therefore have no handle
483 */
484 length = swprintf(temp,
485 L"ACPI\\FixedButton");
486 }
487
488 temp[length++] = UNICODE_NULL;
489
490 NT_ASSERT(length * sizeof(WCHAR) <= sizeof(temp));
491
492 buffer = ExAllocatePoolWithTag(PagedPool, length * sizeof(WCHAR), 'IpcA');
493
494 if (!buffer) {
495 status = STATUS_INSUFFICIENT_RESOURCES;
496 break;
497 }
498
499 RtlCopyMemory (buffer, temp, length * sizeof(WCHAR));
500 Irp->IoStatus.Information = (ULONG_PTR) buffer;
501 DPRINT("BusQueryDeviceID: %ls\n",buffer);
502 break;
503
504 case BusQueryInstanceID:
505
506 /* This is a REG_SZ value */
507
508 /* See comment in BusQueryDeviceID case */
509 if(DeviceData->AcpiHandle)
510 {
511 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
512
513 if (Device->flags.unique_id)
514 length = swprintf(temp,
515 L"%hs",
516 Device->pnp.unique_id);
517 else
518 /* FIXME: Generate unique id! */
519 length = swprintf(temp, L"%ls", L"0");
520 }
521 else
522 {
523 /* FIXME: Generate unique id! */
524 length = swprintf(temp, L"%ls", L"0");
525 }
526
527 temp[length++] = UNICODE_NULL;
528
529 NT_ASSERT(length * sizeof(WCHAR) <= sizeof(temp));
530
531 buffer = ExAllocatePoolWithTag(PagedPool, length * sizeof(WCHAR), 'IpcA');
532 if (!buffer) {
533 status = STATUS_INSUFFICIENT_RESOURCES;
534 break;
535 }
536
537 RtlCopyMemory (buffer, temp, length * sizeof (WCHAR));
538 DPRINT("BusQueryInstanceID: %ls\n",buffer);
539 Irp->IoStatus.Information = (ULONG_PTR) buffer;
540 break;
541
542 case BusQueryHardwareIDs:
543
544 /* This is a REG_MULTI_SZ value */
545 length = 0;
546 status = STATUS_NOT_SUPPORTED;
547
548 /* See comment in BusQueryDeviceID case */
549 if (DeviceData->AcpiHandle)
550 {
551 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
552
553 if (!Device->flags.hardware_id)
554 {
555 /* We don't have the ID to satisfy this request */
556 break;
557 }
558
559 DPRINT("Device name: %s\n", Device->pnp.device_name);
560 DPRINT("Hardware ID: %s\n", Device->pnp.hardware_id);
561
562 if (strcmp(Device->pnp.hardware_id, "Processor") == 0)
563 {
564 length = ProcessorHardwareIds.Length / sizeof(WCHAR);
565 src = ProcessorHardwareIds.Buffer;
566 }
567 else
568 {
569 length += swprintf(&temp[length],
570 L"ACPI\\%hs",
571 Device->pnp.hardware_id);
572 temp[length++] = UNICODE_NULL;
573
574 length += swprintf(&temp[length],
575 L"*%hs",
576 Device->pnp.hardware_id);
577 temp[length++] = UNICODE_NULL;
578 temp[length++] = UNICODE_NULL;
579 src = temp;
580 }
581 }
582 else
583 {
584 length += swprintf(&temp[length],
585 L"ACPI\\FixedButton");
586 temp[length++] = UNICODE_NULL;
587
588 length += swprintf(&temp[length],
589 L"*FixedButton");
590 temp[length++] = UNICODE_NULL;
591 temp[length++] = UNICODE_NULL;
592 src = temp;
593 }
594
595 NT_ASSERT(length * sizeof(WCHAR) <= sizeof(temp));
596
597 buffer = ExAllocatePoolWithTag(PagedPool, length * sizeof(WCHAR), 'IpcA');
598
599 if (!buffer) {
600 status = STATUS_INSUFFICIENT_RESOURCES;
601 break;
602 }
603
604 RtlCopyMemory (buffer, src, length * sizeof(WCHAR));
605 Irp->IoStatus.Information = (ULONG_PTR) buffer;
606 DPRINT("BusQueryHardwareIDs: %ls\n",buffer);
607 status = STATUS_SUCCESS;
608 break;
609
610 case BusQueryCompatibleIDs:
611
612 /* This is a REG_MULTI_SZ value */
613 length = 0;
614 status = STATUS_NOT_SUPPORTED;
615
616 /* See comment in BusQueryDeviceID case */
617 if (DeviceData->AcpiHandle)
618 {
619 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
620
621 if (!Device->flags.hardware_id)
622 {
623 /* We don't have the ID to satisfy this request */
624 break;
625 }
626
627 DPRINT("Device name: %s\n", Device->pnp.device_name);
628 DPRINT("Hardware ID: %s\n", Device->pnp.hardware_id);
629
630 if (strcmp(Device->pnp.hardware_id, "Processor") == 0)
631 {
632 length += swprintf(&temp[length],
633 L"ACPI\\%hs",
634 Device->pnp.hardware_id);
635 temp[length++] = UNICODE_NULL;
636
637 length += swprintf(&temp[length],
638 L"*%hs",
639 Device->pnp.hardware_id);
640 temp[length++] = UNICODE_NULL;
641 temp[length++] = UNICODE_NULL;
642 }
643 else if (Device->flags.compatible_ids)
644 {
645 for (i = 0; i < Device->pnp.cid_list->Count; i++)
646 {
647 length += swprintf(&temp[length],
648 L"ACPI\\%hs",
649 Device->pnp.cid_list->Ids[i].String);
650 temp[length++] = UNICODE_NULL;
651
652 length += swprintf(&temp[length],
653 L"*%hs",
654 Device->pnp.cid_list->Ids[i].String);
655 temp[length++] = UNICODE_NULL;
656 }
657
658 temp[length++] = UNICODE_NULL;
659 }
660 else
661 {
662 /* No compatible IDs */
663 break;
664 }
665
666 NT_ASSERT(length * sizeof(WCHAR) <= sizeof(temp));
667
668 buffer = ExAllocatePoolWithTag(PagedPool, length * sizeof(WCHAR), 'IpcA');
669 if (!buffer)
670 {
671 status = STATUS_INSUFFICIENT_RESOURCES;
672 break;
673 }
674
675 RtlCopyMemory (buffer, temp, length * sizeof(WCHAR));
676 Irp->IoStatus.Information = (ULONG_PTR) buffer;
677 DPRINT("BusQueryCompatibleIDs: %ls\n",buffer);
678 status = STATUS_SUCCESS;
679 }
680 break;
681
682 default:
683 status = Irp->IoStatus.Status;
684 }
685 return status;
686 }
687
688 NTSTATUS
Bus_PDO_QueryDeviceText(PPDO_DEVICE_DATA DeviceData,PIRP Irp)689 Bus_PDO_QueryDeviceText(
690 PPDO_DEVICE_DATA DeviceData,
691 PIRP Irp )
692 {
693 PWCHAR Buffer, Temp;
694 PIO_STACK_LOCATION stack;
695 NTSTATUS status = Irp->IoStatus.Status;
696 PAGED_CODE ();
697
698 stack = IoGetCurrentIrpStackLocation (Irp);
699
700 switch (stack->Parameters.QueryDeviceText.DeviceTextType) {
701
702 case DeviceTextDescription:
703
704 if (!Irp->IoStatus.Information) {
705 if (wcsstr (DeviceData->HardwareIDs, L"PNP000") != 0)
706 Temp = L"Programmable interrupt controller";
707 else if (wcsstr(DeviceData->HardwareIDs, L"PNP010") != 0)
708 Temp = L"System timer";
709 else if (wcsstr(DeviceData->HardwareIDs, L"PNP020") != 0)
710 Temp = L"DMA controller";
711 else if (wcsstr(DeviceData->HardwareIDs, L"PNP03") != 0)
712 Temp = L"Keyboard";
713 else if (wcsstr(DeviceData->HardwareIDs, L"PNP040") != 0)
714 Temp = L"Parallel port";
715 else if (wcsstr(DeviceData->HardwareIDs, L"PNP05") != 0)
716 Temp = L"Serial port";
717 else if (wcsstr(DeviceData->HardwareIDs, L"PNP06") != 0)
718 Temp = L"Disk controller";
719 else if (wcsstr(DeviceData->HardwareIDs, L"PNP07") != 0)
720 Temp = L"Disk controller";
721 else if (wcsstr(DeviceData->HardwareIDs, L"PNP09") != 0)
722 Temp = L"Display adapter";
723 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0A0") != 0)
724 Temp = L"Bus controller";
725 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0E0") != 0)
726 Temp = L"PCMCIA controller";
727 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0F") != 0)
728 Temp = L"Mouse device";
729 else if (wcsstr(DeviceData->HardwareIDs, L"PNP8") != 0)
730 Temp = L"Network adapter";
731 else if (wcsstr(DeviceData->HardwareIDs, L"PNPA0") != 0)
732 Temp = L"SCSI controller";
733 else if (wcsstr(DeviceData->HardwareIDs, L"PNPB0") != 0)
734 Temp = L"Multimedia device";
735 else if (wcsstr(DeviceData->HardwareIDs, L"PNPC00") != 0)
736 Temp = L"Modem";
737 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0C") != 0)
738 Temp = L"Power Button";
739 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0E") != 0)
740 Temp = L"Sleep Button";
741 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0D") != 0)
742 Temp = L"Lid Switch";
743 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C09") != 0)
744 Temp = L"ACPI Embedded Controller";
745 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0B") != 0)
746 Temp = L"ACPI Fan";
747 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0A03") != 0 ||
748 wcsstr(DeviceData->HardwareIDs, L"PNP0A08") != 0)
749 Temp = L"PCI Root Bridge";
750 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0A") != 0)
751 Temp = L"ACPI Battery";
752 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0F") != 0)
753 Temp = L"PCI Interrupt Link";
754 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI_PWR") != 0)
755 Temp = L"ACPI Power Resource";
756 else if (wcsstr(DeviceData->HardwareIDs, L"Processor") != 0)
757 {
758 if (ProcessorNameString != NULL)
759 Temp = ProcessorNameString;
760 else
761 Temp = L"Processor";
762 }
763 else if (wcsstr(DeviceData->HardwareIDs, L"ThermalZone") != 0)
764 Temp = L"ACPI Thermal Zone";
765 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI0002") != 0)
766 Temp = L"Smart Battery";
767 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI0003") != 0)
768 Temp = L"AC Adapter";
769 /* Simply checking if AcpiHandle is NULL eliminates the need to check
770 * for the 4 different names that ACPI knows the fixed feature button as internally
771 */
772 else if (!DeviceData->AcpiHandle)
773 Temp = L"ACPI Fixed Feature Button";
774 else
775 Temp = L"Other ACPI device";
776
777 Buffer = ExAllocatePoolWithTag(PagedPool, (wcslen(Temp) + 1) * sizeof(WCHAR), 'IpcA');
778
779 if (!Buffer) {
780 status = STATUS_INSUFFICIENT_RESOURCES;
781 break;
782 }
783
784 RtlCopyMemory (Buffer, Temp, (wcslen(Temp) + 1) * sizeof(WCHAR));
785
786 DPRINT("\tDeviceTextDescription :%ws\n", Buffer);
787
788 Irp->IoStatus.Information = (ULONG_PTR) Buffer;
789 status = STATUS_SUCCESS;
790 }
791 break;
792
793 default:
794 break;
795 }
796
797 return status;
798
799 }
800
801 NTSTATUS
Bus_PDO_QueryResources(PPDO_DEVICE_DATA DeviceData,PIRP Irp)802 Bus_PDO_QueryResources(
803 PPDO_DEVICE_DATA DeviceData,
804 PIRP Irp )
805 {
806 ULONG NumberOfResources = 0;
807 PCM_RESOURCE_LIST ResourceList;
808 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
809 ACPI_STATUS AcpiStatus;
810 ACPI_BUFFER Buffer;
811 ACPI_RESOURCE* resource;
812 ULONG ResourceListSize;
813 ULONG i;
814 ULONGLONG BusNumber;
815 struct acpi_device *device;
816
817 if (!DeviceData->AcpiHandle)
818 {
819 return Irp->IoStatus.Status;
820 }
821
822 /* A bus number resource is not included in the list of current resources
823 * for the root PCI bus so we manually query one here and if we find it
824 * we create a resource list and add a bus number descriptor to it */
825 if (wcsstr(DeviceData->HardwareIDs, L"PNP0A03") != 0 ||
826 wcsstr(DeviceData->HardwareIDs, L"PNP0A08") != 0)
827 {
828 acpi_bus_get_device(DeviceData->AcpiHandle, &device);
829
830 AcpiStatus = acpi_evaluate_integer(DeviceData->AcpiHandle, "_BBN", NULL, &BusNumber);
831 if (AcpiStatus != AE_OK)
832 {
833 #if 0
834 if (device->flags.unique_id)
835 {
836 /* FIXME: Try the unique ID */
837 }
838 else
839 #endif
840 {
841 BusNumber = 0;
842 DPRINT1("Failed to find a bus number\n");
843 }
844 }
845 else
846 {
847 DPRINT("Using _BBN for bus number\n");
848 }
849
850 DPRINT("Found PCI root hub: %d\n", BusNumber);
851
852 ResourceListSize = sizeof(CM_RESOURCE_LIST);
853 ResourceList = ExAllocatePoolWithTag(PagedPool, ResourceListSize, 'RpcA');
854 if (!ResourceList)
855 return STATUS_INSUFFICIENT_RESOURCES;
856
857 ResourceList->Count = 1;
858 ResourceList->List[0].InterfaceType = Internal;
859 ResourceList->List[0].BusNumber = 0;
860 ResourceList->List[0].PartialResourceList.Version = 1;
861 ResourceList->List[0].PartialResourceList.Revision = 1;
862 ResourceList->List[0].PartialResourceList.Count = 1;
863 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
864
865 ResourceDescriptor->Type = CmResourceTypeBusNumber;
866 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
867 ResourceDescriptor->u.BusNumber.Start = BusNumber;
868 ResourceDescriptor->u.BusNumber.Length = 1;
869
870 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
871 return STATUS_SUCCESS;
872 }
873
874 /* Get current resources */
875 Buffer.Length = 0;
876 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
877 if ((!ACPI_SUCCESS(AcpiStatus) && AcpiStatus != AE_BUFFER_OVERFLOW) ||
878 Buffer.Length == 0)
879 {
880 return Irp->IoStatus.Status;
881 }
882
883 Buffer.Pointer = ExAllocatePoolWithTag(PagedPool, Buffer.Length, 'BpcA');
884 if (!Buffer.Pointer)
885 return STATUS_INSUFFICIENT_RESOURCES;
886
887 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
888 if (!ACPI_SUCCESS(AcpiStatus))
889 {
890 DPRINT1("AcpiGetCurrentResources #2 failed (0x%x)\n", AcpiStatus);
891 ASSERT(FALSE);
892 return STATUS_UNSUCCESSFUL;
893 }
894
895 resource= Buffer.Pointer;
896 /* Count number of resources */
897 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
898 {
899 switch (resource->Type)
900 {
901 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
902 {
903 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
904 if (irq_data->ProducerConsumer == ACPI_PRODUCER)
905 break;
906 NumberOfResources += irq_data->InterruptCount;
907 break;
908 }
909 case ACPI_RESOURCE_TYPE_IRQ:
910 {
911 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
912 NumberOfResources += irq_data->InterruptCount;
913 break;
914 }
915 case ACPI_RESOURCE_TYPE_DMA:
916 {
917 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
918 NumberOfResources += dma_data->ChannelCount;
919 break;
920 }
921 case ACPI_RESOURCE_TYPE_ADDRESS16:
922 case ACPI_RESOURCE_TYPE_ADDRESS32:
923 case ACPI_RESOURCE_TYPE_ADDRESS64:
924 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
925 {
926 ACPI_RESOURCE_ADDRESS *addr_res = (ACPI_RESOURCE_ADDRESS*) &resource->Data;
927 if (addr_res->ProducerConsumer == ACPI_PRODUCER)
928 break;
929 NumberOfResources++;
930 break;
931 }
932 case ACPI_RESOURCE_TYPE_MEMORY24:
933 case ACPI_RESOURCE_TYPE_MEMORY32:
934 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
935 case ACPI_RESOURCE_TYPE_FIXED_IO:
936 case ACPI_RESOURCE_TYPE_IO:
937 {
938 NumberOfResources++;
939 break;
940 }
941 default:
942 {
943 DPRINT1("Unknown resource type: %d\n", resource->Type);
944 break;
945 }
946 }
947 resource = ACPI_NEXT_RESOURCE(resource);
948 }
949
950 /* Allocate memory */
951 ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
952 ResourceList = ExAllocatePoolWithTag(PagedPool, ResourceListSize, 'RpcA');
953
954 if (!ResourceList)
955 {
956 ExFreePoolWithTag(Buffer.Pointer, 'BpcA');
957 return STATUS_INSUFFICIENT_RESOURCES;
958 }
959 ResourceList->Count = 1;
960 ResourceList->List[0].InterfaceType = Internal; /* FIXME */
961 ResourceList->List[0].BusNumber = 0; /* We're the only ACPI bus device in the system */
962 ResourceList->List[0].PartialResourceList.Version = 1;
963 ResourceList->List[0].PartialResourceList.Revision = 1;
964 ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
965 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
966
967 /* Fill resources list structure */
968 resource = Buffer.Pointer;
969 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
970 {
971 switch (resource->Type)
972 {
973 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
974 {
975 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
976 if (irq_data->ProducerConsumer == ACPI_PRODUCER)
977 break;
978 for (i = 0; i < irq_data->InterruptCount; i++)
979 {
980 ResourceDescriptor->Type = CmResourceTypeInterrupt;
981
982 ResourceDescriptor->ShareDisposition =
983 (irq_data->Shareable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
984 ResourceDescriptor->Flags =
985 (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
986 ResourceDescriptor->u.Interrupt.Level =
987 ResourceDescriptor->u.Interrupt.Vector = irq_data->Interrupts[i];
988 ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
989
990 ResourceDescriptor++;
991 }
992 break;
993 }
994 case ACPI_RESOURCE_TYPE_IRQ:
995 {
996 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
997 for (i = 0; i < irq_data->InterruptCount; i++)
998 {
999 ResourceDescriptor->Type = CmResourceTypeInterrupt;
1000
1001 ResourceDescriptor->ShareDisposition =
1002 (irq_data->Shareable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
1003 ResourceDescriptor->Flags =
1004 (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
1005 ResourceDescriptor->u.Interrupt.Level =
1006 ResourceDescriptor->u.Interrupt.Vector = irq_data->Interrupts[i];
1007 ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
1008
1009 ResourceDescriptor++;
1010 }
1011 break;
1012 }
1013 case ACPI_RESOURCE_TYPE_DMA:
1014 {
1015 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
1016 for (i = 0; i < dma_data->ChannelCount; i++)
1017 {
1018 ResourceDescriptor->Type = CmResourceTypeDma;
1019 ResourceDescriptor->Flags = 0;
1020 switch (dma_data->Type)
1021 {
1022 case ACPI_TYPE_A: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
1023 case ACPI_TYPE_B: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
1024 case ACPI_TYPE_F: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
1025 }
1026 if (dma_data->BusMaster == ACPI_BUS_MASTER)
1027 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
1028 switch (dma_data->Transfer)
1029 {
1030 case ACPI_TRANSFER_8: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
1031 case ACPI_TRANSFER_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
1032 case ACPI_TRANSFER_8_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
1033 }
1034 ResourceDescriptor->u.Dma.Channel = dma_data->Channels[i];
1035
1036 ResourceDescriptor++;
1037 }
1038 break;
1039 }
1040 case ACPI_RESOURCE_TYPE_IO:
1041 {
1042 ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &resource->Data;
1043 ResourceDescriptor->Type = CmResourceTypePort;
1044 ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1045 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1046 if (io_data->IoDecode == ACPI_DECODE_16)
1047 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
1048 else
1049 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
1050 ResourceDescriptor->u.Port.Start.QuadPart = io_data->Minimum;
1051 ResourceDescriptor->u.Port.Length = io_data->AddressLength;
1052
1053 ResourceDescriptor++;
1054 break;
1055 }
1056 case ACPI_RESOURCE_TYPE_FIXED_IO:
1057 {
1058 ACPI_RESOURCE_FIXED_IO *io_data = (ACPI_RESOURCE_FIXED_IO*) &resource->Data;
1059 ResourceDescriptor->Type = CmResourceTypePort;
1060 ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1061 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1062 ResourceDescriptor->u.Port.Start.QuadPart = io_data->Address;
1063 ResourceDescriptor->u.Port.Length = io_data->AddressLength;
1064
1065 ResourceDescriptor++;
1066 break;
1067 }
1068 case ACPI_RESOURCE_TYPE_ADDRESS16:
1069 {
1070 ACPI_RESOURCE_ADDRESS16 *addr16_data = (ACPI_RESOURCE_ADDRESS16*) &resource->Data;
1071 if (addr16_data->ProducerConsumer == ACPI_PRODUCER)
1072 break;
1073 if (addr16_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1074 {
1075 ResourceDescriptor->Type = CmResourceTypeBusNumber;
1076 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
1077 ResourceDescriptor->Flags = 0;
1078 ResourceDescriptor->u.BusNumber.Start = addr16_data->Address.Minimum;
1079 ResourceDescriptor->u.BusNumber.Length = addr16_data->Address.AddressLength;
1080 }
1081 else if (addr16_data->ResourceType == ACPI_IO_RANGE)
1082 {
1083 ResourceDescriptor->Type = CmResourceTypePort;
1084 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1085 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1086 if (addr16_data->Decode == ACPI_POS_DECODE)
1087 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1088 ResourceDescriptor->u.Port.Start.QuadPart = addr16_data->Address.Minimum;
1089 ResourceDescriptor->u.Port.Length = addr16_data->Address.AddressLength;
1090 }
1091 else
1092 {
1093 ResourceDescriptor->Type = CmResourceTypeMemory;
1094 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1095 ResourceDescriptor->Flags = 0;
1096 if (addr16_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1097 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1098 else
1099 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1100 switch (addr16_data->Info.Mem.Caching)
1101 {
1102 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1103 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1104 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1105 }
1106 ResourceDescriptor->u.Memory.Start.QuadPart = addr16_data->Address.Minimum;
1107 ResourceDescriptor->u.Memory.Length = addr16_data->Address.AddressLength;
1108 }
1109 ResourceDescriptor++;
1110 break;
1111 }
1112 case ACPI_RESOURCE_TYPE_ADDRESS32:
1113 {
1114 ACPI_RESOURCE_ADDRESS32 *addr32_data = (ACPI_RESOURCE_ADDRESS32*) &resource->Data;
1115 if (addr32_data->ProducerConsumer == ACPI_PRODUCER)
1116 break;
1117 if (addr32_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1118 {
1119 ResourceDescriptor->Type = CmResourceTypeBusNumber;
1120 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
1121 ResourceDescriptor->Flags = 0;
1122 ResourceDescriptor->u.BusNumber.Start = addr32_data->Address.Minimum;
1123 ResourceDescriptor->u.BusNumber.Length = addr32_data->Address.AddressLength;
1124 }
1125 else if (addr32_data->ResourceType == ACPI_IO_RANGE)
1126 {
1127 ResourceDescriptor->Type = CmResourceTypePort;
1128 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1129 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1130 if (addr32_data->Decode == ACPI_POS_DECODE)
1131 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1132 ResourceDescriptor->u.Port.Start.QuadPart = addr32_data->Address.Minimum;
1133 ResourceDescriptor->u.Port.Length = addr32_data->Address.AddressLength;
1134 }
1135 else
1136 {
1137 ResourceDescriptor->Type = CmResourceTypeMemory;
1138 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1139 ResourceDescriptor->Flags = 0;
1140 if (addr32_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1141 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1142 else
1143 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1144 switch (addr32_data->Info.Mem.Caching)
1145 {
1146 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1147 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1148 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1149 }
1150 ResourceDescriptor->u.Memory.Start.QuadPart = addr32_data->Address.Minimum;
1151 ResourceDescriptor->u.Memory.Length = addr32_data->Address.AddressLength;
1152 }
1153 ResourceDescriptor++;
1154 break;
1155 }
1156 case ACPI_RESOURCE_TYPE_ADDRESS64:
1157 {
1158 ACPI_RESOURCE_ADDRESS64 *addr64_data = (ACPI_RESOURCE_ADDRESS64*) &resource->Data;
1159 if (addr64_data->ProducerConsumer == ACPI_PRODUCER)
1160 break;
1161 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1162 {
1163 DPRINT1("64-bit bus address is not supported!\n");
1164 ResourceDescriptor->Type = CmResourceTypeBusNumber;
1165 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
1166 ResourceDescriptor->Flags = 0;
1167 ResourceDescriptor->u.BusNumber.Start = (ULONG)addr64_data->Address.Minimum;
1168 ResourceDescriptor->u.BusNumber.Length = addr64_data->Address.AddressLength;
1169 }
1170 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1171 {
1172 ResourceDescriptor->Type = CmResourceTypePort;
1173 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1174 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1175 if (addr64_data->Decode == ACPI_POS_DECODE)
1176 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1177 ResourceDescriptor->u.Port.Start.QuadPart = addr64_data->Address.Minimum;
1178 ResourceDescriptor->u.Port.Length = addr64_data->Address.AddressLength;
1179 }
1180 else
1181 {
1182 ResourceDescriptor->Type = CmResourceTypeMemory;
1183 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1184 ResourceDescriptor->Flags = 0;
1185 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1186 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1187 else
1188 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1189 switch (addr64_data->Info.Mem.Caching)
1190 {
1191 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1192 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1193 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1194 }
1195 ResourceDescriptor->u.Memory.Start.QuadPart = addr64_data->Address.Minimum;
1196 ResourceDescriptor->u.Memory.Length = addr64_data->Address.AddressLength;
1197 }
1198 ResourceDescriptor++;
1199 break;
1200 }
1201 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1202 {
1203 ACPI_RESOURCE_EXTENDED_ADDRESS64 *addr64_data = (ACPI_RESOURCE_EXTENDED_ADDRESS64*) &resource->Data;
1204 if (addr64_data->ProducerConsumer == ACPI_PRODUCER)
1205 break;
1206 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1207 {
1208 DPRINT1("64-bit bus address is not supported!\n");
1209 ResourceDescriptor->Type = CmResourceTypeBusNumber;
1210 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
1211 ResourceDescriptor->Flags = 0;
1212 ResourceDescriptor->u.BusNumber.Start = (ULONG)addr64_data->Address.Minimum;
1213 ResourceDescriptor->u.BusNumber.Length = addr64_data->Address.AddressLength;
1214 }
1215 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1216 {
1217 ResourceDescriptor->Type = CmResourceTypePort;
1218 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1219 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1220 if (addr64_data->Decode == ACPI_POS_DECODE)
1221 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1222 ResourceDescriptor->u.Port.Start.QuadPart = addr64_data->Address.Minimum;
1223 ResourceDescriptor->u.Port.Length = addr64_data->Address.AddressLength;
1224 }
1225 else
1226 {
1227 ResourceDescriptor->Type = CmResourceTypeMemory;
1228 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1229 ResourceDescriptor->Flags = 0;
1230 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1231 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1232 else
1233 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1234 switch (addr64_data->Info.Mem.Caching)
1235 {
1236 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1237 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1238 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1239 }
1240 ResourceDescriptor->u.Memory.Start.QuadPart = addr64_data->Address.Minimum;
1241 ResourceDescriptor->u.Memory.Length = addr64_data->Address.AddressLength;
1242 }
1243 ResourceDescriptor++;
1244 break;
1245 }
1246 case ACPI_RESOURCE_TYPE_MEMORY24:
1247 {
1248 ACPI_RESOURCE_MEMORY24 *mem24_data = (ACPI_RESOURCE_MEMORY24*) &resource->Data;
1249 ResourceDescriptor->Type = CmResourceTypeMemory;
1250 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1251 ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_24;
1252 if (mem24_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1253 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1254 else
1255 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1256 ResourceDescriptor->u.Memory.Start.QuadPart = mem24_data->Minimum;
1257 ResourceDescriptor->u.Memory.Length = mem24_data->AddressLength;
1258
1259 ResourceDescriptor++;
1260 break;
1261 }
1262 case ACPI_RESOURCE_TYPE_MEMORY32:
1263 {
1264 ACPI_RESOURCE_MEMORY32 *mem32_data = (ACPI_RESOURCE_MEMORY32*) &resource->Data;
1265 ResourceDescriptor->Type = CmResourceTypeMemory;
1266 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1267 ResourceDescriptor->Flags = 0;
1268 if (mem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1269 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1270 else
1271 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1272 ResourceDescriptor->u.Memory.Start.QuadPart = mem32_data->Minimum;
1273 ResourceDescriptor->u.Memory.Length = mem32_data->AddressLength;
1274
1275 ResourceDescriptor++;
1276 break;
1277 }
1278 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1279 {
1280 ACPI_RESOURCE_FIXED_MEMORY32 *memfixed32_data = (ACPI_RESOURCE_FIXED_MEMORY32*) &resource->Data;
1281 ResourceDescriptor->Type = CmResourceTypeMemory;
1282 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1283 ResourceDescriptor->Flags = 0;
1284 if (memfixed32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1285 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1286 else
1287 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1288 ResourceDescriptor->u.Memory.Start.QuadPart = memfixed32_data->Address;
1289 ResourceDescriptor->u.Memory.Length = memfixed32_data->AddressLength;
1290
1291 ResourceDescriptor++;
1292 break;
1293 }
1294 default:
1295 {
1296 break;
1297 }
1298 }
1299 resource = ACPI_NEXT_RESOURCE(resource);
1300 }
1301
1302 ExFreePoolWithTag(Buffer.Pointer, 'BpcA');
1303 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
1304 return STATUS_SUCCESS;
1305 }
1306 #endif /* UNIT_TEST */
1307
1308 NTSTATUS
Bus_PDO_QueryResourceRequirements(PPDO_DEVICE_DATA DeviceData,PIRP Irp)1309 Bus_PDO_QueryResourceRequirements(
1310 PPDO_DEVICE_DATA DeviceData,
1311 PIRP Irp )
1312 {
1313 ULONG NumberOfResources = 0;
1314 ACPI_STATUS AcpiStatus;
1315 ACPI_BUFFER Buffer;
1316 ACPI_RESOURCE* resource;
1317 ULONG i, RequirementsListSize;
1318 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
1319 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor;
1320 BOOLEAN CurrentRes = FALSE;
1321 BOOLEAN SeenStartDependent;
1322
1323 PAGED_CODE ();
1324
1325 if (!DeviceData->AcpiHandle)
1326 {
1327 return Irp->IoStatus.Status;
1328 }
1329
1330 /* Handle the PCI root manually */
1331 if (wcsstr(DeviceData->HardwareIDs, L"PNP0A03") != 0 ||
1332 wcsstr(DeviceData->HardwareIDs, L"PNP0A08") != 0)
1333 {
1334 return Irp->IoStatus.Status;
1335 }
1336
1337 /* Get current resources */
1338 while (TRUE)
1339 {
1340 Buffer.Length = 0;
1341 if (CurrentRes)
1342 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
1343 else
1344 AcpiStatus = AcpiGetPossibleResources(DeviceData->AcpiHandle, &Buffer);
1345 if ((!ACPI_SUCCESS(AcpiStatus) && AcpiStatus != AE_BUFFER_OVERFLOW) ||
1346 Buffer.Length == 0)
1347 {
1348 if (!CurrentRes)
1349 CurrentRes = TRUE;
1350 else
1351 return Irp->IoStatus.Status;
1352 }
1353 else
1354 break;
1355 }
1356
1357 Buffer.Pointer = ExAllocatePoolWithTag(PagedPool, Buffer.Length, 'BpcA');
1358 if (!Buffer.Pointer)
1359 return STATUS_INSUFFICIENT_RESOURCES;
1360
1361 if (CurrentRes)
1362 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
1363 else
1364 AcpiStatus = AcpiGetPossibleResources(DeviceData->AcpiHandle, &Buffer);
1365 if (!ACPI_SUCCESS(AcpiStatus))
1366 {
1367 DPRINT1("AcpiGetCurrentResources #2 failed (0x%x)\n", AcpiStatus);
1368 ASSERT(FALSE);
1369 return STATUS_UNSUCCESSFUL;
1370 }
1371
1372 SeenStartDependent = FALSE;
1373 resource = Buffer.Pointer;
1374 /* Count number of resources */
1375 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG && resource->Type != ACPI_RESOURCE_TYPE_END_DEPENDENT)
1376 {
1377 if (resource->Type == ACPI_RESOURCE_TYPE_START_DEPENDENT)
1378 {
1379 if (SeenStartDependent)
1380 {
1381 break;
1382 }
1383 SeenStartDependent = TRUE;
1384 }
1385 switch (resource->Type)
1386 {
1387 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1388 {
1389 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
1390 if (irq_data->ProducerConsumer == ACPI_PRODUCER)
1391 break;
1392 NumberOfResources += irq_data->InterruptCount;
1393 break;
1394 }
1395 case ACPI_RESOURCE_TYPE_IRQ:
1396 {
1397 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
1398 NumberOfResources += irq_data->InterruptCount;
1399 break;
1400 }
1401 case ACPI_RESOURCE_TYPE_DMA:
1402 {
1403 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
1404 NumberOfResources += dma_data->ChannelCount;
1405 break;
1406 }
1407 case ACPI_RESOURCE_TYPE_ADDRESS16:
1408 case ACPI_RESOURCE_TYPE_ADDRESS32:
1409 case ACPI_RESOURCE_TYPE_ADDRESS64:
1410 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1411 {
1412 ACPI_RESOURCE_ADDRESS *res_addr = (ACPI_RESOURCE_ADDRESS*) &resource->Data;
1413 if (res_addr->ProducerConsumer == ACPI_PRODUCER)
1414 break;
1415 NumberOfResources++;
1416 break;
1417 }
1418 case ACPI_RESOURCE_TYPE_MEMORY24:
1419 case ACPI_RESOURCE_TYPE_MEMORY32:
1420 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1421 case ACPI_RESOURCE_TYPE_FIXED_IO:
1422 case ACPI_RESOURCE_TYPE_IO:
1423 {
1424 NumberOfResources++;
1425 break;
1426 }
1427 default:
1428 {
1429 break;
1430 }
1431 }
1432 resource = ACPI_NEXT_RESOURCE(resource);
1433 }
1434
1435 RequirementsListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
1436 RequirementsList = ExAllocatePoolWithTag(PagedPool, RequirementsListSize, 'RpcA');
1437
1438 if (!RequirementsList)
1439 {
1440 ExFreePoolWithTag(Buffer.Pointer, 'BpcA');
1441 return STATUS_INSUFFICIENT_RESOURCES;
1442 }
1443 RequirementsList->ListSize = RequirementsListSize;
1444 RequirementsList->InterfaceType = Internal;
1445 RequirementsList->BusNumber = 0;
1446 RequirementsList->SlotNumber = 0; /* Not used by WDM drivers */
1447 RequirementsList->AlternativeLists = 1;
1448 RequirementsList->List[0].Version = 1;
1449 RequirementsList->List[0].Revision = 1;
1450 RequirementsList->List[0].Count = NumberOfResources;
1451 RequirementDescriptor = RequirementsList->List[0].Descriptors;
1452
1453 /* Fill resources list structure */
1454 SeenStartDependent = FALSE;
1455 resource = Buffer.Pointer;
1456 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG && resource->Type != ACPI_RESOURCE_TYPE_END_DEPENDENT)
1457 {
1458 if (resource->Type == ACPI_RESOURCE_TYPE_START_DEPENDENT)
1459 {
1460 if (SeenStartDependent)
1461 {
1462 break;
1463 }
1464 SeenStartDependent = TRUE;
1465 }
1466 switch (resource->Type)
1467 {
1468 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1469 {
1470 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = &resource->Data.ExtendedIrq;
1471 if (irq_data->ProducerConsumer == ACPI_PRODUCER)
1472 break;
1473 for (i = 0; i < irq_data->InterruptCount; i++)
1474 {
1475 RequirementDescriptor->Option = (i == 0) ? IO_RESOURCE_PREFERRED : IO_RESOURCE_ALTERNATIVE;
1476 RequirementDescriptor->Type = CmResourceTypeInterrupt;
1477 RequirementDescriptor->ShareDisposition = (irq_data->Shareable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
1478 RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
1479 RequirementDescriptor->u.Interrupt.MinimumVector =
1480 RequirementDescriptor->u.Interrupt.MaximumVector = irq_data->Interrupts[i];
1481
1482 RequirementDescriptor++;
1483 }
1484 break;
1485 }
1486 case ACPI_RESOURCE_TYPE_IRQ:
1487 {
1488 ACPI_RESOURCE_IRQ *irq_data = &resource->Data.Irq;
1489 for (i = 0; i < irq_data->InterruptCount; i++)
1490 {
1491 RequirementDescriptor->Option = (i == 0) ? IO_RESOURCE_PREFERRED : IO_RESOURCE_ALTERNATIVE;
1492 RequirementDescriptor->Type = CmResourceTypeInterrupt;
1493 RequirementDescriptor->ShareDisposition = (irq_data->Shareable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
1494 RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
1495 RequirementDescriptor->u.Interrupt.MinimumVector =
1496 RequirementDescriptor->u.Interrupt.MaximumVector = irq_data->Interrupts[i];
1497
1498 RequirementDescriptor++;
1499 }
1500 break;
1501 }
1502 case ACPI_RESOURCE_TYPE_DMA:
1503 {
1504 ACPI_RESOURCE_DMA *dma_data = &resource->Data.Dma;
1505 for (i = 0; i < dma_data->ChannelCount; i++)
1506 {
1507 RequirementDescriptor->Type = CmResourceTypeDma;
1508 RequirementDescriptor->Flags = 0;
1509 switch (dma_data->Type)
1510 {
1511 case ACPI_TYPE_A: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
1512 case ACPI_TYPE_B: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
1513 case ACPI_TYPE_F: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
1514 }
1515 if (dma_data->BusMaster == ACPI_BUS_MASTER)
1516 RequirementDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
1517 switch (dma_data->Transfer)
1518 {
1519 case ACPI_TRANSFER_8: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
1520 case ACPI_TRANSFER_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
1521 case ACPI_TRANSFER_8_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
1522 }
1523
1524 RequirementDescriptor->Option = (i == 0) ? IO_RESOURCE_PREFERRED : IO_RESOURCE_ALTERNATIVE;
1525 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1526 RequirementDescriptor->u.Dma.MinimumChannel =
1527 RequirementDescriptor->u.Dma.MaximumChannel = dma_data->Channels[i];
1528 RequirementDescriptor++;
1529 }
1530 break;
1531 }
1532 case ACPI_RESOURCE_TYPE_IO:
1533 {
1534 ACPI_RESOURCE_IO *io_data = &resource->Data.Io;
1535 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1536 if (io_data->IoDecode == ACPI_DECODE_16)
1537 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
1538 else
1539 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
1540 RequirementDescriptor->u.Port.Length = io_data->AddressLength;
1541 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1542 RequirementDescriptor->Type = CmResourceTypePort;
1543 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1544 RequirementDescriptor->u.Port.Alignment = io_data->Alignment;
1545 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = io_data->Minimum;
1546 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = io_data->Maximum + io_data->AddressLength - 1;
1547
1548 RequirementDescriptor++;
1549 break;
1550 }
1551 case ACPI_RESOURCE_TYPE_FIXED_IO:
1552 {
1553 ACPI_RESOURCE_FIXED_IO *io_data = &resource->Data.FixedIo;
1554 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1555 RequirementDescriptor->u.Port.Length = io_data->AddressLength;
1556 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1557 RequirementDescriptor->Type = CmResourceTypePort;
1558 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1559 RequirementDescriptor->u.Port.Alignment = 1;
1560 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = io_data->Address;
1561 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = io_data->Address + io_data->AddressLength - 1;
1562
1563 RequirementDescriptor++;
1564 break;
1565 }
1566 case ACPI_RESOURCE_TYPE_ADDRESS16:
1567 {
1568 ACPI_RESOURCE_ADDRESS16 *addr16_data = &resource->Data.Address16;
1569 if (addr16_data->ProducerConsumer == ACPI_PRODUCER)
1570 break;
1571 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1572 if (addr16_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1573 {
1574 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1575 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1576 RequirementDescriptor->Flags = 0;
1577 RequirementDescriptor->u.BusNumber.MinBusNumber = addr16_data->Address.Minimum;
1578 RequirementDescriptor->u.BusNumber.MaxBusNumber = addr16_data->Address.Maximum + addr16_data->Address.AddressLength - 1;
1579 RequirementDescriptor->u.BusNumber.Length = addr16_data->Address.AddressLength;
1580 }
1581 else if (addr16_data->ResourceType == ACPI_IO_RANGE)
1582 {
1583 RequirementDescriptor->Type = CmResourceTypePort;
1584 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1585 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1586 if (addr16_data->Decode == ACPI_POS_DECODE)
1587 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1588 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr16_data->Address.Minimum;
1589 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr16_data->Address.Maximum + addr16_data->Address.AddressLength - 1;
1590 RequirementDescriptor->u.Port.Length = addr16_data->Address.AddressLength;
1591 }
1592 else
1593 {
1594 RequirementDescriptor->Type = CmResourceTypeMemory;
1595 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1596 RequirementDescriptor->Flags = 0;
1597 if (addr16_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1598 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1599 else
1600 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1601 switch (addr16_data->Info.Mem.Caching)
1602 {
1603 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1604 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1605 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1606 }
1607 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr16_data->Address.Minimum;
1608 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr16_data->Address.Maximum + addr16_data->Address.AddressLength - 1;
1609 RequirementDescriptor->u.Memory.Length = addr16_data->Address.AddressLength;
1610 }
1611 RequirementDescriptor++;
1612 break;
1613 }
1614 case ACPI_RESOURCE_TYPE_ADDRESS32:
1615 {
1616 ACPI_RESOURCE_ADDRESS32 *addr32_data = &resource->Data.Address32;
1617 if (addr32_data->ProducerConsumer == ACPI_PRODUCER)
1618 break;
1619 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1620 if (addr32_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1621 {
1622 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1623 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1624 RequirementDescriptor->Flags = 0;
1625 RequirementDescriptor->u.BusNumber.MinBusNumber = addr32_data->Address.Minimum;
1626 RequirementDescriptor->u.BusNumber.MaxBusNumber = addr32_data->Address.Maximum + addr32_data->Address.AddressLength - 1;
1627 RequirementDescriptor->u.BusNumber.Length = addr32_data->Address.AddressLength;
1628 }
1629 else if (addr32_data->ResourceType == ACPI_IO_RANGE)
1630 {
1631 RequirementDescriptor->Type = CmResourceTypePort;
1632 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1633 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1634 if (addr32_data->Decode == ACPI_POS_DECODE)
1635 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1636 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr32_data->Address.Minimum;
1637 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr32_data->Address.Maximum + addr32_data->Address.AddressLength - 1;
1638 RequirementDescriptor->u.Port.Length = addr32_data->Address.AddressLength;
1639 }
1640 else
1641 {
1642 RequirementDescriptor->Type = CmResourceTypeMemory;
1643 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1644 RequirementDescriptor->Flags = 0;
1645 if (addr32_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1646 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1647 else
1648 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1649 switch (addr32_data->Info.Mem.Caching)
1650 {
1651 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1652 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1653 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1654 }
1655 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr32_data->Address.Minimum;
1656 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr32_data->Address.Maximum + addr32_data->Address.AddressLength - 1;
1657 RequirementDescriptor->u.Memory.Length = addr32_data->Address.AddressLength;
1658 }
1659 RequirementDescriptor++;
1660 break;
1661 }
1662 case ACPI_RESOURCE_TYPE_ADDRESS64:
1663 {
1664 ACPI_RESOURCE_ADDRESS64 *addr64_data = &resource->Data.Address64;
1665 if (addr64_data->ProducerConsumer == ACPI_PRODUCER)
1666 break;
1667 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1668 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1669 {
1670 DPRINT1("64-bit bus address is not supported!\n");
1671 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1672 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1673 RequirementDescriptor->Flags = 0;
1674 RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Address.Minimum;
1675 RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Address.Maximum + addr64_data->Address.AddressLength - 1;
1676 RequirementDescriptor->u.BusNumber.Length = addr64_data->Address.AddressLength;
1677 }
1678 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1679 {
1680 RequirementDescriptor->Type = CmResourceTypePort;
1681 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1682 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1683 if (addr64_data->Decode == ACPI_POS_DECODE)
1684 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1685 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Address.Minimum;
1686 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Address.Maximum + addr64_data->Address.AddressLength - 1;
1687 RequirementDescriptor->u.Port.Length = addr64_data->Address.AddressLength;
1688 }
1689 else
1690 {
1691 RequirementDescriptor->Type = CmResourceTypeMemory;
1692 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1693 RequirementDescriptor->Flags = 0;
1694 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1695 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1696 else
1697 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1698 switch (addr64_data->Info.Mem.Caching)
1699 {
1700 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1701 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1702 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1703 }
1704 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Address.Minimum;
1705 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Address.Maximum + addr64_data->Address.AddressLength - 1;
1706 RequirementDescriptor->u.Memory.Length = addr64_data->Address.AddressLength;
1707 }
1708 RequirementDescriptor++;
1709 break;
1710 }
1711 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1712 {
1713 ACPI_RESOURCE_EXTENDED_ADDRESS64 *addr64_data = &resource->Data.ExtAddress64;
1714 if (addr64_data->ProducerConsumer == ACPI_PRODUCER)
1715 break;
1716 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1717 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1718 {
1719 DPRINT1("64-bit bus address is not supported!\n");
1720 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1721 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1722 RequirementDescriptor->Flags = 0;
1723 RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Address.Minimum;
1724 RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Address.Maximum + addr64_data->Address.AddressLength - 1;
1725 RequirementDescriptor->u.BusNumber.Length = addr64_data->Address.AddressLength;
1726 }
1727 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1728 {
1729 RequirementDescriptor->Type = CmResourceTypePort;
1730 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1731 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1732 if (addr64_data->Decode == ACPI_POS_DECODE)
1733 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1734 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Address.Minimum;
1735 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Address.Maximum + addr64_data->Address.AddressLength - 1;
1736 RequirementDescriptor->u.Port.Length = addr64_data->Address.AddressLength;
1737 }
1738 else
1739 {
1740 RequirementDescriptor->Type = CmResourceTypeMemory;
1741 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1742 RequirementDescriptor->Flags = 0;
1743 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1744 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1745 else
1746 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1747 switch (addr64_data->Info.Mem.Caching)
1748 {
1749 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1750 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1751 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1752 }
1753 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Address.Minimum;
1754 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Address.Maximum + addr64_data->Address.AddressLength - 1;
1755 RequirementDescriptor->u.Memory.Length = addr64_data->Address.AddressLength;
1756 }
1757 RequirementDescriptor++;
1758 break;
1759 }
1760 case ACPI_RESOURCE_TYPE_MEMORY24:
1761 {
1762 ACPI_RESOURCE_MEMORY24 *mem24_data = &resource->Data.Memory24;
1763 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1764 RequirementDescriptor->Type = CmResourceTypeMemory;
1765 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1766 RequirementDescriptor->Flags = CM_RESOURCE_MEMORY_24;
1767 if (mem24_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1768 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1769 else
1770 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1771 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem24_data->Minimum;
1772 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem24_data->Maximum + mem24_data->AddressLength - 1;
1773 RequirementDescriptor->u.Memory.Length = mem24_data->AddressLength;
1774
1775 RequirementDescriptor++;
1776 break;
1777 }
1778 case ACPI_RESOURCE_TYPE_MEMORY32:
1779 {
1780 ACPI_RESOURCE_MEMORY32 *mem32_data = &resource->Data.Memory32;
1781 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1782 RequirementDescriptor->Type = CmResourceTypeMemory;
1783 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1784 RequirementDescriptor->Flags = 0;
1785 if (mem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1786 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1787 else
1788 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1789 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem32_data->Minimum;
1790 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem32_data->Maximum + mem32_data->AddressLength - 1;
1791 RequirementDescriptor->u.Memory.Length = mem32_data->AddressLength;
1792
1793 RequirementDescriptor++;
1794 break;
1795 }
1796 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1797 {
1798 ACPI_RESOURCE_FIXED_MEMORY32 *fixedmem32_data = &resource->Data.FixedMemory32;
1799 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1800 RequirementDescriptor->Type = CmResourceTypeMemory;
1801 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1802 RequirementDescriptor->Flags = 0;
1803 if (fixedmem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1804 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1805 else
1806 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1807 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = fixedmem32_data->Address;
1808 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = fixedmem32_data->Address + fixedmem32_data->AddressLength - 1;
1809 RequirementDescriptor->u.Memory.Length = fixedmem32_data->AddressLength;
1810
1811 RequirementDescriptor++;
1812 break;
1813 }
1814 default:
1815 {
1816 break;
1817 }
1818 }
1819 resource = ACPI_NEXT_RESOURCE(resource);
1820 }
1821 ExFreePoolWithTag(Buffer.Pointer, 'BpcA');
1822
1823 Irp->IoStatus.Information = (ULONG_PTR)RequirementsList;
1824
1825 return STATUS_SUCCESS;
1826 }
1827
1828 #ifndef UNIT_TEST
1829 NTSTATUS
Bus_PDO_QueryDeviceRelations(PPDO_DEVICE_DATA DeviceData,PIRP Irp)1830 Bus_PDO_QueryDeviceRelations(
1831 PPDO_DEVICE_DATA DeviceData,
1832 PIRP Irp )
1833 /*++
1834
1835 Routine Description:
1836
1837 The PnP Manager sends this IRP to gather information about
1838 devices with a relationship to the specified device.
1839 Bus drivers must handle this request for TargetDeviceRelation
1840 for their child devices (child PDOs).
1841
1842 If a driver returns relations in response to this IRP,
1843 it allocates a DEVICE_RELATIONS structure from paged
1844 memory containing a count and the appropriate number of
1845 device object pointers. The PnP Manager frees the structure
1846 when it is no longer needed. If a driver replaces a
1847 DEVICE_RELATIONS structure allocated by another driver,
1848 it must free the previous structure.
1849
1850 A driver must reference the PDO of any device that it
1851 reports in this IRP (ObReferenceObject). The PnP Manager
1852 removes the reference when appropriate.
1853
1854 Arguments:
1855
1856 DeviceData - Pointer to the PDO's device extension.
1857 Irp - Pointer to the irp.
1858
1859 Return Value:
1860
1861 NT STATUS
1862
1863 --*/
1864 {
1865
1866 PIO_STACK_LOCATION stack;
1867 PDEVICE_RELATIONS deviceRelations;
1868 NTSTATUS status;
1869
1870 PAGED_CODE ();
1871
1872 stack = IoGetCurrentIrpStackLocation (Irp);
1873
1874 switch (stack->Parameters.QueryDeviceRelations.Type) {
1875
1876 case TargetDeviceRelation:
1877
1878 deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
1879 if (deviceRelations) {
1880 //
1881 // Only PDO can handle this request. Somebody above
1882 // is not playing by rule.
1883 //
1884 ASSERTMSG("Someone above is handling TargetDeviceRelation\n", !deviceRelations);
1885 }
1886
1887 deviceRelations = ExAllocatePoolWithTag(PagedPool,
1888 sizeof(DEVICE_RELATIONS),
1889 'IpcA');
1890 if (!deviceRelations) {
1891 status = STATUS_INSUFFICIENT_RESOURCES;
1892 break;
1893 }
1894
1895 //
1896 // There is only one PDO pointer in the structure
1897 // for this relation type. The PnP Manager removes
1898 // the reference to the PDO when the driver or application
1899 // un-registers for notification on the device.
1900 //
1901
1902 deviceRelations->Count = 1;
1903 deviceRelations->Objects[0] = DeviceData->Common.Self;
1904 ObReferenceObject(DeviceData->Common.Self);
1905
1906 status = STATUS_SUCCESS;
1907 Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
1908 break;
1909
1910 case BusRelations: // Not handled by PDO
1911 case EjectionRelations: // optional for PDO
1912 case RemovalRelations: // // optional for PDO
1913 default:
1914 status = Irp->IoStatus.Status;
1915 }
1916
1917 return status;
1918 }
1919
1920 NTSTATUS
Bus_PDO_QueryBusInformation(PPDO_DEVICE_DATA DeviceData,PIRP Irp)1921 Bus_PDO_QueryBusInformation(
1922 PPDO_DEVICE_DATA DeviceData,
1923 PIRP Irp )
1924 /*++
1925
1926 Routine Description:
1927
1928 The PnP Manager uses this IRP to request the type and
1929 instance number of a device's parent bus. Bus drivers
1930 should handle this request for their child devices (PDOs).
1931
1932 Arguments:
1933
1934 DeviceData - Pointer to the PDO's device extension.
1935 Irp - Pointer to the irp.
1936
1937 Return Value:
1938
1939 NT STATUS
1940
1941 --*/
1942 {
1943
1944 PPNP_BUS_INFORMATION busInfo;
1945
1946 PAGED_CODE ();
1947
1948 busInfo = ExAllocatePoolWithTag(PagedPool,
1949 sizeof(PNP_BUS_INFORMATION),
1950 'IpcA');
1951
1952 if (busInfo == NULL) {
1953 return STATUS_INSUFFICIENT_RESOURCES;
1954 }
1955
1956 busInfo->BusTypeGuid = GUID_ACPI_INTERFACE_STANDARD;
1957
1958 busInfo->LegacyBusType = InternalPowerBus;
1959
1960 busInfo->BusNumber = 0; //fixme
1961
1962 Irp->IoStatus.Information = (ULONG_PTR)busInfo;
1963
1964 return STATUS_SUCCESS;
1965 }
1966
1967
1968 NTSTATUS
Bus_GetDeviceCapabilities(PDEVICE_OBJECT DeviceObject,PDEVICE_CAPABILITIES DeviceCapabilities)1969 Bus_GetDeviceCapabilities(
1970 PDEVICE_OBJECT DeviceObject,
1971 PDEVICE_CAPABILITIES DeviceCapabilities
1972 )
1973 {
1974 IO_STATUS_BLOCK ioStatus;
1975 KEVENT pnpEvent;
1976 NTSTATUS status;
1977 PDEVICE_OBJECT targetObject;
1978 PIO_STACK_LOCATION irpStack;
1979 PIRP pnpIrp;
1980
1981 PAGED_CODE();
1982
1983 //
1984 // Initialize the capabilities that we will send down
1985 //
1986 RtlZeroMemory( DeviceCapabilities, sizeof(DEVICE_CAPABILITIES) );
1987 DeviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
1988 DeviceCapabilities->Version = 1;
1989 DeviceCapabilities->Address = -1;
1990 DeviceCapabilities->UINumber = -1;
1991
1992 //
1993 // Initialize the event
1994 //
1995 KeInitializeEvent( &pnpEvent, NotificationEvent, FALSE );
1996
1997 targetObject = IoGetAttachedDeviceReference( DeviceObject );
1998
1999 //
2000 // Build an Irp
2001 //
2002 pnpIrp = IoBuildSynchronousFsdRequest(
2003 IRP_MJ_PNP,
2004 targetObject,
2005 NULL,
2006 0,
2007 NULL,
2008 &pnpEvent,
2009 &ioStatus
2010 );
2011 if (pnpIrp == NULL) {
2012
2013 status = STATUS_INSUFFICIENT_RESOURCES;
2014 goto GetDeviceCapabilitiesExit;
2015
2016 }
2017
2018 //
2019 // Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
2020 //
2021 pnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
2022
2023 //
2024 // Get the top of stack
2025 //
2026 irpStack = IoGetNextIrpStackLocation( pnpIrp );
2027
2028 //
2029 // Set the top of stack
2030 //
2031 RtlZeroMemory( irpStack, sizeof(IO_STACK_LOCATION ) );
2032 irpStack->MajorFunction = IRP_MJ_PNP;
2033 irpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
2034 irpStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
2035
2036 //
2037 // Call the driver
2038 //
2039 status = IoCallDriver( targetObject, pnpIrp );
2040 if (status == STATUS_PENDING) {
2041
2042 //
2043 // Block until the irp comes back.
2044 // Important thing to note here is when you allocate
2045 // the memory for an event in the stack you must do a
2046 // KernelMode wait instead of UserMode to prevent
2047 // the stack from getting paged out.
2048 //
2049
2050 KeWaitForSingleObject(
2051 &pnpEvent,
2052 Executive,
2053 KernelMode,
2054 FALSE,
2055 NULL
2056 );
2057 status = ioStatus.Status;
2058
2059 }
2060
2061 GetDeviceCapabilitiesExit:
2062 //
2063 // Done with reference
2064 //
2065 ObDereferenceObject( targetObject );
2066
2067 //
2068 // Done
2069 //
2070 return status;
2071
2072 }
2073 #endif /* UNIT_TEST */
2074