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