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