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