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