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