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