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