9 #include <acpi_drivers.h>
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)
28 PDEVICE_OBJECT DeviceObject
,
30 PIO_STACK_LOCATION IrpStack
,
31 PPDO_DEVICE_DATA DeviceData
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
45 switch (IrpStack
->MinorFunction
) {
47 case IRP_MN_START_DEVICE
:
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.
54 if (DeviceData
->AcpiHandle
&& acpi_bus_power_manageable(DeviceData
->AcpiHandle
) &&
55 !ACPI_SUCCESS(acpi_bus_set_power(DeviceData
->AcpiHandle
, ACPI_STATE_D0
)))
57 DPRINT1("Device %x failed to start!\n", DeviceData
->AcpiHandle
);
58 status
= STATUS_UNSUCCESSFUL
;
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
;
69 case IRP_MN_STOP_DEVICE
:
72 // Here we shut down the device and give up and unmap any resources
73 // we acquired for the device.
75 if (DeviceData
->AcpiHandle
&& acpi_bus_power_manageable(DeviceData
->AcpiHandle
) &&
76 !ACPI_SUCCESS(acpi_bus_set_power(DeviceData
->AcpiHandle
, ACPI_STATE_D3
)))
78 DPRINT1("Device %x failed to stop!\n", DeviceData
->AcpiHandle
);
79 status
= STATUS_UNSUCCESSFUL
;
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
;
91 case IRP_MN_QUERY_STOP_DEVICE
:
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.
99 SET_NEW_PNP_STATE(DeviceData
->Common
, StopPending
);
100 status
= STATUS_SUCCESS
;
103 case IRP_MN_CANCEL_STOP_DEVICE
:
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.
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
119 if (StopPending
== DeviceData
->Common
.DevicePnPState
)
122 // We did receive a query-stop, so restore.
124 RESTORE_PREVIOUS_PNP_STATE(DeviceData
->Common
);
126 status
= STATUS_SUCCESS
;// We must not fail this IRP.
128 case IRP_MN_QUERY_CAPABILITIES
:
131 // Return the capabilities of a device, such as whether the device
132 // can be locked or ejected..etc
135 status
= Bus_PDO_QueryDeviceCaps(DeviceData
, Irp
);
139 case IRP_MN_QUERY_ID
:
141 // Query the IDs of the device
142 status
= Bus_PDO_QueryDeviceId(DeviceData
, Irp
);
146 case IRP_MN_QUERY_DEVICE_RELATIONS
:
148 DPRINT("\tQueryDeviceRelation Type: %s\n",DbgDeviceRelationString(\
149 IrpStack
->Parameters
.QueryDeviceRelations
.Type
));
151 status
= Bus_PDO_QueryDeviceRelations(DeviceData
, Irp
);
155 case IRP_MN_QUERY_DEVICE_TEXT
:
157 status
= Bus_PDO_QueryDeviceText(DeviceData
, Irp
);
161 case IRP_MN_QUERY_RESOURCES
:
163 status
= Bus_PDO_QueryResources(DeviceData
, Irp
);
167 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
169 status
= Bus_PDO_QueryResourceRequirements(DeviceData
, Irp
);
173 case IRP_MN_QUERY_BUS_INFORMATION
:
175 status
= Bus_PDO_QueryBusInformation(DeviceData
, Irp
);
180 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
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.
191 //case IRP_MN_QUERY_PNP_DEVICE_STATE:
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.
203 //case IRP_MN_READ_CONFIG:
204 //case IRP_MN_WRITE_CONFIG:
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.
214 //case IRP_MN_SET_LOCK:
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
;
229 Irp
->IoStatus
.Status
= status
;
230 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
236 Bus_PDO_QueryDeviceCaps(
237 PPDO_DEVICE_DATA DeviceData
,
241 PIO_STACK_LOCATION stack
;
242 PDEVICE_CAPABILITIES deviceCapabilities
;
243 struct acpi_device
*device
= NULL
;
248 if (DeviceData
->AcpiHandle
)
249 acpi_bus_get_device(DeviceData
->AcpiHandle
, &device
);
251 stack
= IoGetCurrentIrpStackLocation (Irp
);
256 deviceCapabilities
=stack
->Parameters
.DeviceCapabilities
.Capabilities
;
259 // Set the capabilities.
262 if (deviceCapabilities
->Version
!= 1 ||
263 deviceCapabilities
->Size
< sizeof(DEVICE_CAPABILITIES
))
265 return STATUS_UNSUCCESSFUL
;
268 deviceCapabilities
->D1Latency
= 0;
269 deviceCapabilities
->D2Latency
= 0;
270 deviceCapabilities
->D3Latency
= 0;
272 deviceCapabilities
->DeviceState
[PowerSystemWorking
] = PowerDeviceD0
;
273 deviceCapabilities
->DeviceState
[PowerSystemSleeping1
] = PowerDeviceD3
;
274 deviceCapabilities
->DeviceState
[PowerSystemSleeping2
] = PowerDeviceD3
;
275 deviceCapabilities
->DeviceState
[PowerSystemSleeping3
] = PowerDeviceD3
;
277 for (i
= 0; i
< ACPI_D_STATE_COUNT
&& device
; i
++)
279 if (!device
->power
.states
[i
].flags
.valid
)
285 deviceCapabilities
->DeviceState
[PowerSystemWorking
] = PowerDeviceD0
;
289 deviceCapabilities
->DeviceState
[PowerSystemSleeping1
] = PowerDeviceD1
;
290 deviceCapabilities
->D1Latency
= device
->power
.states
[i
].latency
;
294 deviceCapabilities
->DeviceState
[PowerSystemSleeping2
] = PowerDeviceD2
;
295 deviceCapabilities
->D2Latency
= device
->power
.states
[i
].latency
;
299 deviceCapabilities
->DeviceState
[PowerSystemSleeping3
] = PowerDeviceD3
;
300 deviceCapabilities
->D3Latency
= device
->power
.states
[i
].latency
;
305 // We can wake the system from D1
306 deviceCapabilities
->DeviceWake
= PowerDeviceD1
;
309 deviceCapabilities
->DeviceD1
=
310 (deviceCapabilities
->DeviceState
[PowerSystemSleeping1
] == PowerDeviceD1
) ? TRUE
: FALSE
;
311 deviceCapabilities
->DeviceD2
=
312 (deviceCapabilities
->DeviceState
[PowerSystemSleeping2
] == PowerDeviceD2
) ? TRUE
: FALSE
;
314 deviceCapabilities
->WakeFromD0
= FALSE
;
315 deviceCapabilities
->WakeFromD1
= TRUE
; //Yes we can
316 deviceCapabilities
->WakeFromD2
= FALSE
;
317 deviceCapabilities
->WakeFromD3
= FALSE
;
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
;
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;
340 /* The ACPI driver will run fixed buttons */
341 deviceCapabilities
->RawDeviceOK
= TRUE
;
344 deviceCapabilities
->SilentInstall
= FALSE
;
345 deviceCapabilities
->UINumber
= (ULONG
)-1;
347 return STATUS_SUCCESS
;
352 Bus_PDO_QueryDeviceId(
353 PPDO_DEVICE_DATA DeviceData
,
356 PIO_STACK_LOCATION stack
;
360 NTSTATUS status
= STATUS_SUCCESS
;
361 struct acpi_device
*Device
;
365 stack
= IoGetCurrentIrpStackLocation (Irp
);
367 switch (stack
->Parameters
.QueryId
.IdType
) {
369 case BusQueryDeviceID
:
370 if (DeviceData
->AcpiHandle
)
372 acpi_bus_get_device(DeviceData
->AcpiHandle
, &Device
);
374 length
= swprintf(temp
,
376 Device
->pnp
.hardware_id
);
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
384 length
= swprintf(temp
,
385 L
"ACPI\\FixedButton");
388 temp
[++length
] = UNICODE_NULL
;
390 buffer
= ExAllocatePoolWithTag (PagedPool
, length
* sizeof(WCHAR
), 'IPCA');
393 status
= STATUS_INSUFFICIENT_RESOURCES
;
397 RtlCopyMemory (buffer
, temp
, length
* sizeof(WCHAR
));
398 Irp
->IoStatus
.Information
= (ULONG_PTR
) buffer
;
399 DPRINT("BusQueryDeviceID: %ls\n",buffer
);
402 case BusQueryInstanceID
:
403 /* See comment in BusQueryDeviceID case */
404 if(DeviceData
->AcpiHandle
)
406 acpi_bus_get_device(DeviceData
->AcpiHandle
, &Device
);
408 if (Device
->flags
.unique_id
)
409 length
= swprintf(temp
,
411 Device
->pnp
.unique_id
);
413 /* FIXME: Generate unique id! */
414 length
= swprintf(temp
, L
"%ls", L
"0000");
417 /* FIXME: Generate unique id! */
418 length
= swprintf(temp
, L
"%ls", L
"0000");
420 temp
[++length
] = UNICODE_NULL
;
422 buffer
= ExAllocatePoolWithTag (PagedPool
, length
* sizeof (WCHAR
), 'IPCA');
424 status
= STATUS_INSUFFICIENT_RESOURCES
;
428 RtlCopyMemory (buffer
, temp
, length
* sizeof (WCHAR
));
429 DPRINT("BusQueryInstanceID: %ls\n",buffer
);
430 Irp
->IoStatus
.Information
= (ULONG_PTR
) buffer
;
433 case BusQueryHardwareIDs
:
436 /* See comment in BusQueryDeviceID case */
437 if (DeviceData
->AcpiHandle
)
439 acpi_bus_get_device(DeviceData
->AcpiHandle
, &Device
);
441 length
+= swprintf(&temp
[length
],
443 Device
->pnp
.hardware_id
);
446 length
+= swprintf(&temp
[length
],
448 Device
->pnp
.hardware_id
);
453 length
+= swprintf(&temp
[length
],
454 L
"ACPI\\FixedButton");
457 length
+= swprintf(&temp
[length
],
462 temp
[length
] = UNICODE_NULL
;
466 temp
[length
] = UNICODE_NULL
;
468 buffer
= ExAllocatePoolWithTag (PagedPool
, length
* sizeof(WCHAR
), 'IPCA');
471 status
= STATUS_INSUFFICIENT_RESOURCES
;
475 RtlCopyMemory (buffer
, temp
, length
* sizeof(WCHAR
));
476 Irp
->IoStatus
.Information
= (ULONG_PTR
) buffer
;
477 DPRINT("BusQueryHardwareIDs: %ls\n",buffer
);
481 status
= Irp
->IoStatus
.Status
;
487 Bus_PDO_QueryDeviceText(
488 PPDO_DEVICE_DATA DeviceData
,
492 PIO_STACK_LOCATION stack
;
496 stack
= IoGetCurrentIrpStackLocation (Irp
);
498 switch (stack
->Parameters
.QueryDeviceText
.DeviceTextType
) {
500 case DeviceTextDescription
:
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)
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
564 else if (!DeviceData
->AcpiHandle
)
565 Buffer
= L
"ACPI Fixed Feature Button";
567 Buffer
= L
"Other ACPI device";
569 DPRINT("\tDeviceTextDescription :%ws\n", Buffer
);
571 Irp
->IoStatus
.Information
= (ULONG_PTR
) Buffer
;
573 status
= STATUS_SUCCESS
;
577 status
= Irp
->IoStatus
.Status
;
586 Bus_PDO_QueryResources(
587 PPDO_DEVICE_DATA DeviceData
,
590 ULONG NumberOfResources
= 0;
591 PCM_RESOURCE_LIST ResourceList
;
592 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor
;
593 ACPI_STATUS AcpiStatus
;
595 ACPI_RESOURCE
* resource
;
596 ULONG ResourceListSize
;
599 /* Get current resources */
601 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
602 if ((!ACPI_SUCCESS(AcpiStatus
) && AcpiStatus
!= AE_BUFFER_OVERFLOW
) ||
605 return Irp
->IoStatus
.Status
;
608 Buffer
.Pointer
= ExAllocatePool(PagedPool
, Buffer
.Length
);
610 return STATUS_INSUFFICIENT_RESOURCES
;
612 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
613 if (!ACPI_SUCCESS(AcpiStatus
))
615 DPRINT1("AcpiGetCurrentResources #2 failed (0x%x)\n", AcpiStatus
);
617 return STATUS_UNSUCCESSFUL
;
620 resource
= Buffer
.Pointer
;
621 /* Count number of resources */
622 while (resource
->Type
!= ACPI_RESOURCE_TYPE_END_TAG
)
624 switch (resource
->Type
)
626 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ
:
628 ACPI_RESOURCE_EXTENDED_IRQ
*irq_data
= (ACPI_RESOURCE_EXTENDED_IRQ
*) &resource
->Data
;
629 NumberOfResources
+= irq_data
->InterruptCount
;
632 case ACPI_RESOURCE_TYPE_IRQ
:
634 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
635 NumberOfResources
+= irq_data
->InterruptCount
;
638 case ACPI_RESOURCE_TYPE_DMA
:
640 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
641 NumberOfResources
+= dma_data
->ChannelCount
;
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
:
657 DPRINT1("Unknown resource type: %d\n", resource
->Type
);
661 resource
= ACPI_NEXT_RESOURCE(resource
);
664 /* Allocate memory */
665 ResourceListSize
= sizeof(CM_RESOURCE_LIST
) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) * (NumberOfResources
- 1);
666 ResourceList
= (PCM_RESOURCE_LIST
)ExAllocatePool(PagedPool
, ResourceListSize
);
670 ExFreePool(Buffer
.Pointer
);
671 return STATUS_INSUFFICIENT_RESOURCES
;
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
;
681 /* Fill resources list structure */
682 resource
= Buffer
.Pointer
;
683 while (resource
->Type
!= ACPI_RESOURCE_TYPE_END_TAG
)
685 switch (resource
->Type
)
687 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ
:
689 ACPI_RESOURCE_EXTENDED_IRQ
*irq_data
= (ACPI_RESOURCE_EXTENDED_IRQ
*) &resource
->Data
;
690 for (i
= 0; i
< irq_data
->InterruptCount
; i
++)
692 ResourceDescriptor
->Type
= CmResourceTypeInterrupt
;
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);
702 ResourceDescriptor
++;
706 case ACPI_RESOURCE_TYPE_IRQ
:
708 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
709 for (i
= 0; i
< irq_data
->InterruptCount
; i
++)
711 ResourceDescriptor
->Type
= CmResourceTypeInterrupt
;
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);
721 ResourceDescriptor
++;
725 case ACPI_RESOURCE_TYPE_DMA
:
727 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
728 for (i
= 0; i
< dma_data
->ChannelCount
; i
++)
730 ResourceDescriptor
->Type
= CmResourceTypeDma
;
731 ResourceDescriptor
->Flags
= 0;
732 switch (dma_data
->Type
)
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;
738 if (dma_data
->BusMaster
== ACPI_BUS_MASTER
)
739 ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_BUS_MASTER
;
740 switch (dma_data
->Transfer
)
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;
746 ResourceDescriptor
->u
.Dma
.Channel
= dma_data
->Channels
[i
];
748 ResourceDescriptor
++;
752 case ACPI_RESOURCE_TYPE_IO
:
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
;
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
;
765 ResourceDescriptor
++;
768 case ACPI_RESOURCE_TYPE_ADDRESS16
:
770 ACPI_RESOURCE_ADDRESS16
*addr16_data
= (ACPI_RESOURCE_ADDRESS16
*) &resource
->Data
;
771 if (addr16_data
->ResourceType
== ACPI_BUS_NUMBER_RANGE
)
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
;
779 else if (addr16_data
->ResourceType
== ACPI_IO_RANGE
)
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
;
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
;
797 ResourceDescriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_WRITE
;
798 switch (addr16_data
->Info
.Mem
.Caching
)
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;
804 ResourceDescriptor
->u
.Memory
.Start
.QuadPart
= addr16_data
->Minimum
;
805 ResourceDescriptor
->u
.Memory
.Length
= addr16_data
->AddressLength
;
807 ResourceDescriptor
++;
810 case ACPI_RESOURCE_TYPE_ADDRESS32
:
812 ACPI_RESOURCE_ADDRESS32
*addr32_data
= (ACPI_RESOURCE_ADDRESS32
*) &resource
->Data
;
813 if (addr32_data
->ResourceType
== ACPI_BUS_NUMBER_RANGE
)
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
;
821 else if (addr32_data
->ResourceType
== ACPI_IO_RANGE
)
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
;
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
;
839 ResourceDescriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_WRITE
;
840 switch (addr32_data
->Info
.Mem
.Caching
)
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;
846 ResourceDescriptor
->u
.Memory
.Start
.QuadPart
= addr32_data
->Minimum
;
847 ResourceDescriptor
->u
.Memory
.Length
= addr32_data
->AddressLength
;
849 ResourceDescriptor
++;
852 case ACPI_RESOURCE_TYPE_ADDRESS64
:
854 ACPI_RESOURCE_ADDRESS64
*addr64_data
= (ACPI_RESOURCE_ADDRESS64
*) &resource
->Data
;
855 if (addr64_data
->ResourceType
== ACPI_BUS_NUMBER_RANGE
)
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
;
864 else if (addr64_data
->ResourceType
== ACPI_IO_RANGE
)
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
;
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
;
882 ResourceDescriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_WRITE
;
883 switch (addr64_data
->Info
.Mem
.Caching
)
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;
889 ResourceDescriptor
->u
.Memory
.Start
.QuadPart
= addr64_data
->Minimum
;
890 ResourceDescriptor
->u
.Memory
.Length
= addr64_data
->AddressLength
;
892 ResourceDescriptor
++;
895 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64
:
897 ACPI_RESOURCE_EXTENDED_ADDRESS64
*addr64_data
= (ACPI_RESOURCE_EXTENDED_ADDRESS64
*) &resource
->Data
;
898 if (addr64_data
->ResourceType
== ACPI_BUS_NUMBER_RANGE
)
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
;
907 else if (addr64_data
->ResourceType
== ACPI_IO_RANGE
)
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
;
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
;
925 ResourceDescriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_WRITE
;
926 switch (addr64_data
->Info
.Mem
.Caching
)
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;
932 ResourceDescriptor
->u
.Memory
.Start
.QuadPart
= addr64_data
->Minimum
;
933 ResourceDescriptor
->u
.Memory
.Length
= addr64_data
->AddressLength
;
935 ResourceDescriptor
++;
938 case ACPI_RESOURCE_TYPE_MEMORY24
:
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
;
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
;
951 ResourceDescriptor
++;
954 case ACPI_RESOURCE_TYPE_MEMORY32
:
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
;
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
;
967 ResourceDescriptor
++;
975 resource
= ACPI_NEXT_RESOURCE(resource
);
978 ExFreePool(Buffer
.Pointer
);
979 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
980 return STATUS_SUCCESS
;
984 Bus_PDO_QueryResourceRequirements(
985 PPDO_DEVICE_DATA DeviceData
,
988 ULONG NumberOfResources
= 0;
989 ACPI_STATUS AcpiStatus
;
991 ACPI_RESOURCE
* resource
;
992 ULONG i
, RequirementsListSize
;
993 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
994 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor
;
995 BOOLEAN CurrentRes
= FALSE
;
1000 /* Get current resources */
1005 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
1007 AcpiStatus
= AcpiGetPossibleResources(DeviceData
->AcpiHandle
, &Buffer
);
1008 if ((!ACPI_SUCCESS(AcpiStatus
) && AcpiStatus
!= AE_BUFFER_OVERFLOW
) ||
1014 return Irp
->IoStatus
.Status
;
1020 Buffer
.Pointer
= ExAllocatePool(PagedPool
, Buffer
.Length
);
1021 if (!Buffer
.Pointer
)
1022 return STATUS_INSUFFICIENT_RESOURCES
;
1025 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
1027 AcpiStatus
= AcpiGetPossibleResources(DeviceData
->AcpiHandle
, &Buffer
);
1028 if (!ACPI_SUCCESS(AcpiStatus
))
1030 DPRINT1("AcpiGetCurrentResources #2 failed (0x%x)\n", AcpiStatus
);
1032 return STATUS_UNSUCCESSFUL
;
1035 resource
= Buffer
.Pointer
;
1036 /* Count number of resources */
1037 while (resource
->Type
!= ACPI_RESOURCE_TYPE_END_TAG
)
1039 switch (resource
->Type
)
1041 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ
:
1043 ACPI_RESOURCE_EXTENDED_IRQ
*irq_data
= (ACPI_RESOURCE_EXTENDED_IRQ
*) &resource
->Data
;
1044 NumberOfResources
+= irq_data
->InterruptCount
;
1047 case ACPI_RESOURCE_TYPE_IRQ
:
1049 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
1050 NumberOfResources
+= irq_data
->InterruptCount
;
1053 case ACPI_RESOURCE_TYPE_DMA
:
1055 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
1056 NumberOfResources
+= dma_data
->ChannelCount
;
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
:
1067 NumberOfResources
++;
1075 resource
= ACPI_NEXT_RESOURCE(resource
);
1078 RequirementsListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
) + sizeof(IO_RESOURCE_DESCRIPTOR
) * (NumberOfResources
- 1);
1079 RequirementsList
= (PIO_RESOURCE_REQUIREMENTS_LIST
)ExAllocatePool(PagedPool
, RequirementsListSize
);
1081 if (!RequirementsList
)
1083 ExFreePool(Buffer
.Pointer
);
1084 return STATUS_INSUFFICIENT_RESOURCES
;
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
;
1096 /* Fill resources list structure */
1097 resource
= Buffer
.Pointer
;
1098 while (resource
->Type
!= ACPI_RESOURCE_TYPE_END_TAG
)
1100 switch (resource
->Type
)
1102 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ
:
1104 ACPI_RESOURCE_EXTENDED_IRQ
*irq_data
= (ACPI_RESOURCE_EXTENDED_IRQ
*) &resource
->Data
;
1105 for (i
= 0; i
< irq_data
->InterruptCount
; i
++)
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
];
1114 RequirementDescriptor
++;
1118 case ACPI_RESOURCE_TYPE_IRQ
:
1120 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
1121 for (i
= 0; i
< irq_data
->InterruptCount
; i
++)
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
];
1130 RequirementDescriptor
++;
1134 case ACPI_RESOURCE_TYPE_DMA
:
1136 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
1137 for (i
= 0; i
< dma_data
->ChannelCount
; i
++)
1139 RequirementDescriptor
->Type
= CmResourceTypeDma
;
1140 RequirementDescriptor
->Flags
= 0;
1141 switch (dma_data
->Type
)
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;
1147 if (dma_data
->BusMaster
== ACPI_BUS_MASTER
)
1148 RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_BUS_MASTER
;
1149 switch (dma_data
->Transfer
)
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;
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
++;
1164 case ACPI_RESOURCE_TYPE_IO
:
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
;
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
;
1180 RequirementDescriptor
++;
1183 case ACPI_RESOURCE_TYPE_ADDRESS16
:
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
)
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
;
1196 else if (addr16_data
->ResourceType
== ACPI_IO_RANGE
)
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
;
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
;
1215 RequirementDescriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_WRITE
;
1216 switch (addr16_data
->Info
.Mem
.Caching
)
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;
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
;
1226 RequirementDescriptor
++;
1229 case ACPI_RESOURCE_TYPE_ADDRESS32
:
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
)
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
;
1242 else if (addr32_data
->ResourceType
== ACPI_IO_RANGE
)
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
;
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
;
1261 RequirementDescriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_WRITE
;
1262 switch (addr32_data
->Info
.Mem
.Caching
)
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;
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
;
1272 RequirementDescriptor
++;
1275 case ACPI_RESOURCE_TYPE_ADDRESS64
:
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
)
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
;
1289 else if (addr64_data
->ResourceType
== ACPI_IO_RANGE
)
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
;
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
;
1308 RequirementDescriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_WRITE
;
1309 switch (addr64_data
->Info
.Mem
.Caching
)
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;
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
;
1319 RequirementDescriptor
++;
1322 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64
:
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
)
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
;
1336 else if (addr64_data
->ResourceType
== ACPI_IO_RANGE
)
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
;
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
;
1355 RequirementDescriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_WRITE
;
1356 switch (addr64_data
->Info
.Mem
.Caching
)
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;
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
;
1366 RequirementDescriptor
++;
1369 case ACPI_RESOURCE_TYPE_MEMORY24
:
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
;
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
;
1384 RequirementDescriptor
++;
1387 case ACPI_RESOURCE_TYPE_MEMORY32
:
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
;
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
;
1402 RequirementDescriptor
++;
1410 resource
= ACPI_NEXT_RESOURCE(resource
);
1412 ExFreePool(Buffer
.Pointer
);
1414 Irp
->IoStatus
.Information
= (ULONG_PTR
)RequirementsList
;
1416 return STATUS_SUCCESS
;
1420 Bus_PDO_QueryDeviceRelations(
1421 PPDO_DEVICE_DATA DeviceData
,
1425 Routine Description:
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).
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.
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.
1446 DeviceData - Pointer to the PDO's device extension.
1447 Irp - Pointer to the irp.
1456 PIO_STACK_LOCATION stack
;
1457 PDEVICE_RELATIONS deviceRelations
;
1462 stack
= IoGetCurrentIrpStackLocation (Irp
);
1464 switch (stack
->Parameters
.QueryDeviceRelations
.Type
) {
1466 case TargetDeviceRelation
:
1468 deviceRelations
= (PDEVICE_RELATIONS
) Irp
->IoStatus
.Information
;
1469 if (deviceRelations
) {
1471 // Only PDO can handle this request. Somebody above
1472 // is not playing by rule.
1474 ASSERTMSG("Someone above is handling TargetDeviceRelation", !deviceRelations
);
1477 deviceRelations
= (PDEVICE_RELATIONS
)
1478 ExAllocatePoolWithTag (PagedPool
,
1479 sizeof(DEVICE_RELATIONS
),
1481 if (!deviceRelations
) {
1482 status
= STATUS_INSUFFICIENT_RESOURCES
;
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.
1493 deviceRelations
->Count
= 1;
1494 deviceRelations
->Objects
[0] = DeviceData
->Common
.Self
;
1495 ObReferenceObject(DeviceData
->Common
.Self
);
1497 status
= STATUS_SUCCESS
;
1498 Irp
->IoStatus
.Information
= (ULONG_PTR
) deviceRelations
;
1501 case BusRelations
: // Not handled by PDO
1502 case EjectionRelations
: // optional for PDO
1503 case RemovalRelations
: // // optional for PDO
1505 status
= Irp
->IoStatus
.Status
;
1512 Bus_PDO_QueryBusInformation(
1513 PPDO_DEVICE_DATA DeviceData
,
1517 Routine Description:
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).
1525 DeviceData - Pointer to the PDO's device extension.
1526 Irp - Pointer to the irp.
1535 PPNP_BUS_INFORMATION busInfo
;
1539 busInfo
= ExAllocatePoolWithTag (PagedPool
, sizeof(PNP_BUS_INFORMATION
),
1542 if (busInfo
== NULL
) {
1543 return STATUS_INSUFFICIENT_RESOURCES
;
1546 busInfo
->BusTypeGuid
= GUID_ACPI_INTERFACE_STANDARD
;
1548 busInfo
->LegacyBusType
= InternalPowerBus
;
1550 busInfo
->BusNumber
= 0; //fixme
1552 Irp
->IoStatus
.Information
= (ULONG_PTR
)busInfo
;
1554 return STATUS_SUCCESS
;
1559 Bus_GetDeviceCapabilities(
1560 PDEVICE_OBJECT DeviceObject
,
1561 PDEVICE_CAPABILITIES DeviceCapabilities
1564 IO_STATUS_BLOCK ioStatus
;
1567 PDEVICE_OBJECT targetObject
;
1568 PIO_STACK_LOCATION irpStack
;
1574 // Initialize the capabilities that we will send down
1576 RtlZeroMemory( DeviceCapabilities
, sizeof(DEVICE_CAPABILITIES
) );
1577 DeviceCapabilities
->Size
= sizeof(DEVICE_CAPABILITIES
);
1578 DeviceCapabilities
->Version
= 1;
1579 DeviceCapabilities
->Address
= -1;
1580 DeviceCapabilities
->UINumber
= -1;
1583 // Initialize the event
1585 KeInitializeEvent( &pnpEvent
, NotificationEvent
, FALSE
);
1587 targetObject
= IoGetAttachedDeviceReference( DeviceObject
);
1592 pnpIrp
= IoBuildSynchronousFsdRequest(
1601 if (pnpIrp
== NULL
) {
1603 status
= STATUS_INSUFFICIENT_RESOURCES
;
1604 goto GetDeviceCapabilitiesExit
;
1609 // Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
1611 pnpIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
1614 // Get the top of stack
1616 irpStack
= IoGetNextIrpStackLocation( pnpIrp
);
1619 // Set the top of stack
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
;
1629 status
= IoCallDriver( targetObject
, pnpIrp
);
1630 if (status
== STATUS_PENDING
) {
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.
1640 KeWaitForSingleObject(
1647 status
= ioStatus
.Status
;
1651 GetDeviceCapabilitiesExit
:
1653 // Done with reference
1655 ObDereferenceObject( targetObject
);