[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
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
648 /* Get current resources */
649 Buffer.Length = 0;
650 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
651 if ((!ACPI_SUCCESS(AcpiStatus) && AcpiStatus != AE_BUFFER_OVERFLOW) ||
652 Buffer.Length == 0)
653 {
654 return Irp->IoStatus.Status;
655 }
656
657 Buffer.Pointer = ExAllocatePool(PagedPool, Buffer.Length);
658 if (!Buffer.Pointer)
659 return STATUS_INSUFFICIENT_RESOURCES;
660
661 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
662 if (!ACPI_SUCCESS(AcpiStatus))
663 {
664 DPRINT1("AcpiGetCurrentResources #2 failed (0x%x)\n", AcpiStatus);
665 ASSERT(FALSE);
666 return STATUS_UNSUCCESSFUL;
667 }
668
669 resource= Buffer.Pointer;
670 /* Count number of resources */
671 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
672 {
673 switch (resource->Type)
674 {
675 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
676 {
677 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
678 NumberOfResources += irq_data->InterruptCount;
679 break;
680 }
681 case ACPI_RESOURCE_TYPE_IRQ:
682 {
683 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
684 NumberOfResources += irq_data->InterruptCount;
685 break;
686 }
687 case ACPI_RESOURCE_TYPE_DMA:
688 {
689 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
690 NumberOfResources += dma_data->ChannelCount;
691 break;
692 }
693 case ACPI_RESOURCE_TYPE_ADDRESS16:
694 case ACPI_RESOURCE_TYPE_ADDRESS32:
695 case ACPI_RESOURCE_TYPE_ADDRESS64:
696 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
697 case ACPI_RESOURCE_TYPE_MEMORY24:
698 case ACPI_RESOURCE_TYPE_MEMORY32:
699 case ACPI_RESOURCE_TYPE_IO:
700 {
701 NumberOfResources++;
702 break;
703 }
704 default:
705 {
706 DPRINT1("Unknown resource type: %d\n", resource->Type);
707 break;
708 }
709 }
710 resource = ACPI_NEXT_RESOURCE(resource);
711 }
712
713 /* Allocate memory */
714 ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
715 ResourceList = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool, ResourceListSize);
716
717 if (!ResourceList)
718 {
719 ExFreePool(Buffer.Pointer);
720 return STATUS_INSUFFICIENT_RESOURCES;
721 }
722 ResourceList->Count = 1;
723 ResourceList->List[0].InterfaceType = Internal; /* FIXME */
724 ResourceList->List[0].BusNumber = 0; /* We're the only ACPI bus device in the system */
725 ResourceList->List[0].PartialResourceList.Version = 1;
726 ResourceList->List[0].PartialResourceList.Revision = 1;
727 ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
728 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
729
730 /* Fill resources list structure */
731 resource = Buffer.Pointer;
732 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
733 {
734 switch (resource->Type)
735 {
736 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
737 {
738 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
739 for (i = 0; i < irq_data->InterruptCount; i++)
740 {
741 ResourceDescriptor->Type = CmResourceTypeInterrupt;
742
743 ResourceDescriptor->ShareDisposition =
744 (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
745 ResourceDescriptor->Flags =
746 (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
747 ResourceDescriptor->u.Interrupt.Level = irq_data->Interrupts[i];
748 ResourceDescriptor->u.Interrupt.Vector = 0;
749 ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
750
751 ResourceDescriptor++;
752 }
753 break;
754 }
755 case ACPI_RESOURCE_TYPE_IRQ:
756 {
757 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
758 for (i = 0; i < irq_data->InterruptCount; i++)
759 {
760 ResourceDescriptor->Type = CmResourceTypeInterrupt;
761
762 ResourceDescriptor->ShareDisposition =
763 (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
764 ResourceDescriptor->Flags =
765 (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
766 ResourceDescriptor->u.Interrupt.Level = irq_data->Interrupts[i];
767 ResourceDescriptor->u.Interrupt.Vector = 0;
768 ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
769
770 ResourceDescriptor++;
771 }
772 break;
773 }
774 case ACPI_RESOURCE_TYPE_DMA:
775 {
776 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
777 for (i = 0; i < dma_data->ChannelCount; i++)
778 {
779 ResourceDescriptor->Type = CmResourceTypeDma;
780 ResourceDescriptor->Flags = 0;
781 switch (dma_data->Type)
782 {
783 case ACPI_TYPE_A: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
784 case ACPI_TYPE_B: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
785 case ACPI_TYPE_F: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
786 }
787 if (dma_data->BusMaster == ACPI_BUS_MASTER)
788 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
789 switch (dma_data->Transfer)
790 {
791 case ACPI_TRANSFER_8: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
792 case ACPI_TRANSFER_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
793 case ACPI_TRANSFER_8_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
794 }
795 ResourceDescriptor->u.Dma.Channel = dma_data->Channels[i];
796
797 ResourceDescriptor++;
798 }
799 break;
800 }
801 case ACPI_RESOURCE_TYPE_IO:
802 {
803 ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &resource->Data;
804 ResourceDescriptor->Type = CmResourceTypePort;
805 ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
806 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
807 if (io_data->IoDecode == ACPI_DECODE_16)
808 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
809 else
810 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
811 ResourceDescriptor->u.Port.Start.QuadPart = io_data->Minimum;
812 ResourceDescriptor->u.Port.Length = io_data->AddressLength;
813
814 ResourceDescriptor++;
815 break;
816 }
817 case ACPI_RESOURCE_TYPE_ADDRESS16:
818 {
819 ACPI_RESOURCE_ADDRESS16 *addr16_data = (ACPI_RESOURCE_ADDRESS16*) &resource->Data;
820 if (addr16_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
821 {
822 ResourceDescriptor->Type = CmResourceTypeBusNumber;
823 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
824 ResourceDescriptor->Flags = 0;
825 ResourceDescriptor->u.BusNumber.Start = addr16_data->Minimum;
826 ResourceDescriptor->u.BusNumber.Length = addr16_data->AddressLength;
827 }
828 else if (addr16_data->ResourceType == ACPI_IO_RANGE)
829 {
830 ResourceDescriptor->Type = CmResourceTypePort;
831 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
832 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
833 if (addr16_data->Decode == ACPI_POS_DECODE)
834 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
835 ResourceDescriptor->u.Port.Start.QuadPart = addr16_data->Minimum;
836 ResourceDescriptor->u.Port.Length = addr16_data->AddressLength;
837 }
838 else
839 {
840 ResourceDescriptor->Type = CmResourceTypeMemory;
841 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
842 ResourceDescriptor->Flags = 0;
843 if (addr16_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
844 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
845 else
846 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
847 switch (addr16_data->Info.Mem.Caching)
848 {
849 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
850 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
851 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
852 }
853 ResourceDescriptor->u.Memory.Start.QuadPart = addr16_data->Minimum;
854 ResourceDescriptor->u.Memory.Length = addr16_data->AddressLength;
855 }
856 ResourceDescriptor++;
857 break;
858 }
859 case ACPI_RESOURCE_TYPE_ADDRESS32:
860 {
861 ACPI_RESOURCE_ADDRESS32 *addr32_data = (ACPI_RESOURCE_ADDRESS32*) &resource->Data;
862 if (addr32_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
863 {
864 ResourceDescriptor->Type = CmResourceTypeBusNumber;
865 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
866 ResourceDescriptor->Flags = 0;
867 ResourceDescriptor->u.BusNumber.Start = addr32_data->Minimum;
868 ResourceDescriptor->u.BusNumber.Length = addr32_data->AddressLength;
869 }
870 else if (addr32_data->ResourceType == ACPI_IO_RANGE)
871 {
872 ResourceDescriptor->Type = CmResourceTypePort;
873 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
874 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
875 if (addr32_data->Decode == ACPI_POS_DECODE)
876 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
877 ResourceDescriptor->u.Port.Start.QuadPart = addr32_data->Minimum;
878 ResourceDescriptor->u.Port.Length = addr32_data->AddressLength;
879 }
880 else
881 {
882 ResourceDescriptor->Type = CmResourceTypeMemory;
883 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
884 ResourceDescriptor->Flags = 0;
885 if (addr32_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
886 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
887 else
888 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
889 switch (addr32_data->Info.Mem.Caching)
890 {
891 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
892 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
893 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
894 }
895 ResourceDescriptor->u.Memory.Start.QuadPart = addr32_data->Minimum;
896 ResourceDescriptor->u.Memory.Length = addr32_data->AddressLength;
897 }
898 ResourceDescriptor++;
899 break;
900 }
901 case ACPI_RESOURCE_TYPE_ADDRESS64:
902 {
903 ACPI_RESOURCE_ADDRESS64 *addr64_data = (ACPI_RESOURCE_ADDRESS64*) &resource->Data;
904 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
905 {
906 DPRINT1("64-bit bus address is not supported!\n");
907 ResourceDescriptor->Type = CmResourceTypeBusNumber;
908 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
909 ResourceDescriptor->Flags = 0;
910 ResourceDescriptor->u.BusNumber.Start = (ULONG)addr64_data->Minimum;
911 ResourceDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
912 }
913 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
914 {
915 ResourceDescriptor->Type = CmResourceTypePort;
916 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
917 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
918 if (addr64_data->Decode == ACPI_POS_DECODE)
919 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
920 ResourceDescriptor->u.Port.Start.QuadPart = addr64_data->Minimum;
921 ResourceDescriptor->u.Port.Length = addr64_data->AddressLength;
922 }
923 else
924 {
925 ResourceDescriptor->Type = CmResourceTypeMemory;
926 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
927 ResourceDescriptor->Flags = 0;
928 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
929 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
930 else
931 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
932 switch (addr64_data->Info.Mem.Caching)
933 {
934 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
935 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
936 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
937 }
938 ResourceDescriptor->u.Memory.Start.QuadPart = addr64_data->Minimum;
939 ResourceDescriptor->u.Memory.Length = addr64_data->AddressLength;
940 }
941 ResourceDescriptor++;
942 break;
943 }
944 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
945 {
946 ACPI_RESOURCE_EXTENDED_ADDRESS64 *addr64_data = (ACPI_RESOURCE_EXTENDED_ADDRESS64*) &resource->Data;
947 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
948 {
949 DPRINT1("64-bit bus address is not supported!\n");
950 ResourceDescriptor->Type = CmResourceTypeBusNumber;
951 ResourceDescriptor->ShareDisposition = CmResourceShareShared;
952 ResourceDescriptor->Flags = 0;
953 ResourceDescriptor->u.BusNumber.Start = (ULONG)addr64_data->Minimum;
954 ResourceDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
955 }
956 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
957 {
958 ResourceDescriptor->Type = CmResourceTypePort;
959 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
960 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
961 if (addr64_data->Decode == ACPI_POS_DECODE)
962 ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
963 ResourceDescriptor->u.Port.Start.QuadPart = addr64_data->Minimum;
964 ResourceDescriptor->u.Port.Length = addr64_data->AddressLength;
965 }
966 else
967 {
968 ResourceDescriptor->Type = CmResourceTypeMemory;
969 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
970 ResourceDescriptor->Flags = 0;
971 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
972 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
973 else
974 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
975 switch (addr64_data->Info.Mem.Caching)
976 {
977 case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
978 case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
979 case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
980 }
981 ResourceDescriptor->u.Memory.Start.QuadPart = addr64_data->Minimum;
982 ResourceDescriptor->u.Memory.Length = addr64_data->AddressLength;
983 }
984 ResourceDescriptor++;
985 break;
986 }
987 case ACPI_RESOURCE_TYPE_MEMORY24:
988 {
989 ACPI_RESOURCE_MEMORY24 *mem24_data = (ACPI_RESOURCE_MEMORY24*) &resource->Data;
990 ResourceDescriptor->Type = CmResourceTypeMemory;
991 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
992 ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_24;
993 if (mem24_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
994 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
995 else
996 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
997 ResourceDescriptor->u.Memory.Start.QuadPart = mem24_data->Minimum;
998 ResourceDescriptor->u.Memory.Length = mem24_data->AddressLength;
999
1000 ResourceDescriptor++;
1001 break;
1002 }
1003 case ACPI_RESOURCE_TYPE_MEMORY32:
1004 {
1005 ACPI_RESOURCE_MEMORY32 *mem32_data = (ACPI_RESOURCE_MEMORY32*) &resource->Data;
1006 ResourceDescriptor->Type = CmResourceTypeMemory;
1007 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1008 ResourceDescriptor->Flags = 0;
1009 if (mem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1010 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1011 else
1012 ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1013 ResourceDescriptor->u.Memory.Start.QuadPart = mem32_data->Minimum;
1014 ResourceDescriptor->u.Memory.Length = mem32_data->AddressLength;
1015
1016 ResourceDescriptor++;
1017 break;
1018 }
1019 default:
1020 {
1021 break;
1022 }
1023 }
1024 resource = ACPI_NEXT_RESOURCE(resource);
1025 }
1026
1027 ExFreePool(Buffer.Pointer);
1028 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
1029 return STATUS_SUCCESS;
1030 }
1031
1032 NTSTATUS
1033 Bus_PDO_QueryResourceRequirements(
1034 PPDO_DEVICE_DATA DeviceData,
1035 PIRP Irp )
1036 {
1037 ULONG NumberOfResources = 0;
1038 ACPI_STATUS AcpiStatus;
1039 ACPI_BUFFER Buffer;
1040 ACPI_RESOURCE* resource;
1041 ULONG i, RequirementsListSize;
1042 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
1043 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor;
1044 BOOLEAN CurrentRes = FALSE;
1045
1046 PAGED_CODE ();
1047
1048
1049 /* Get current resources */
1050 while (TRUE)
1051 {
1052 Buffer.Length = 0;
1053 if (CurrentRes)
1054 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
1055 else
1056 AcpiStatus = AcpiGetPossibleResources(DeviceData->AcpiHandle, &Buffer);
1057 if ((!ACPI_SUCCESS(AcpiStatus) && AcpiStatus != AE_BUFFER_OVERFLOW) ||
1058 Buffer.Length == 0)
1059 {
1060 if (!CurrentRes)
1061 CurrentRes = TRUE;
1062 else
1063 return Irp->IoStatus.Status;
1064 }
1065 else
1066 break;
1067 }
1068
1069 Buffer.Pointer = ExAllocatePool(PagedPool, Buffer.Length);
1070 if (!Buffer.Pointer)
1071 return STATUS_INSUFFICIENT_RESOURCES;
1072
1073 if (CurrentRes)
1074 AcpiStatus = AcpiGetCurrentResources(DeviceData->AcpiHandle, &Buffer);
1075 else
1076 AcpiStatus = AcpiGetPossibleResources(DeviceData->AcpiHandle, &Buffer);
1077 if (!ACPI_SUCCESS(AcpiStatus))
1078 {
1079 DPRINT1("AcpiGetCurrentResources #2 failed (0x%x)\n", AcpiStatus);
1080 ASSERT(FALSE);
1081 return STATUS_UNSUCCESSFUL;
1082 }
1083
1084 resource= Buffer.Pointer;
1085 /* Count number of resources */
1086 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
1087 {
1088 switch (resource->Type)
1089 {
1090 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1091 {
1092 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
1093 NumberOfResources += irq_data->InterruptCount;
1094 break;
1095 }
1096 case ACPI_RESOURCE_TYPE_IRQ:
1097 {
1098 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
1099 NumberOfResources += irq_data->InterruptCount;
1100 break;
1101 }
1102 case ACPI_RESOURCE_TYPE_DMA:
1103 {
1104 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
1105 NumberOfResources += dma_data->ChannelCount;
1106 break;
1107 }
1108 case ACPI_RESOURCE_TYPE_ADDRESS16:
1109 case ACPI_RESOURCE_TYPE_ADDRESS32:
1110 case ACPI_RESOURCE_TYPE_ADDRESS64:
1111 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1112 case ACPI_RESOURCE_TYPE_MEMORY24:
1113 case ACPI_RESOURCE_TYPE_MEMORY32:
1114 case ACPI_RESOURCE_TYPE_IO:
1115 {
1116 NumberOfResources++;
1117 break;
1118 }
1119 default:
1120 {
1121 break;
1122 }
1123 }
1124 resource = ACPI_NEXT_RESOURCE(resource);
1125 }
1126
1127 RequirementsListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
1128 RequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool(PagedPool, RequirementsListSize);
1129
1130 if (!RequirementsList)
1131 {
1132 ExFreePool(Buffer.Pointer);
1133 return STATUS_INSUFFICIENT_RESOURCES;
1134 }
1135 RequirementsList->ListSize = RequirementsListSize;
1136 RequirementsList->InterfaceType = Internal;
1137 RequirementsList->BusNumber = 0;
1138 RequirementsList->SlotNumber = 0; /* Not used by WDM drivers */
1139 RequirementsList->AlternativeLists = 1;
1140 RequirementsList->List[0].Version = 1;
1141 RequirementsList->List[0].Revision = 1;
1142 RequirementsList->List[0].Count = NumberOfResources;
1143 RequirementDescriptor = RequirementsList->List[0].Descriptors;
1144
1145 /* Fill resources list structure */
1146 resource = Buffer.Pointer;
1147 while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
1148 {
1149 switch (resource->Type)
1150 {
1151 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1152 {
1153 ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
1154 for (i = 0; i < irq_data->InterruptCount; i++)
1155 {
1156 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1157 RequirementDescriptor->Type = CmResourceTypeInterrupt;
1158 RequirementDescriptor->ShareDisposition = (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
1159 RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
1160 RequirementDescriptor->u.Interrupt.MinimumVector =
1161 RequirementDescriptor->u.Interrupt.MaximumVector = irq_data->Interrupts[i];
1162
1163 RequirementDescriptor++;
1164 }
1165 break;
1166 }
1167 case ACPI_RESOURCE_TYPE_IRQ:
1168 {
1169 ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
1170 for (i = 0; i < irq_data->InterruptCount; i++)
1171 {
1172 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1173 RequirementDescriptor->Type = CmResourceTypeInterrupt;
1174 RequirementDescriptor->ShareDisposition = (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
1175 RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
1176 RequirementDescriptor->u.Interrupt.MinimumVector =
1177 RequirementDescriptor->u.Interrupt.MaximumVector = irq_data->Interrupts[i];
1178
1179 RequirementDescriptor++;
1180 }
1181 break;
1182 }
1183 case ACPI_RESOURCE_TYPE_DMA:
1184 {
1185 ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &resource->Data;
1186 for (i = 0; i < dma_data->ChannelCount; i++)
1187 {
1188 RequirementDescriptor->Type = CmResourceTypeDma;
1189 RequirementDescriptor->Flags = 0;
1190 switch (dma_data->Type)
1191 {
1192 case ACPI_TYPE_A: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
1193 case ACPI_TYPE_B: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
1194 case ACPI_TYPE_F: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
1195 }
1196 if (dma_data->BusMaster == ACPI_BUS_MASTER)
1197 RequirementDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
1198 switch (dma_data->Transfer)
1199 {
1200 case ACPI_TRANSFER_8: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
1201 case ACPI_TRANSFER_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
1202 case ACPI_TRANSFER_8_16: RequirementDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
1203 }
1204
1205 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1206 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1207 RequirementDescriptor->u.Dma.MinimumChannel =
1208 RequirementDescriptor->u.Dma.MaximumChannel = dma_data->Channels[i];
1209 RequirementDescriptor++;
1210 }
1211 break;
1212 }
1213 case ACPI_RESOURCE_TYPE_IO:
1214 {
1215 ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &resource->Data;
1216 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1217 if (io_data->IoDecode == ACPI_DECODE_16)
1218 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
1219 else
1220 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
1221 RequirementDescriptor->u.Port.Length = io_data->AddressLength;
1222 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1223 RequirementDescriptor->Type = CmResourceTypePort;
1224 RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
1225 RequirementDescriptor->u.Port.Alignment = io_data->Alignment;
1226 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = io_data->Minimum;
1227 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = io_data->Maximum;
1228
1229 RequirementDescriptor++;
1230 break;
1231 }
1232 case ACPI_RESOURCE_TYPE_ADDRESS16:
1233 {
1234 ACPI_RESOURCE_ADDRESS16 *addr16_data = (ACPI_RESOURCE_ADDRESS16*) &resource->Data;
1235 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1236 if (addr16_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1237 {
1238 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1239 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1240 RequirementDescriptor->Flags = 0;
1241 RequirementDescriptor->u.BusNumber.MinBusNumber = addr16_data->Minimum;
1242 RequirementDescriptor->u.BusNumber.MaxBusNumber = addr16_data->Maximum;
1243 RequirementDescriptor->u.BusNumber.Length = addr16_data->AddressLength;
1244 }
1245 else if (addr16_data->ResourceType == ACPI_IO_RANGE)
1246 {
1247 RequirementDescriptor->Type = CmResourceTypePort;
1248 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1249 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1250 if (addr16_data->Decode == ACPI_POS_DECODE)
1251 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1252 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr16_data->Minimum;
1253 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr16_data->Maximum;
1254 RequirementDescriptor->u.Port.Length = addr16_data->AddressLength;
1255 }
1256 else
1257 {
1258 RequirementDescriptor->Type = CmResourceTypeMemory;
1259 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1260 RequirementDescriptor->Flags = 0;
1261 if (addr16_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1262 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1263 else
1264 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1265 switch (addr16_data->Info.Mem.Caching)
1266 {
1267 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1268 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1269 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1270 }
1271 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr16_data->Minimum;
1272 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr16_data->Maximum;
1273 RequirementDescriptor->u.Memory.Length = addr16_data->AddressLength;
1274 }
1275 RequirementDescriptor++;
1276 break;
1277 }
1278 case ACPI_RESOURCE_TYPE_ADDRESS32:
1279 {
1280 ACPI_RESOURCE_ADDRESS32 *addr32_data = (ACPI_RESOURCE_ADDRESS32*) &resource->Data;
1281 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1282 if (addr32_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1283 {
1284 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1285 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1286 RequirementDescriptor->Flags = 0;
1287 RequirementDescriptor->u.BusNumber.MinBusNumber = addr32_data->Minimum;
1288 RequirementDescriptor->u.BusNumber.MaxBusNumber = addr32_data->Maximum;
1289 RequirementDescriptor->u.BusNumber.Length = addr32_data->AddressLength;
1290 }
1291 else if (addr32_data->ResourceType == ACPI_IO_RANGE)
1292 {
1293 RequirementDescriptor->Type = CmResourceTypePort;
1294 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1295 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1296 if (addr32_data->Decode == ACPI_POS_DECODE)
1297 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1298 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr32_data->Minimum;
1299 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr32_data->Maximum;
1300 RequirementDescriptor->u.Port.Length = addr32_data->AddressLength;
1301 }
1302 else
1303 {
1304 RequirementDescriptor->Type = CmResourceTypeMemory;
1305 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1306 RequirementDescriptor->Flags = 0;
1307 if (addr32_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1308 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1309 else
1310 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1311 switch (addr32_data->Info.Mem.Caching)
1312 {
1313 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1314 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1315 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1316 }
1317 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr32_data->Minimum;
1318 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr32_data->Maximum;
1319 RequirementDescriptor->u.Memory.Length = addr32_data->AddressLength;
1320 }
1321 RequirementDescriptor++;
1322 break;
1323 }
1324 case ACPI_RESOURCE_TYPE_ADDRESS64:
1325 {
1326 ACPI_RESOURCE_ADDRESS64 *addr64_data = (ACPI_RESOURCE_ADDRESS64*) &resource->Data;
1327 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1328 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1329 {
1330 DPRINT1("64-bit bus address is not supported!\n");
1331 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1332 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1333 RequirementDescriptor->Flags = 0;
1334 RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Minimum;
1335 RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Maximum;
1336 RequirementDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
1337 }
1338 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1339 {
1340 RequirementDescriptor->Type = CmResourceTypePort;
1341 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1342 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1343 if (addr64_data->Decode == ACPI_POS_DECODE)
1344 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1345 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Minimum;
1346 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Maximum;
1347 RequirementDescriptor->u.Port.Length = addr64_data->AddressLength;
1348 }
1349 else
1350 {
1351 RequirementDescriptor->Type = CmResourceTypeMemory;
1352 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1353 RequirementDescriptor->Flags = 0;
1354 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1355 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1356 else
1357 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1358 switch (addr64_data->Info.Mem.Caching)
1359 {
1360 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1361 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1362 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1363 }
1364 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Minimum;
1365 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Maximum;
1366 RequirementDescriptor->u.Memory.Length = addr64_data->AddressLength;
1367 }
1368 RequirementDescriptor++;
1369 break;
1370 }
1371 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
1372 {
1373 ACPI_RESOURCE_EXTENDED_ADDRESS64 *addr64_data = (ACPI_RESOURCE_EXTENDED_ADDRESS64*) &resource->Data;
1374 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1375 if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
1376 {
1377 DPRINT1("64-bit bus address is not supported!\n");
1378 RequirementDescriptor->Type = CmResourceTypeBusNumber;
1379 RequirementDescriptor->ShareDisposition = CmResourceShareShared;
1380 RequirementDescriptor->Flags = 0;
1381 RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Minimum;
1382 RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Maximum;
1383 RequirementDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
1384 }
1385 else if (addr64_data->ResourceType == ACPI_IO_RANGE)
1386 {
1387 RequirementDescriptor->Type = CmResourceTypePort;
1388 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1389 RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
1390 if (addr64_data->Decode == ACPI_POS_DECODE)
1391 RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
1392 RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Minimum;
1393 RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Maximum;
1394 RequirementDescriptor->u.Port.Length = addr64_data->AddressLength;
1395 }
1396 else
1397 {
1398 RequirementDescriptor->Type = CmResourceTypeMemory;
1399 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1400 RequirementDescriptor->Flags = 0;
1401 if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
1402 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1403 else
1404 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1405 switch (addr64_data->Info.Mem.Caching)
1406 {
1407 case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
1408 case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
1409 case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
1410 }
1411 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Minimum;
1412 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Maximum;
1413 RequirementDescriptor->u.Memory.Length = addr64_data->AddressLength;
1414 }
1415 RequirementDescriptor++;
1416 break;
1417 }
1418 case ACPI_RESOURCE_TYPE_MEMORY24:
1419 {
1420 ACPI_RESOURCE_MEMORY24 *mem24_data = (ACPI_RESOURCE_MEMORY24*) &resource->Data;
1421 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1422 RequirementDescriptor->Type = CmResourceTypeMemory;
1423 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1424 RequirementDescriptor->Flags = CM_RESOURCE_MEMORY_24;
1425 if (mem24_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1426 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1427 else
1428 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1429 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem24_data->Minimum;
1430 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem24_data->Maximum;
1431 RequirementDescriptor->u.Memory.Length = mem24_data->AddressLength;
1432
1433 RequirementDescriptor++;
1434 break;
1435 }
1436 case ACPI_RESOURCE_TYPE_MEMORY32:
1437 {
1438 ACPI_RESOURCE_MEMORY32 *mem32_data = (ACPI_RESOURCE_MEMORY32*) &resource->Data;
1439 RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
1440 RequirementDescriptor->Type = CmResourceTypeMemory;
1441 RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1442 RequirementDescriptor->Flags = 0;
1443 if (mem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
1444 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1445 else
1446 RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1447 RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem32_data->Minimum;
1448 RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem32_data->Maximum;
1449 RequirementDescriptor->u.Memory.Length = mem32_data->AddressLength;
1450
1451 RequirementDescriptor++;
1452 break;
1453 }
1454 default:
1455 {
1456 break;
1457 }
1458 }
1459 resource = ACPI_NEXT_RESOURCE(resource);
1460 }
1461 ExFreePool(Buffer.Pointer);
1462
1463 Irp->IoStatus.Information = (ULONG_PTR)RequirementsList;
1464
1465 return STATUS_SUCCESS;
1466 }
1467
1468 NTSTATUS
1469 Bus_PDO_QueryDeviceRelations(
1470 PPDO_DEVICE_DATA DeviceData,
1471 PIRP Irp )
1472 /*++
1473
1474 Routine Description:
1475
1476 The PnP Manager sends this IRP to gather information about
1477 devices with a relationship to the specified device.
1478 Bus drivers must handle this request for TargetDeviceRelation
1479 for their child devices (child PDOs).
1480
1481 If a driver returns relations in response to this IRP,
1482 it allocates a DEVICE_RELATIONS structure from paged
1483 memory containing a count and the appropriate number of
1484 device object pointers. The PnP Manager frees the structure
1485 when it is no longer needed. If a driver replaces a
1486 DEVICE_RELATIONS structure allocated by another driver,
1487 it must free the previous structure.
1488
1489 A driver must reference the PDO of any device that it
1490 reports in this IRP (ObReferenceObject). The PnP Manager
1491 removes the reference when appropriate.
1492
1493 Arguments:
1494
1495 DeviceData - Pointer to the PDO's device extension.
1496 Irp - Pointer to the irp.
1497
1498 Return Value:
1499
1500 NT STATUS
1501
1502 --*/
1503 {
1504
1505 PIO_STACK_LOCATION stack;
1506 PDEVICE_RELATIONS deviceRelations;
1507 NTSTATUS status;
1508
1509 PAGED_CODE ();
1510
1511 stack = IoGetCurrentIrpStackLocation (Irp);
1512
1513 switch (stack->Parameters.QueryDeviceRelations.Type) {
1514
1515 case TargetDeviceRelation:
1516
1517 deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
1518 if (deviceRelations) {
1519 //
1520 // Only PDO can handle this request. Somebody above
1521 // is not playing by rule.
1522 //
1523 ASSERTMSG("Someone above is handling TargetDeviceRelation", !deviceRelations);
1524 }
1525
1526 deviceRelations = (PDEVICE_RELATIONS)
1527 ExAllocatePoolWithTag (PagedPool,
1528 sizeof(DEVICE_RELATIONS),
1529 'IPCA');
1530 if (!deviceRelations) {
1531 status = STATUS_INSUFFICIENT_RESOURCES;
1532 break;
1533 }
1534
1535 //
1536 // There is only one PDO pointer in the structure
1537 // for this relation type. The PnP Manager removes
1538 // the reference to the PDO when the driver or application
1539 // un-registers for notification on the device.
1540 //
1541
1542 deviceRelations->Count = 1;
1543 deviceRelations->Objects[0] = DeviceData->Common.Self;
1544 ObReferenceObject(DeviceData->Common.Self);
1545
1546 status = STATUS_SUCCESS;
1547 Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
1548 break;
1549
1550 case BusRelations: // Not handled by PDO
1551 case EjectionRelations: // optional for PDO
1552 case RemovalRelations: // // optional for PDO
1553 default:
1554 status = Irp->IoStatus.Status;
1555 }
1556
1557 return status;
1558 }
1559
1560 NTSTATUS
1561 Bus_PDO_QueryBusInformation(
1562 PPDO_DEVICE_DATA DeviceData,
1563 PIRP Irp )
1564 /*++
1565
1566 Routine Description:
1567
1568 The PnP Manager uses this IRP to request the type and
1569 instance number of a device's parent bus. Bus drivers
1570 should handle this request for their child devices (PDOs).
1571
1572 Arguments:
1573
1574 DeviceData - Pointer to the PDO's device extension.
1575 Irp - Pointer to the irp.
1576
1577 Return Value:
1578
1579 NT STATUS
1580
1581 --*/
1582 {
1583
1584 PPNP_BUS_INFORMATION busInfo;
1585
1586 PAGED_CODE ();
1587
1588 busInfo = ExAllocatePoolWithTag (PagedPool, sizeof(PNP_BUS_INFORMATION),
1589 'IPCA');
1590
1591 if (busInfo == NULL) {
1592 return STATUS_INSUFFICIENT_RESOURCES;
1593 }
1594
1595 busInfo->BusTypeGuid = GUID_ACPI_INTERFACE_STANDARD;
1596
1597 busInfo->LegacyBusType = InternalPowerBus;
1598
1599 busInfo->BusNumber = 0; //fixme
1600
1601 Irp->IoStatus.Information = (ULONG_PTR)busInfo;
1602
1603 return STATUS_SUCCESS;
1604 }
1605
1606
1607 NTSTATUS
1608 Bus_GetDeviceCapabilities(
1609 PDEVICE_OBJECT DeviceObject,
1610 PDEVICE_CAPABILITIES DeviceCapabilities
1611 )
1612 {
1613 IO_STATUS_BLOCK ioStatus;
1614 KEVENT pnpEvent;
1615 NTSTATUS status;
1616 PDEVICE_OBJECT targetObject;
1617 PIO_STACK_LOCATION irpStack;
1618 PIRP pnpIrp;
1619
1620 PAGED_CODE();
1621
1622 //
1623 // Initialize the capabilities that we will send down
1624 //
1625 RtlZeroMemory( DeviceCapabilities, sizeof(DEVICE_CAPABILITIES) );
1626 DeviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
1627 DeviceCapabilities->Version = 1;
1628 DeviceCapabilities->Address = -1;
1629 DeviceCapabilities->UINumber = -1;
1630
1631 //
1632 // Initialize the event
1633 //
1634 KeInitializeEvent( &pnpEvent, NotificationEvent, FALSE );
1635
1636 targetObject = IoGetAttachedDeviceReference( DeviceObject );
1637
1638 //
1639 // Build an Irp
1640 //
1641 pnpIrp = IoBuildSynchronousFsdRequest(
1642 IRP_MJ_PNP,
1643 targetObject,
1644 NULL,
1645 0,
1646 NULL,
1647 &pnpEvent,
1648 &ioStatus
1649 );
1650 if (pnpIrp == NULL) {
1651
1652 status = STATUS_INSUFFICIENT_RESOURCES;
1653 goto GetDeviceCapabilitiesExit;
1654
1655 }
1656
1657 //
1658 // Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
1659 //
1660 pnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1661
1662 //
1663 // Get the top of stack
1664 //
1665 irpStack = IoGetNextIrpStackLocation( pnpIrp );
1666
1667 //
1668 // Set the top of stack
1669 //
1670 RtlZeroMemory( irpStack, sizeof(IO_STACK_LOCATION ) );
1671 irpStack->MajorFunction = IRP_MJ_PNP;
1672 irpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
1673 irpStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
1674
1675 //
1676 // Call the driver
1677 //
1678 status = IoCallDriver( targetObject, pnpIrp );
1679 if (status == STATUS_PENDING) {
1680
1681 //
1682 // Block until the irp comes back.
1683 // Important thing to note here is when you allocate
1684 // the memory for an event in the stack you must do a
1685 // KernelMode wait instead of UserMode to prevent
1686 // the stack from getting paged out.
1687 //
1688
1689 KeWaitForSingleObject(
1690 &pnpEvent,
1691 Executive,
1692 KernelMode,
1693 FALSE,
1694 NULL
1695 );
1696 status = ioStatus.Status;
1697
1698 }
1699
1700 GetDeviceCapabilitiesExit:
1701 //
1702 // Done with reference
1703 //
1704 ObDereferenceObject( targetObject );
1705
1706 //
1707 // Done
1708 //
1709 return status;
1710
1711 }
1712
1713