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