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