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