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