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