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