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