- Enable debug prints temporarily in an attempt to help diagnose the ACPI issues
[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 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->EjectSupported = device->flags.ejectable;
376 deviceCapabilities->HardwareDisabled = !device->status.enabled;
377 deviceCapabilities->Removable = device->flags.removable;
378 deviceCapabilities->SurpriseRemovalOK = device->flags.suprise_removal_ok;
379 deviceCapabilities->UniqueID = device->flags.unique_id;
380 deviceCapabilities->NoDisplayInUI = !device->status.show_in_ui;
381 deviceCapabilities->Address = device->pnp.bus_address;
382 }
383
384 if (!device ||
385 (device->flags.hardware_id &&
386 (strstr(device->pnp.hardware_id, ACPI_BUTTON_HID_LID) ||
387 strstr(device->pnp.hardware_id, ACPI_THERMAL_HID) ||
388 strstr(device->pnp.hardware_id, ACPI_PROCESSOR_HID))))
389 {
390 /* Allow ACPI to control the device if it is a lid button,
391 * a thermal zone, a processor, or a fixed feature button */
392 deviceCapabilities->RawDeviceOK = TRUE;
393 }
394
395 deviceCapabilities->SilentInstall = FALSE;
396 deviceCapabilities->UINumber = (ULONG)-1;
397
398 return STATUS_SUCCESS;
399
400 }
401
402 NTSTATUS
403 Bus_PDO_QueryDeviceId(
404 PPDO_DEVICE_DATA DeviceData,
405 PIRP Irp )
406 {
407 PIO_STACK_LOCATION stack;
408 PWCHAR buffer;
409 WCHAR temp[256];
410 ULONG length;
411 NTSTATUS status = STATUS_SUCCESS;
412 struct acpi_device *Device;
413
414 PAGED_CODE ();
415
416 stack = IoGetCurrentIrpStackLocation (Irp);
417
418 switch (stack->Parameters.QueryId.IdType) {
419
420 case BusQueryDeviceID:
421 if (DeviceData->AcpiHandle)
422 {
423 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
424
425 length = swprintf(temp,
426 L"ACPI\\%hs",
427 Device->pnp.hardware_id);
428 }
429 else
430 {
431 /* We know it's a fixed feature button because
432 * these are direct children of the ACPI root device
433 * and therefore have no handle
434 */
435 length = swprintf(temp,
436 L"ACPI\\FixedButton");
437 }
438
439 temp[++length] = UNICODE_NULL;
440
441 buffer = ExAllocatePoolWithTag (PagedPool, length * sizeof(WCHAR), 'IPCA');
442
443 if (!buffer) {
444 status = STATUS_INSUFFICIENT_RESOURCES;
445 break;
446 }
447
448 RtlCopyMemory (buffer, temp, length * sizeof(WCHAR));
449 Irp->IoStatus.Information = (ULONG_PTR) buffer;
450 DPRINT("BusQueryDeviceID: %ls\n",buffer);
451 break;
452
453 case BusQueryInstanceID:
454 /* See comment in BusQueryDeviceID case */
455 if(DeviceData->AcpiHandle)
456 {
457 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
458
459 if (Device->flags.unique_id)
460 length = swprintf(temp,
461 L"%hs",
462 Device->pnp.unique_id);
463 else
464 /* FIXME: Generate unique id! */
465 length = swprintf(temp, L"%ls", L"0000");
466 }
467 else
468 /* FIXME: Generate unique id! */
469 length = swprintf(temp, L"%ls", L"0000");
470
471 temp[++length] = UNICODE_NULL;
472
473 buffer = ExAllocatePoolWithTag (PagedPool, length * sizeof (WCHAR), 'IPCA');
474 if (!buffer) {
475 status = STATUS_INSUFFICIENT_RESOURCES;
476 break;
477 }
478
479 RtlCopyMemory (buffer, temp, length * sizeof (WCHAR));
480 DPRINT("BusQueryInstanceID: %ls\n",buffer);
481 Irp->IoStatus.Information = (ULONG_PTR) buffer;
482 break;
483
484 case BusQueryHardwareIDs:
485 length = 0;
486
487 /* See comment in BusQueryDeviceID case */
488 if (DeviceData->AcpiHandle)
489 {
490 acpi_bus_get_device(DeviceData->AcpiHandle, &Device);
491
492 length += swprintf(&temp[length],
493 L"ACPI\\%hs",
494 Device->pnp.hardware_id);
495 length++;
496
497 length += swprintf(&temp[length],
498 L"*%hs",
499 Device->pnp.hardware_id);
500 length++;
501 }
502 else
503 {
504 length += swprintf(&temp[length],
505 L"ACPI\\FixedButton");
506 length++;
507
508 length += swprintf(&temp[length],
509 L"*FixedButton");
510 length++;
511 }
512
513 temp[length] = UNICODE_NULL;
514
515 length++;
516
517 temp[length] = UNICODE_NULL;
518
519 buffer = ExAllocatePoolWithTag (PagedPool, length * sizeof(WCHAR), 'IPCA');
520
521 if (!buffer) {
522 status = STATUS_INSUFFICIENT_RESOURCES;
523 break;
524 }
525
526 RtlCopyMemory (buffer, temp, length * sizeof(WCHAR));
527 Irp->IoStatus.Information = (ULONG_PTR) buffer;
528 DPRINT("BusQueryHardwareIDs: %ls\n",buffer);
529 break;
530
531 default:
532 status = Irp->IoStatus.Status;
533 }
534 return status;
535 }
536
537 NTSTATUS
538 Bus_PDO_QueryDeviceText(
539 PPDO_DEVICE_DATA DeviceData,
540 PIRP Irp )
541 {
542 PWCHAR Buffer;
543 PIO_STACK_LOCATION stack;
544 NTSTATUS status;
545 PAGED_CODE ();
546
547 stack = IoGetCurrentIrpStackLocation (Irp);
548
549 switch (stack->Parameters.QueryDeviceText.DeviceTextType) {
550
551 case DeviceTextDescription:
552
553 if (!Irp->IoStatus.Information) {
554 if (wcsstr (DeviceData->HardwareIDs, L"PNP000") != 0)
555 Buffer = L"Programmable interrupt controller";
556 else if (wcsstr(DeviceData->HardwareIDs, L"PNP010") != 0)
557 Buffer = L"System timer";
558 else if (wcsstr(DeviceData->HardwareIDs, L"PNP020") != 0)
559 Buffer = L"DMA controller";
560 else if (wcsstr(DeviceData->HardwareIDs, L"PNP03") != 0)
561 Buffer = L"Keyboard";
562 else if (wcsstr(DeviceData->HardwareIDs, L"PNP040") != 0)
563 Buffer = L"Parallel port";
564 else if (wcsstr(DeviceData->HardwareIDs, L"PNP05") != 0)
565 Buffer = L"Serial port";
566 else if (wcsstr(DeviceData->HardwareIDs, L"PNP06") != 0)
567 Buffer = L"Disk controller";
568 else if (wcsstr(DeviceData->HardwareIDs, L"PNP07") != 0)
569 Buffer = L"Disk controller";
570 else if (wcsstr(DeviceData->HardwareIDs, L"PNP09") != 0)
571 Buffer = L"Display adapter";
572 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0A0") != 0)
573 Buffer = L"Bus controller";
574 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0E0") != 0)
575 Buffer = L"PCMCIA controller";
576 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0F") != 0)
577 Buffer = L"Mouse device";
578 else if (wcsstr(DeviceData->HardwareIDs, L"PNP8") != 0)
579 Buffer = L"Network adapter";
580 else if (wcsstr(DeviceData->HardwareIDs, L"PNPA0") != 0)
581 Buffer = L"SCSI controller";
582 else if (wcsstr(DeviceData->HardwareIDs, L"PNPB0") != 0)
583 Buffer = L"Multimedia device";
584 else if (wcsstr(DeviceData->HardwareIDs, L"PNPC00") != 0)
585 Buffer = L"Modem";
586 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0C") != 0)
587 Buffer = L"Power Button";
588 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0E") != 0)
589 Buffer = L"Sleep Button";
590 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0D") != 0)
591 Buffer = L"Lid Switch";
592 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C09") != 0)
593 Buffer = L"ACPI Embedded Controller";
594 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0B") != 0)
595 Buffer = L"ACPI Fan";
596 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0A03") != 0)
597 Buffer = L"PCI Root Bridge";
598 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0A") != 0)
599 Buffer = L"ACPI Battery";
600 else if (wcsstr(DeviceData->HardwareIDs, L"PNP0C0F") != 0)
601 Buffer = L"PCI Interrupt Link";
602 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI_PWR") != 0)
603 Buffer = L"ACPI Power Resource";
604 else if (wcsstr(DeviceData->HardwareIDs, L"Processor") != 0)
605 Buffer = L"Processor";
606 else if (wcsstr(DeviceData->HardwareIDs, L"ThermalZone") != 0)
607 Buffer = L"ACPI Thermal Zone";
608 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI0002") != 0)
609 Buffer = L"Smart Battery";
610 else if (wcsstr(DeviceData->HardwareIDs, L"ACPI0003") != 0)
611 Buffer = L"AC Adapter";
612 /* Simply checking if AcpiHandle is NULL eliminates the need to check
613 * for the 4 different names that ACPI knows the fixed feature button as internally
614 */
615 else if (!DeviceData->AcpiHandle)
616 Buffer = L"ACPI Fixed Feature Button";
617 else
618 Buffer = L"Other ACPI device";
619
620 DPRINT("\tDeviceTextDescription :%ws\n", Buffer);
621
622 Irp->IoStatus.Information = (ULONG_PTR) Buffer;
623 }
624 status = STATUS_SUCCESS;
625 break;
626
627 default:
628 status = Irp->IoStatus.Status;
629 break;
630 }
631
632 return status;
633
634 }
635
636 NTSTATUS
637 Bus_PDO_QueryResources(
638 PPDO_DEVICE_DATA DeviceData,
639 PIRP Irp )
640 {
641 ULONG NumberOfResources = 0;
642 PCM_RESOURCE_LIST ResourceList;
643 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
644 ACPI_STATUS AcpiStatus;
645 ACPI_BUFFER Buffer;
646 ACPI_RESOURCE* resource;
647 ULONG ResourceListSize;
648 ULONG i;
649 ULONGLONG BusNumber;
650
651 /* A bus number resource is not included in the list of current resources
652 * for the root PCI bus so we manually query one here and if we find it
653 * we create a resource list and add a bus number descriptor to it */
654 AcpiStatus = acpi_evaluate_integer(DeviceData->AcpiHandle, "_BBN", NULL, &BusNumber);
655 if (AcpiStatus == AE_OK)
656 {
657 DPRINT1("Found PCI root hub: %d\n", BusNumber);
658
659 ResourceListSize = sizeof(CM_RESOURCE_LIST);
660 ResourceList = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool, ResourceListSize);
661 if (!ResourceList)
662 return STATUS_INSUFFICIENT_RESOURCES;
663
664 ResourceList->Count = 1;
665 ResourceList->List[0].InterfaceType = Internal;
666 ResourceList->List[0].BusNumber = 0;
667 ResourceList->List[0].PartialResourceList.Version = 1;
668 ResourceList->List[0].PartialResourceList.Revision = 1;
669 ResourceList->List[0].PartialResourceList.Count = 1;
670 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
671
672 ResourceDescriptor->Type = CmResourceTypeBusNumber;
673 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
674 ResourceDescriptor->u.BusNumber.Start = BusNumber;
675 ResourceDescriptor->u.BusNumber.Length = 1;
676
677 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
678 return STATUS_SUCCESS;
679 }
680
681 /* Get current resources */
682 Buffer.Length = 0;
683 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
684 if ((!ACPI_SUCCESS(AcpiStatus) && AcpiStatus != AE_BUFFER_OVERFLOW) ||
685 Buffer.Length == 0)
686 {
687 return Irp->IoStatus.Status;
688 }
689
690 Buffer.Pointer = ExAllocatePool(PagedPool, Buffer.Length);
691 if (!Buffer.Pointer)
692 return STATUS_INSUFFICIENT_RESOURCES;
693
694 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
695 if (!ACPI_SUCCESS(AcpiStatus))
696 {
697 DPRINT1("AcpiGetCurrentResources #2 failed (0x%x)\n", AcpiStatus);
698 ASSERT(FALSE);
699 return STATUS_UNSUCCESSFUL;
700 }
701
702 resource= Buffer.Pointer;
703 /* Count number of resources */
704 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
705 {
706 switch (resource->Type)
707 {
708 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
709 {
710 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
711 NumberOfResources += irq_data->InterruptCount;
712 break;
713 }
714 case ACPI_RESOURCE_TYPE_IRQ:
715 {
716 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
717 NumberOfResources += irq_data->InterruptCount;
718 break;
719 }
720 case ACPI_RESOURCE_TYPE_DMA:
721 {
722 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
723 NumberOfResources += dma_data->ChannelCount;
724 break;
725 }
726 case ACPI_RESOURCE_TYPE_ADDRESS16:
727 case ACPI_RESOURCE_TYPE_ADDRESS32:
728 case ACPI_RESOURCE_TYPE_ADDRESS64:
729 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
730 case ACPI_RESOURCE_TYPE_MEMORY24:
731 case ACPI_RESOURCE_TYPE_MEMORY32:
732 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
733 case ACPI_RESOURCE_TYPE_IO:
734 {
735 NumberOfResources++;
736 break;
737 }
738 default:
739 {
740 DPRINT1("Unknown resource type: %d\n", resource->Type);
741 break;
742 }
743 }
744 resource = ACPI_NEXT_RESOURCE(resource);
745 }
746
747 /* Allocate memory */
748 ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
749 ResourceList = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool, ResourceListSize);
750
751 if (!ResourceList)
752 {
753 ExFreePool(Buffer.Pointer);
754 return STATUS_INSUFFICIENT_RESOURCES;
755 }
756 ResourceList->Count = 1;
757 ResourceList->List[0].InterfaceType = Internal; /* FIXME */
758 ResourceList->List[0].BusNumber = 0; /* We're the only ACPI bus device in the system */
759 ResourceList->List[0].PartialResourceList.Version = 1;
760 ResourceList->List[0].PartialResourceList.Revision = 1;
761 ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
762 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
763
764 /* Fill resources list structure */
765 resource = Buffer.Pointer;
766 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
767 {
768 switch (resource->Type)
769 {
770 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
771 {
772 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
773 for (i = 0; i < irq_data->InterruptCount; i++)
774 {
775 ResourceDescriptor->Type = CmResourceTypeInterrupt;
776
777 ResourceDescriptor->ShareDisposition =
778 (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
779 ResourceDescriptor->Flags =
780 (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
781 ResourceDescriptor->u.Interrupt.Level =
782 ResourceDescriptor->u.Interrupt.Vector = irq_data->Interrupts[i];
783 ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
784
785 ResourceDescriptor++;
786 }
787 break;
788 }
789 case ACPI_RESOURCE_TYPE_IRQ:
790 {
791 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
792 for (i = 0; i < irq_data->InterruptCount; i++)
793 {
794 ResourceDescriptor->Type = CmResourceTypeInterrupt;
795
796 ResourceDescriptor->ShareDisposition =
797 (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
798 ResourceDescriptor->Flags =
799 (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
800 ResourceDescriptor->u.Interrupt.Level =
801 ResourceDescriptor->u.Interrupt.Vector = irq_data->Interrupts[i];
802 ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
803
804 ResourceDescriptor++;
805 }
806 break;
807 }
808 case ACPI_RESOURCE_TYPE_DMA:
809 {
810 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
811 for (i = 0; i < dma_data->ChannelCount; i++)
812 {
813 ResourceDescriptor->Type = CmResourceTypeDma;
814 ResourceDescriptor->Flags = 0;
815 switch (dma_data->Type)
816 {
817 case ACPI_TYPE_A: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
818 case ACPI_TYPE_B: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
819 case ACPI_TYPE_F: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
820 }
821 if (dma_data->BusMaster == ACPI_BUS_MASTER)
822 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
823 switch (dma_data->Transfer)
824 {
825 case ACPI_TRANSFER_8: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
826 case ACPI_TRANSFER_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
827 case ACPI_TRANSFER_8_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
828 }
829 ResourceDescriptor->u.Dma.Channel = dma_data->Channels[i];
830
831 ResourceDescriptor++;
832 }
833 break;
834 }
835 case ACPI_RESOURCE_TYPE_IO:
836 {
837 ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &resource->Data;
838 ResourceDescriptor->Type = CmResourceTypePort;
839 ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
840 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
841 if (io_data->IoDecode == ACPI_DECODE_16)
842 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
843 else
844 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
845 ResourceDescriptor->u.Port.Start.QuadPart = io_data->Minimum;
846 ResourceDescriptor->u.Port.Length = io_data->AddressLength;
847
848 ResourceDescriptor++;
849 break;
850 }
851 case ACPI_RESOURCE_TYPE_ADDRESS16:
852 {
853 ACPI_RESOURCE_ADDRESS16 *addr16_data = (ACPI_RESOURCE_ADDRESS16*) &resource->Data;
854 if (addr16_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
855 {
856 ResourceDescriptor->Type = CmResourceTypeBusNumber;
857 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
858 ResourceDescriptor->Flags = 0;
859 ResourceDescriptor->u.BusNumber.Start = addr16_data->Minimum;
860 ResourceDescriptor->u.BusNumber.Length = addr16_data->AddressLength;
861 }
862 else if (addr16_data->ResourceType == ACPI_IO_RANGE)
863 {
864 ResourceDescriptor->Type = CmResourceTypePort;
865 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
866 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
867 if (addr16_data->Decode == ACPI_POS_DECODE)
868 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
869 ResourceDescriptor->u.Port.Start.QuadPart = addr16_data->Minimum;
870 ResourceDescriptor->u.Port.Length = addr16_data->AddressLength;
871 }
872 else
873 {
874 ResourceDescriptor->Type = CmResourceTypeMemory;
875 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
876 ResourceDescriptor->Flags = 0;
877 if (addr16_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
878 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
879 else
880 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
881 switch (addr16_data->Info.Mem.Caching)
882 {
883 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
884 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
885 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
886 }
887 ResourceDescriptor->u.Memory.Start.QuadPart = addr16_data->Minimum;
888 ResourceDescriptor->u.Memory.Length = addr16_data->AddressLength;
889 }
890 ResourceDescriptor++;
891 break;
892 }
893 case ACPI_RESOURCE_TYPE_ADDRESS32:
894 {
895 ACPI_RESOURCE_ADDRESS32 *addr32_data = (ACPI_RESOURCE_ADDRESS32*) &resource->Data;
896 if (addr32_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
897 {
898 ResourceDescriptor->Type = CmResourceTypeBusNumber;
899 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
900 ResourceDescriptor->Flags = 0;
901 ResourceDescriptor->u.BusNumber.Start = addr32_data->Minimum;
902 ResourceDescriptor->u.BusNumber.Length = addr32_data->AddressLength;
903 }
904 else if (addr32_data->ResourceType == ACPI_IO_RANGE)
905 {
906 ResourceDescriptor->Type = CmResourceTypePort;
907 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
908 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
909 if (addr32_data->Decode == ACPI_POS_DECODE)
910 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
911 ResourceDescriptor->u.Port.Start.QuadPart = addr32_data->Minimum;
912 ResourceDescriptor->u.Port.Length = addr32_data->AddressLength;
913 }
914 else
915 {
916 ResourceDescriptor->Type = CmResourceTypeMemory;
917 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
918 ResourceDescriptor->Flags = 0;
919 if (addr32_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
920 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
921 else
922 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
923 switch (addr32_data->Info.Mem.Caching)
924 {
925 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
926 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
927 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
928 }
929 ResourceDescriptor->u.Memory.Start.QuadPart = addr32_data->Minimum;
930 ResourceDescriptor->u.Memory.Length = addr32_data->AddressLength;
931 }
932 ResourceDescriptor++;
933 break;
934 }
935 case ACPI_RESOURCE_TYPE_ADDRESS64:
936 {
937 ACPI_RESOURCE_ADDRESS64 *addr64_data = (ACPI_RESOURCE_ADDRESS64*) &resource->Data;
938 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
939 {
940 DPRINT1("64-bit bus address is not supported!\n");
941 ResourceDescriptor->Type = CmResourceTypeBusNumber;
942 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
943 ResourceDescriptor->Flags = 0;
944 ResourceDescriptor->u.BusNumber.Start = (ULONG)addr64_data->Minimum;
945 ResourceDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
946 }
947 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
948 {
949 ResourceDescriptor->Type = CmResourceTypePort;
950 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
951 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
952 if (addr64_data->Decode == ACPI_POS_DECODE)
953 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
954 ResourceDescriptor->u.Port.Start.QuadPart = addr64_data->Minimum;
955 ResourceDescriptor->u.Port.Length = addr64_data->AddressLength;
956 }
957 else
958 {
959 ResourceDescriptor->Type = CmResourceTypeMemory;
960 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
961 ResourceDescriptor->Flags = 0;
962 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
963 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
964 else
965 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
966 switch (addr64_data->Info.Mem.Caching)
967 {
968 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
969 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
970 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
971 }
972 ResourceDescriptor->u.Memory.Start.QuadPart = addr64_data->Minimum;
973 ResourceDescriptor->u.Memory.Length = addr64_data->AddressLength;
974 }
975 ResourceDescriptor++;
976 break;
977 }
978 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
979 {
980 ACPI_RESOURCE_EXTENDED_ADDRESS64 *addr64_data = (ACPI_RESOURCE_EXTENDED_ADDRESS64*) &resource->Data;
981 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
982 {
983 DPRINT1("64-bit bus address is not supported!\n");
984 ResourceDescriptor->Type = CmResourceTypeBusNumber;
985 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
986 ResourceDescriptor->Flags = 0;
987 ResourceDescriptor->u.BusNumber.Start = (ULONG)addr64_data->Minimum;
988 ResourceDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
989 }
990 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
991 {
992 ResourceDescriptor->Type = CmResourceTypePort;
993 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
994 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
995 if (addr64_data->Decode == ACPI_POS_DECODE)
996 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
997 ResourceDescriptor->u.Port.Start.QuadPart = addr64_data->Minimum;
998 ResourceDescriptor->u.Port.Length = addr64_data->AddressLength;
999 }
1000 else
1001 {
1002 ResourceDescriptor->Type = CmResourceTypeMemory;
1003 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1004 ResourceDescriptor->Flags = 0;
1005 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1006 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1007 else
1008 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1009 switch (addr64_data->Info.Mem.Caching)
1010 {
1011 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1012 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1013 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1014 }
1015 ResourceDescriptor->u.Memory.Start.QuadPart = addr64_data->Minimum;
1016 ResourceDescriptor->u.Memory.Length = addr64_data->AddressLength;
1017 }
1018 ResourceDescriptor++;
1019 break;
1020 }
1021 case ACPI_RESOURCE_TYPE_MEMORY24:
1022 {
1023 ACPI_RESOURCE_MEMORY24 *mem24_data = (ACPI_RESOURCE_MEMORY24*) &resource->Data;
1024 ResourceDescriptor->Type = CmResourceTypeMemory;
1025 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1026 ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_24;
1027 if (mem24_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1028 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1029 else
1030 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1031 ResourceDescriptor->u.Memory.Start.QuadPart = mem24_data->Minimum;
1032 ResourceDescriptor->u.Memory.Length = mem24_data->AddressLength;
1033
1034 ResourceDescriptor++;
1035 break;
1036 }
1037 case ACPI_RESOURCE_TYPE_MEMORY32:
1038 {
1039 ACPI_RESOURCE_MEMORY32 *mem32_data = (ACPI_RESOURCE_MEMORY32*) &resource->Data;
1040 ResourceDescriptor->Type = CmResourceTypeMemory;
1041 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1042 ResourceDescriptor->Flags = 0;
1043 if (mem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1044 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1045 else
1046 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1047 ResourceDescriptor->u.Memory.Start.QuadPart = mem32_data->Minimum;
1048 ResourceDescriptor->u.Memory.Length = mem32_data->AddressLength;
1049
1050 ResourceDescriptor++;
1051 break;
1052 }
1053 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1054 {
1055 ACPI_RESOURCE_FIXED_MEMORY32 *memfixed32_data = (ACPI_RESOURCE_FIXED_MEMORY32*) &resource->Data;
1056 ResourceDescriptor->Type = CmResourceTypeMemory;
1057 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1058 ResourceDescriptor->Flags = 0;
1059 if (memfixed32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1060 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1061 else
1062 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1063 ResourceDescriptor->u.Memory.Start.QuadPart = memfixed32_data->Address;
1064 ResourceDescriptor->u.Memory.Length = memfixed32_data->AddressLength;
1065
1066 ResourceDescriptor++;
1067 break;
1068 }
1069 default:
1070 {
1071 break;
1072 }
1073 }
1074 resource = ACPI_NEXT_RESOURCE(resource);
1075 }
1076
1077 ExFreePool(Buffer.Pointer);
1078 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
1079 return STATUS_SUCCESS;
1080 }
1081
1082 NTSTATUS
1083 Bus_PDO_QueryResourceRequirements(
1084 PPDO_DEVICE_DATA DeviceData,
1085 PIRP Irp )
1086 {
1087 ULONG NumberOfResources = 0;
1088 ACPI_STATUS AcpiStatus;
1089 ACPI_BUFFER Buffer;
1090 ACPI_RESOURCE* resource;
1091 ULONG i, RequirementsListSize;
1092 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
1093 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor;
1094 BOOLEAN CurrentRes = FALSE;
1095
1096 PAGED_CODE ();
1097
1098
1099 /* Get current resources */
1100 while (TRUE)
1101 {
1102 Buffer.Length = 0;
1103 if (CurrentRes)
1104 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
1105 else
1106 AcpiStatus = AcpiGetPossibleResources(DeviceData->AcpiHandle, &Buffer);
1107 if ((!ACPI_SUCCESS(AcpiStatus) && AcpiStatus != AE_BUFFER_OVERFLOW) ||
1108 Buffer.Length == 0)
1109 {
1110 if (!CurrentRes)
1111 CurrentRes = TRUE;
1112 else
1113 return Irp->IoStatus.Status;
1114 }
1115 else
1116 break;
1117 }
1118
1119 Buffer.Pointer = ExAllocatePool(PagedPool, Buffer.Length);
1120 if (!Buffer.Pointer)
1121 return STATUS_INSUFFICIENT_RESOURCES;
1122
1123 if (CurrentRes)
1124 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
1125 else
1126 AcpiStatus = AcpiGetPossibleResources(DeviceData->AcpiHandle, &Buffer);
1127 if (!ACPI_SUCCESS(AcpiStatus))
1128 {
1129 DPRINT1("AcpiGetCurrentResources #2 failed (0x%x)\n", AcpiStatus);
1130 ASSERT(FALSE);
1131 return STATUS_UNSUCCESSFUL;
1132 }
1133
1134 resource= Buffer.Pointer;
1135 /* Count number of resources */
1136 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
1137 {
1138 switch (resource->Type)
1139 {
1140 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1141 {
1142 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
1143 NumberOfResources += irq_data->InterruptCount;
1144 break;
1145 }
1146 case ACPI_RESOURCE_TYPE_IRQ:
1147 {
1148 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
1149 NumberOfResources += irq_data->InterruptCount;
1150 break;
1151 }
1152 case ACPI_RESOURCE_TYPE_DMA:
1153 {
1154 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
1155 NumberOfResources += dma_data->ChannelCount;
1156 break;
1157 }
1158 case ACPI_RESOURCE_TYPE_ADDRESS16:
1159 case ACPI_RESOURCE_TYPE_ADDRESS32:
1160 case ACPI_RESOURCE_TYPE_ADDRESS64:
1161 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1162 case ACPI_RESOURCE_TYPE_MEMORY24:
1163 case ACPI_RESOURCE_TYPE_MEMORY32:
1164 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1165 case ACPI_RESOURCE_TYPE_IO:
1166 {
1167 NumberOfResources++;
1168 break;
1169 }
1170 default:
1171 {
1172 break;
1173 }
1174 }
1175 resource = ACPI_NEXT_RESOURCE(resource);
1176 }
1177
1178 RequirementsListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
1179 RequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool(PagedPool, RequirementsListSize);
1180
1181 if (!RequirementsList)
1182 {
1183 ExFreePool(Buffer.Pointer);
1184 return STATUS_INSUFFICIENT_RESOURCES;
1185 }
1186 RequirementsList->ListSize = RequirementsListSize;
1187 RequirementsList->InterfaceType = Internal;
1188 RequirementsList->BusNumber = 0;
1189 RequirementsList->SlotNumber = 0; /* Not used by WDM drivers */
1190 RequirementsList->AlternativeLists = 1;
1191 RequirementsList->List[0].Version = 1;
1192 RequirementsList->List[0].Revision = 1;
1193 RequirementsList->List[0].Count = NumberOfResources;
1194 RequirementDescriptor = RequirementsList->List[0].Descriptors;
1195
1196 /* Fill resources list structure */
1197 resource = Buffer.Pointer;
1198 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
1199 {
1200 switch (resource->Type)
1201 {
1202 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1203 {
1204 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
1205 for (i = 0; i < irq_data->InterruptCount; i++)
1206 {
1207 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1208 RequirementDescriptor->Type = CmResourceTypeInterrupt;
1209 RequirementDescriptor->ShareDisposition = (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
1210 RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
1211 RequirementDescriptor->u.Interrupt.MinimumVector =
1212 RequirementDescriptor->u.Interrupt.MaximumVector = irq_data->Interrupts[i];
1213
1214 RequirementDescriptor++;
1215 }
1216 break;
1217 }
1218 case ACPI_RESOURCE_TYPE_IRQ:
1219 {
1220 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
1221 for (i = 0; i < irq_data->InterruptCount; i++)
1222 {
1223 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1224 RequirementDescriptor->Type = CmResourceTypeInterrupt;
1225 RequirementDescriptor->ShareDisposition = (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
1226 RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
1227 RequirementDescriptor->u.Interrupt.MinimumVector =
1228 RequirementDescriptor->u.Interrupt.MaximumVector = irq_data->Interrupts[i];
1229
1230 RequirementDescriptor++;
1231 }
1232 break;
1233 }
1234 case ACPI_RESOURCE_TYPE_DMA:
1235 {
1236 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
1237 for (i = 0; i < dma_data->ChannelCount; i++)
1238 {
1239 RequirementDescriptor->Type = CmResourceTypeDma;
1240 RequirementDescriptor->Flags = 0;
1241 switch (dma_data->Type)
1242 {
1243 case ACPI_TYPE_A: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
1244 case ACPI_TYPE_B: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
1245 case ACPI_TYPE_F: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
1246 }
1247 if (dma_data->BusMaster == ACPI_BUS_MASTER)
1248 RequirementDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
1249 switch (dma_data->Transfer)
1250 {
1251 case ACPI_TRANSFER_8: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
1252 case ACPI_TRANSFER_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
1253 case ACPI_TRANSFER_8_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
1254 }
1255
1256 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1257 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1258 RequirementDescriptor->u.Dma.MinimumChannel =
1259 RequirementDescriptor->u.Dma.MaximumChannel = dma_data->Channels[i];
1260 RequirementDescriptor++;
1261 }
1262 break;
1263 }
1264 case ACPI_RESOURCE_TYPE_IO:
1265 {
1266 ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &resource->Data;
1267 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1268 if (io_data->IoDecode == ACPI_DECODE_16)
1269 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
1270 else
1271 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
1272 RequirementDescriptor->u.Port.Length = io_data->AddressLength;
1273 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1274 RequirementDescriptor->Type = CmResourceTypePort;
1275 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1276 RequirementDescriptor->u.Port.Alignment = io_data->Alignment;
1277 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = io_data->Minimum;
1278 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = io_data->Maximum;
1279
1280 RequirementDescriptor++;
1281 break;
1282 }
1283 case ACPI_RESOURCE_TYPE_ADDRESS16:
1284 {
1285 ACPI_RESOURCE_ADDRESS16 *addr16_data = (ACPI_RESOURCE_ADDRESS16*) &resource->Data;
1286 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1287 if (addr16_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1288 {
1289 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1290 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1291 RequirementDescriptor->Flags = 0;
1292 RequirementDescriptor->u.BusNumber.MinBusNumber = addr16_data->Minimum;
1293 RequirementDescriptor->u.BusNumber.MaxBusNumber = addr16_data->Maximum;
1294 RequirementDescriptor->u.BusNumber.Length = addr16_data->AddressLength;
1295 }
1296 else if (addr16_data->ResourceType == ACPI_IO_RANGE)
1297 {
1298 RequirementDescriptor->Type = CmResourceTypePort;
1299 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1300 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1301 if (addr16_data->Decode == ACPI_POS_DECODE)
1302 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1303 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr16_data->Minimum;
1304 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr16_data->Maximum;
1305 RequirementDescriptor->u.Port.Length = addr16_data->AddressLength;
1306 }
1307 else
1308 {
1309 RequirementDescriptor->Type = CmResourceTypeMemory;
1310 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1311 RequirementDescriptor->Flags = 0;
1312 if (addr16_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1313 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1314 else
1315 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1316 switch (addr16_data->Info.Mem.Caching)
1317 {
1318 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1319 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1320 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1321 }
1322 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr16_data->Minimum;
1323 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr16_data->Maximum;
1324 RequirementDescriptor->u.Memory.Length = addr16_data->AddressLength;
1325 }
1326 RequirementDescriptor++;
1327 break;
1328 }
1329 case ACPI_RESOURCE_TYPE_ADDRESS32:
1330 {
1331 ACPI_RESOURCE_ADDRESS32 *addr32_data = (ACPI_RESOURCE_ADDRESS32*) &resource->Data;
1332 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1333 if (addr32_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1334 {
1335 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1336 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1337 RequirementDescriptor->Flags = 0;
1338 RequirementDescriptor->u.BusNumber.MinBusNumber = addr32_data->Minimum;
1339 RequirementDescriptor->u.BusNumber.MaxBusNumber = addr32_data->Maximum;
1340 RequirementDescriptor->u.BusNumber.Length = addr32_data->AddressLength;
1341 }
1342 else if (addr32_data->ResourceType == ACPI_IO_RANGE)
1343 {
1344 RequirementDescriptor->Type = CmResourceTypePort;
1345 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1346 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1347 if (addr32_data->Decode == ACPI_POS_DECODE)
1348 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1349 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr32_data->Minimum;
1350 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr32_data->Maximum;
1351 RequirementDescriptor->u.Port.Length = addr32_data->AddressLength;
1352 }
1353 else
1354 {
1355 RequirementDescriptor->Type = CmResourceTypeMemory;
1356 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1357 RequirementDescriptor->Flags = 0;
1358 if (addr32_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1359 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1360 else
1361 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1362 switch (addr32_data->Info.Mem.Caching)
1363 {
1364 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1365 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1366 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1367 }
1368 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr32_data->Minimum;
1369 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr32_data->Maximum;
1370 RequirementDescriptor->u.Memory.Length = addr32_data->AddressLength;
1371 }
1372 RequirementDescriptor++;
1373 break;
1374 }
1375 case ACPI_RESOURCE_TYPE_ADDRESS64:
1376 {
1377 ACPI_RESOURCE_ADDRESS64 *addr64_data = (ACPI_RESOURCE_ADDRESS64*) &resource->Data;
1378 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1379 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1380 {
1381 DPRINT1("64-bit bus address is not supported!\n");
1382 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1383 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1384 RequirementDescriptor->Flags = 0;
1385 RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Minimum;
1386 RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Maximum;
1387 RequirementDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
1388 }
1389 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1390 {
1391 RequirementDescriptor->Type = CmResourceTypePort;
1392 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1393 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1394 if (addr64_data->Decode == ACPI_POS_DECODE)
1395 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1396 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Minimum;
1397 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Maximum;
1398 RequirementDescriptor->u.Port.Length = addr64_data->AddressLength;
1399 }
1400 else
1401 {
1402 RequirementDescriptor->Type = CmResourceTypeMemory;
1403 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1404 RequirementDescriptor->Flags = 0;
1405 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1406 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1407 else
1408 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1409 switch (addr64_data->Info.Mem.Caching)
1410 {
1411 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1412 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1413 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1414 }
1415 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Minimum;
1416 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Maximum;
1417 RequirementDescriptor->u.Memory.Length = addr64_data->AddressLength;
1418 }
1419 RequirementDescriptor++;
1420 break;
1421 }
1422 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1423 {
1424 ACPI_RESOURCE_EXTENDED_ADDRESS64 *addr64_data = (ACPI_RESOURCE_EXTENDED_ADDRESS64*) &resource->Data;
1425 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1426 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1427 {
1428 DPRINT1("64-bit bus address is not supported!\n");
1429 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1430 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1431 RequirementDescriptor->Flags = 0;
1432 RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Minimum;
1433 RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Maximum;
1434 RequirementDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
1435 }
1436 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1437 {
1438 RequirementDescriptor->Type = CmResourceTypePort;
1439 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1440 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1441 if (addr64_data->Decode == ACPI_POS_DECODE)
1442 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1443 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Minimum;
1444 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Maximum;
1445 RequirementDescriptor->u.Port.Length = addr64_data->AddressLength;
1446 }
1447 else
1448 {
1449 RequirementDescriptor->Type = CmResourceTypeMemory;
1450 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1451 RequirementDescriptor->Flags = 0;
1452 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1453 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1454 else
1455 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1456 switch (addr64_data->Info.Mem.Caching)
1457 {
1458 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1459 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1460 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1461 }
1462 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Minimum;
1463 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Maximum;
1464 RequirementDescriptor->u.Memory.Length = addr64_data->AddressLength;
1465 }
1466 RequirementDescriptor++;
1467 break;
1468 }
1469 case ACPI_RESOURCE_TYPE_MEMORY24:
1470 {
1471 ACPI_RESOURCE_MEMORY24 *mem24_data = (ACPI_RESOURCE_MEMORY24*) &resource->Data;
1472 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1473 RequirementDescriptor->Type = CmResourceTypeMemory;
1474 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1475 RequirementDescriptor->Flags = CM_RESOURCE_MEMORY_24;
1476 if (mem24_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1477 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1478 else
1479 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1480 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem24_data->Minimum;
1481 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem24_data->Maximum;
1482 RequirementDescriptor->u.Memory.Length = mem24_data->AddressLength;
1483
1484 RequirementDescriptor++;
1485 break;
1486 }
1487 case ACPI_RESOURCE_TYPE_MEMORY32:
1488 {
1489 ACPI_RESOURCE_MEMORY32 *mem32_data = (ACPI_RESOURCE_MEMORY32*) &resource->Data;
1490 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1491 RequirementDescriptor->Type = CmResourceTypeMemory;
1492 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1493 RequirementDescriptor->Flags = 0;
1494 if (mem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1495 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1496 else
1497 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1498 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem32_data->Minimum;
1499 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem32_data->Maximum;
1500 RequirementDescriptor->u.Memory.Length = mem32_data->AddressLength;
1501
1502 RequirementDescriptor++;
1503 break;
1504 }
1505 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1506 {
1507 ACPI_RESOURCE_FIXED_MEMORY32 *fixedmem32_data = (ACPI_RESOURCE_FIXED_MEMORY32*) &resource->Data;
1508 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1509 RequirementDescriptor->Type = CmResourceTypeMemory;
1510 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1511 RequirementDescriptor->Flags = 0;
1512 if (fixedmem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1513 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1514 else
1515 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1516 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = fixedmem32_data->Address;
1517 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = fixedmem32_data->Address;
1518 RequirementDescriptor->u.Memory.Length = fixedmem32_data->AddressLength;
1519
1520 RequirementDescriptor++;
1521 break;
1522 }
1523 default:
1524 {
1525 break;
1526 }
1527 }
1528 resource = ACPI_NEXT_RESOURCE(resource);
1529 }
1530 ExFreePool(Buffer.Pointer);
1531
1532 Irp->IoStatus.Information = (ULONG_PTR)RequirementsList;
1533
1534 return STATUS_SUCCESS;
1535 }
1536
1537 NTSTATUS
1538 Bus_PDO_QueryDeviceRelations(
1539 PPDO_DEVICE_DATA DeviceData,
1540 PIRP Irp )
1541 /*++
1542
1543 Routine Description:
1544
1545 The PnP Manager sends this IRP to gather information about
1546 devices with a relationship to the specified device.
1547 Bus drivers must handle this request for TargetDeviceRelation
1548 for their child devices (child PDOs).
1549
1550 If a driver returns relations in response to this IRP,
1551 it allocates a DEVICE_RELATIONS structure from paged
1552 memory containing a count and the appropriate number of
1553 device object pointers. The PnP Manager frees the structure
1554 when it is no longer needed. If a driver replaces a
1555 DEVICE_RELATIONS structure allocated by another driver,
1556 it must free the previous structure.
1557
1558 A driver must reference the PDO of any device that it
1559 reports in this IRP (ObReferenceObject). The PnP Manager
1560 removes the reference when appropriate.
1561
1562 Arguments:
1563
1564 DeviceData - Pointer to the PDO's device extension.
1565 Irp - Pointer to the irp.
1566
1567 Return Value:
1568
1569 NT STATUS
1570
1571 --*/
1572 {
1573
1574 PIO_STACK_LOCATION stack;
1575 PDEVICE_RELATIONS deviceRelations;
1576 NTSTATUS status;
1577
1578 PAGED_CODE ();
1579
1580 stack = IoGetCurrentIrpStackLocation (Irp);
1581
1582 switch (stack->Parameters.QueryDeviceRelations.Type) {
1583
1584 case TargetDeviceRelation:
1585
1586 deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
1587 if (deviceRelations) {
1588 //
1589 // Only PDO can handle this request. Somebody above
1590 // is not playing by rule.
1591 //
1592 ASSERTMSG("Someone above is handling TargetDeviceRelation", !deviceRelations);
1593 }
1594
1595 deviceRelations = (PDEVICE_RELATIONS)
1596 ExAllocatePoolWithTag (PagedPool,
1597 sizeof(DEVICE_RELATIONS),
1598 'IPCA');
1599 if (!deviceRelations) {
1600 status = STATUS_INSUFFICIENT_RESOURCES;
1601 break;
1602 }
1603
1604 //
1605 // There is only one PDO pointer in the structure
1606 // for this relation type. The PnP Manager removes
1607 // the reference to the PDO when the driver or application
1608 // un-registers for notification on the device.
1609 //
1610
1611 deviceRelations->Count = 1;
1612 deviceRelations->Objects[0] = DeviceData->Common.Self;
1613 ObReferenceObject(DeviceData->Common.Self);
1614
1615 status = STATUS_SUCCESS;
1616 Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
1617 break;
1618
1619 case BusRelations: // Not handled by PDO
1620 case EjectionRelations: // optional for PDO
1621 case RemovalRelations: // // optional for PDO
1622 default:
1623 status = Irp->IoStatus.Status;
1624 }
1625
1626 return status;
1627 }
1628
1629 NTSTATUS
1630 Bus_PDO_QueryBusInformation(
1631 PPDO_DEVICE_DATA DeviceData,
1632 PIRP Irp )
1633 /*++
1634
1635 Routine Description:
1636
1637 The PnP Manager uses this IRP to request the type and
1638 instance number of a device's parent bus. Bus drivers
1639 should handle this request for their child devices (PDOs).
1640
1641 Arguments:
1642
1643 DeviceData - Pointer to the PDO's device extension.
1644 Irp - Pointer to the irp.
1645
1646 Return Value:
1647
1648 NT STATUS
1649
1650 --*/
1651 {
1652
1653 PPNP_BUS_INFORMATION busInfo;
1654
1655 PAGED_CODE ();
1656
1657 busInfo = ExAllocatePoolWithTag (PagedPool, sizeof(PNP_BUS_INFORMATION),
1658 'IPCA');
1659
1660 if (busInfo == NULL) {
1661 return STATUS_INSUFFICIENT_RESOURCES;
1662 }
1663
1664 busInfo->BusTypeGuid = GUID_ACPI_INTERFACE_STANDARD;
1665
1666 busInfo->LegacyBusType = InternalPowerBus;
1667
1668 busInfo->BusNumber = 0; //fixme
1669
1670 Irp->IoStatus.Information = (ULONG_PTR)busInfo;
1671
1672 return STATUS_SUCCESS;
1673 }
1674
1675
1676 NTSTATUS
1677 Bus_GetDeviceCapabilities(
1678 PDEVICE_OBJECT DeviceObject,
1679 PDEVICE_CAPABILITIES DeviceCapabilities
1680 )
1681 {
1682 IO_STATUS_BLOCK ioStatus;
1683 KEVENT pnpEvent;
1684 NTSTATUS status;
1685 PDEVICE_OBJECT targetObject;
1686 PIO_STACK_LOCATION irpStack;
1687 PIRP pnpIrp;
1688
1689 PAGED_CODE();
1690
1691 //
1692 // Initialize the capabilities that we will send down
1693 //
1694 RtlZeroMemory( DeviceCapabilities, sizeof(DEVICE_CAPABILITIES) );
1695 DeviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
1696 DeviceCapabilities->Version = 1;
1697 DeviceCapabilities->Address = -1;
1698 DeviceCapabilities->UINumber = -1;
1699
1700 //
1701 // Initialize the event
1702 //
1703 KeInitializeEvent( &pnpEvent, NotificationEvent, FALSE );
1704
1705 targetObject = IoGetAttachedDeviceReference( DeviceObject );
1706
1707 //
1708 // Build an Irp
1709 //
1710 pnpIrp = IoBuildSynchronousFsdRequest(
1711 IRP_MJ_PNP,
1712 targetObject,
1713 NULL,
1714 0,
1715 NULL,
1716 &pnpEvent,
1717 &ioStatus
1718 );
1719 if (pnpIrp == NULL) {
1720
1721 status = STATUS_INSUFFICIENT_RESOURCES;
1722 goto GetDeviceCapabilitiesExit;
1723
1724 }
1725
1726 //
1727 // Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
1728 //
1729 pnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1730
1731 //
1732 // Get the top of stack
1733 //
1734 irpStack = IoGetNextIrpStackLocation( pnpIrp );
1735
1736 //
1737 // Set the top of stack
1738 //
1739 RtlZeroMemory( irpStack, sizeof(IO_STACK_LOCATION ) );
1740 irpStack->MajorFunction = IRP_MJ_PNP;
1741 irpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
1742 irpStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
1743
1744 //
1745 // Call the driver
1746 //
1747 status = IoCallDriver( targetObject, pnpIrp );
1748 if (status == STATUS_PENDING) {
1749
1750 //
1751 // Block until the irp comes back.
1752 // Important thing to note here is when you allocate
1753 // the memory for an event in the stack you must do a
1754 // KernelMode wait instead of UserMode to prevent
1755 // the stack from getting paged out.
1756 //
1757
1758 KeWaitForSingleObject(
1759 &pnpEvent,
1760 Executive,
1761 KernelMode,
1762 FALSE,
1763 NULL
1764 );
1765 status = ioStatus.Status;
1766
1767 }
1768
1769 GetDeviceCapabilitiesExit:
1770 //
1771 // Done with reference
1772 //
1773 ObDereferenceObject( targetObject );
1774
1775 //
1776 // Done
1777 //
1778 return status;
1779
1780 }
1781
1782