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
35 struct acpi_device
*device
= NULL
;
40 if (DeviceData
->AcpiHandle
)
41 acpi_bus_get_device(DeviceData
->AcpiHandle
, &device
);
45 // NB: Because we are a bus enumerator, we have no one to whom we could
46 // defer these irps. Therefore we do not pass them down but merely
50 switch (IrpStack
->MinorFunction
) {
52 case IRP_MN_START_DEVICE
:
55 // Here we do what ever initialization and ``turning on'' that is
56 // required to allow others to access this device.
57 // Power up the device.
59 if (device
&& !ACPI_SUCCESS(acpi_power_transition(device
, ACPI_STATE_D0
)))
61 DPRINT1("Device %x failed to start!\n", device
);
62 status
= STATUS_UNSUCCESSFUL
;
66 state
.DeviceState
= PowerDeviceD0
;
67 PoSetPowerState(DeviceData
->Common
.Self
, DevicePowerState
, state
);
68 DeviceData
->Common
.DevicePowerState
= PowerDeviceD0
;
69 SET_NEW_PNP_STATE(DeviceData
->Common
, Started
);
70 status
= STATUS_SUCCESS
;
73 case IRP_MN_STOP_DEVICE
:
76 // Here we shut down the device and give up and unmap any resources
77 // we acquired for the device.
79 if (device
&& !ACPI_SUCCESS(acpi_power_transition(device
, ACPI_STATE_D3
)))
81 DPRINT1("Device %x failed to stop!\n", device
);
82 status
= STATUS_UNSUCCESSFUL
;
86 state
.DeviceState
= PowerDeviceD3
;
87 PoSetPowerState(DeviceData
->Common
.Self
, DevicePowerState
, state
);
88 DeviceData
->Common
.DevicePowerState
= PowerDeviceD3
;
89 SET_NEW_PNP_STATE(DeviceData
->Common
, Stopped
);
90 status
= STATUS_SUCCESS
;
94 case IRP_MN_QUERY_STOP_DEVICE
:
97 // No reason here why we can't stop the device.
98 // If there were a reason we should speak now, because answering success
99 // here may result in a stop device irp.
102 SET_NEW_PNP_STATE(DeviceData
->Common
, StopPending
);
103 status
= STATUS_SUCCESS
;
106 case IRP_MN_CANCEL_STOP_DEVICE
:
109 // The stop was canceled. Whatever state we set, or resources we put
110 // on hold in anticipation of the forthcoming STOP device IRP should be
111 // put back to normal. Someone, in the long list of concerned parties,
112 // has failed the stop device query.
116 // First check to see whether you have received cancel-stop
117 // without first receiving a query-stop. This could happen if someone
118 // above us fails a query-stop and passes down the subsequent
122 if (StopPending
== DeviceData
->Common
.DevicePnPState
)
125 // We did receive a query-stop, so restore.
127 RESTORE_PREVIOUS_PNP_STATE(DeviceData
->Common
);
129 acpi_power_transition(device
, ACPI_STATE_D0
);
131 status
= STATUS_SUCCESS
;// We must not fail this IRP.
133 case IRP_MN_QUERY_CAPABILITIES
:
136 // Return the capabilities of a device, such as whether the device
137 // can be locked or ejected..etc
140 status
= Bus_PDO_QueryDeviceCaps(DeviceData
, Irp
);
144 case IRP_MN_QUERY_ID
:
146 // Query the IDs of the device
147 status
= Bus_PDO_QueryDeviceId(DeviceData
, Irp
);
151 case IRP_MN_QUERY_DEVICE_RELATIONS
:
153 DPRINT("\tQueryDeviceRelation Type: %s\n",DbgDeviceRelationString(\
154 IrpStack
->Parameters
.QueryDeviceRelations
.Type
));
156 status
= Bus_PDO_QueryDeviceRelations(DeviceData
, Irp
);
160 case IRP_MN_QUERY_DEVICE_TEXT
:
162 status
= Bus_PDO_QueryDeviceText(DeviceData
, Irp
);
166 case IRP_MN_QUERY_RESOURCES
:
168 status
= Bus_PDO_QueryResources(DeviceData
, Irp
);
172 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
174 status
= Bus_PDO_QueryResourceRequirements(DeviceData
, Irp
);
178 case IRP_MN_QUERY_BUS_INFORMATION
:
180 status
= Bus_PDO_QueryBusInformation(DeviceData
, Irp
);
185 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
188 // OPTIONAL for bus drivers.
189 // The PnP Manager sends this IRP to a device
190 // stack so filter and function drivers can adjust the
191 // resources required by the device, if appropriate.
196 //case IRP_MN_QUERY_PNP_DEVICE_STATE:
199 // OPTIONAL for bus drivers.
200 // The PnP Manager sends this IRP after the drivers for
201 // a device return success from the IRP_MN_START_DEVICE
202 // request. The PnP Manager also sends this IRP when a
203 // driver for the device calls IoInvalidateDeviceState.
208 //case IRP_MN_READ_CONFIG:
209 //case IRP_MN_WRITE_CONFIG:
212 // Bus drivers for buses with configuration space must handle
213 // this request for their child devices. Our devices don't
214 // have a config space.
219 //case IRP_MN_SET_LOCK:
226 // For PnP requests to the PDO that we do not understand we should
227 // return the IRP WITHOUT setting the status or information fields.
228 // These fields may have already been set by a filter (eg acpi).
229 status
= Irp
->IoStatus
.Status
;
234 Irp
->IoStatus
.Status
= status
;
235 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
241 Bus_PDO_QueryDeviceCaps(
242 PPDO_DEVICE_DATA DeviceData
,
246 PIO_STACK_LOCATION stack
;
247 PDEVICE_CAPABILITIES deviceCapabilities
;
248 struct acpi_device
*device
= NULL
;
253 if (DeviceData
->AcpiHandle
)
254 acpi_bus_get_device(DeviceData
->AcpiHandle
, &device
);
256 stack
= IoGetCurrentIrpStackLocation (Irp
);
261 deviceCapabilities
=stack
->Parameters
.DeviceCapabilities
.Capabilities
;
264 // Set the capabilities.
267 if (deviceCapabilities
->Version
!= 1 ||
268 deviceCapabilities
->Size
< sizeof(DEVICE_CAPABILITIES
))
270 return STATUS_UNSUCCESSFUL
;
273 deviceCapabilities
->D1Latency
= 0;
274 deviceCapabilities
->D2Latency
= 0;
275 deviceCapabilities
->D3Latency
= 0;
277 deviceCapabilities
->DeviceState
[PowerSystemWorking
] = PowerDeviceD0
;
278 deviceCapabilities
->DeviceState
[PowerSystemSleeping1
] = PowerDeviceD3
;
279 deviceCapabilities
->DeviceState
[PowerSystemSleeping2
] = PowerDeviceD3
;
280 deviceCapabilities
->DeviceState
[PowerSystemSleeping3
] = PowerDeviceD3
;
282 for (i
= 0; i
< ACPI_D_STATE_COUNT
&& device
; i
++)
284 if (!device
->power
.states
[i
].flags
.valid
)
290 deviceCapabilities
->DeviceState
[PowerSystemWorking
] = PowerDeviceD0
;
294 deviceCapabilities
->DeviceState
[PowerSystemSleeping1
] = PowerDeviceD1
;
295 deviceCapabilities
->D1Latency
= device
->power
.states
[i
].latency
;
299 deviceCapabilities
->DeviceState
[PowerSystemSleeping2
] = PowerDeviceD2
;
300 deviceCapabilities
->D2Latency
= device
->power
.states
[i
].latency
;
304 deviceCapabilities
->DeviceState
[PowerSystemSleeping3
] = PowerDeviceD3
;
305 deviceCapabilities
->D3Latency
= device
->power
.states
[i
].latency
;
310 // We can wake the system from D1
311 deviceCapabilities
->DeviceWake
= PowerDeviceD1
;
314 deviceCapabilities
->DeviceD1
=
315 (deviceCapabilities
->DeviceState
[PowerSystemSleeping1
] == PowerDeviceD1
) ? TRUE
: FALSE
;
316 deviceCapabilities
->DeviceD2
=
317 (deviceCapabilities
->DeviceState
[PowerSystemSleeping2
] == PowerDeviceD2
) ? TRUE
: FALSE
;
319 deviceCapabilities
->WakeFromD0
= FALSE
;
320 deviceCapabilities
->WakeFromD1
= TRUE
; //Yes we can
321 deviceCapabilities
->WakeFromD2
= FALSE
;
322 deviceCapabilities
->WakeFromD3
= FALSE
;
326 deviceCapabilities
->EjectSupported
= device
->flags
.ejectable
;
327 deviceCapabilities
->HardwareDisabled
= !device
->status
.enabled
;
328 deviceCapabilities
->Removable
= device
->flags
.removable
;
329 deviceCapabilities
->SurpriseRemovalOK
= device
->flags
.suprise_removal_ok
;
330 deviceCapabilities
->UniqueID
= device
->flags
.unique_id
;
331 deviceCapabilities
->NoDisplayInUI
= !device
->status
.show_in_ui
;
332 deviceCapabilities
->Address
= device
->pnp
.bus_address
;
336 deviceCapabilities
->EjectSupported
= FALSE
;
337 deviceCapabilities
->HardwareDisabled
= FALSE
;
338 deviceCapabilities
->Removable
= FALSE
;
339 deviceCapabilities
->SurpriseRemovalOK
= FALSE
;
340 deviceCapabilities
->UniqueID
= FALSE
;
341 deviceCapabilities
->NoDisplayInUI
= FALSE
;
342 deviceCapabilities
->Address
= 0;
345 deviceCapabilities
->SilentInstall
= FALSE
;
346 deviceCapabilities
->UINumber
= (ULONG
)-1;
348 return STATUS_SUCCESS
;
353 Bus_PDO_QueryDeviceId(
354 PPDO_DEVICE_DATA DeviceData
,
357 PIO_STACK_LOCATION stack
;
361 NTSTATUS status
= STATUS_SUCCESS
;
362 struct acpi_device
*Device
;
366 stack
= IoGetCurrentIrpStackLocation (Irp
);
368 switch (stack
->Parameters
.QueryId
.IdType
) {
370 case BusQueryDeviceID
:
371 if (DeviceData
->AcpiHandle
)
373 acpi_bus_get_device(DeviceData
->AcpiHandle
, &Device
);
375 length
= swprintf(temp
,
377 Device
->pnp
.hardware_id
);
381 /* We know it's a fixed feature button because
382 * these are direct children of the ACPI root device
383 * and therefore have no handle
385 length
= swprintf(temp
,
386 L
"ACPI\\FixedButton");
389 temp
[++length
] = UNICODE_NULL
;
391 buffer
= ExAllocatePoolWithTag (PagedPool
, length
* sizeof(WCHAR
), 'IPCA');
394 status
= STATUS_INSUFFICIENT_RESOURCES
;
398 RtlCopyMemory (buffer
, temp
, length
* sizeof(WCHAR
));
399 Irp
->IoStatus
.Information
= (ULONG_PTR
) buffer
;
400 DPRINT("BusQueryDeviceID: %ls\n",buffer
);
403 case BusQueryInstanceID
:
404 /* See comment in BusQueryDeviceID case */
405 if(DeviceData
->AcpiHandle
)
407 acpi_bus_get_device(DeviceData
->AcpiHandle
, &Device
);
409 if (Device
->flags
.unique_id
)
410 length
= swprintf(temp
,
412 Device
->pnp
.unique_id
);
414 /* FIXME: Generate unique id! */
415 length
= swprintf(temp
, L
"%ls", L
"0000");
418 /* FIXME: Generate unique id! */
419 length
= swprintf(temp
, L
"%ls", L
"0000");
421 temp
[++length
] = UNICODE_NULL
;
423 buffer
= ExAllocatePoolWithTag (PagedPool
, length
* sizeof (WCHAR
), 'IPCA');
425 status
= STATUS_INSUFFICIENT_RESOURCES
;
429 RtlCopyMemory (buffer
, temp
, length
* sizeof (WCHAR
));
430 DPRINT("BusQueryInstanceID: %ls\n",buffer
);
431 Irp
->IoStatus
.Information
= (ULONG_PTR
) buffer
;
434 case BusQueryHardwareIDs
:
437 /* See comment in BusQueryDeviceID case */
438 if (DeviceData
->AcpiHandle
)
440 acpi_bus_get_device(DeviceData
->AcpiHandle
, &Device
);
442 length
+= swprintf(&temp
[length
],
444 Device
->pnp
.hardware_id
);
447 length
+= swprintf(&temp
[length
],
449 Device
->pnp
.hardware_id
);
454 length
+= swprintf(&temp
[length
],
455 L
"ACPI\\FixedButton");
458 length
+= swprintf(&temp
[length
],
463 temp
[length
] = UNICODE_NULL
;
467 temp
[length
] = UNICODE_NULL
;
469 buffer
= ExAllocatePoolWithTag (PagedPool
, length
* sizeof(WCHAR
), 'IPCA');
472 status
= STATUS_INSUFFICIENT_RESOURCES
;
476 RtlCopyMemory (buffer
, temp
, length
* sizeof(WCHAR
));
477 Irp
->IoStatus
.Information
= (ULONG_PTR
) buffer
;
478 DPRINT("BusQueryHardwareIDs: %ls\n",buffer
);
482 status
= Irp
->IoStatus
.Status
;
488 Bus_PDO_QueryDeviceText(
489 PPDO_DEVICE_DATA DeviceData
,
493 PIO_STACK_LOCATION stack
;
497 stack
= IoGetCurrentIrpStackLocation (Irp
);
499 switch (stack
->Parameters
.QueryDeviceText
.DeviceTextType
) {
501 case DeviceTextDescription
:
503 if (!Irp
->IoStatus
.Information
) {
504 if (wcsstr (DeviceData
->HardwareIDs
, L
"PNP000") != 0)
505 Buffer
= L
"Programmable interrupt controller";
506 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP010") != 0)
507 Buffer
= L
"System timer";
508 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP020") != 0)
509 Buffer
= L
"DMA controller";
510 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP03") != 0)
511 Buffer
= L
"Keyboard";
512 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP040") != 0)
513 Buffer
= L
"Parallel port";
514 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP05") != 0)
515 Buffer
= L
"Serial port";
516 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP06") != 0)
517 Buffer
= L
"Disk controller";
518 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP07") != 0)
519 Buffer
= L
"Disk controller";
520 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP09") != 0)
521 Buffer
= L
"Display adapter";
522 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0A0") != 0)
523 Buffer
= L
"Bus controller";
524 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0E0") != 0)
525 Buffer
= L
"PCMCIA controller";
526 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0F") != 0)
527 Buffer
= L
"Mouse device";
528 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP8") != 0)
529 Buffer
= L
"Network adapter";
530 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNPA0") != 0)
531 Buffer
= L
"SCSI controller";
532 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNPB0") != 0)
533 Buffer
= L
"Multimedia device";
534 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNPC00") != 0)
536 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0C") != 0)
537 Buffer
= L
"Power Button";
538 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0E") != 0)
539 Buffer
= L
"Sleep Button";
540 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0D") != 0)
541 Buffer
= L
"Lid Switch";
542 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C09") != 0)
543 Buffer
= L
"ACPI Embedded Controller";
544 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0B") != 0)
545 Buffer
= L
"ACPI Fan";
546 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0A03") != 0)
547 Buffer
= L
"PCI Root Bridge";
548 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0A") != 0)
549 Buffer
= L
"ACPI Battery";
550 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0F") != 0)
551 Buffer
= L
"PCI Interrupt Link";
552 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ACPI_PWR") != 0)
553 Buffer
= L
"ACPI Power Resource";
554 else if (wcsstr(DeviceData
->HardwareIDs
, L
"Processor") != 0)
555 Buffer
= L
"Processor";
556 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ACPI_SYS") != 0)
557 Buffer
= L
"ACPI System";
558 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ThermalZone") != 0)
559 Buffer
= L
"ACPI Thermal Zone";
560 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ACPI0002") != 0)
561 Buffer
= L
"Smart Battery";
562 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ACPI0003") != 0)
563 Buffer
= L
"AC Adapter";
564 /* Simply checking if AcpiHandle is NULL eliminates the need to check
565 * for the 4 different names that ACPI knows the fixed feature button as internally
567 else if (!DeviceData
->AcpiHandle
)
568 Buffer
= L
"ACPI Fixed Feature Button";
570 Buffer
= L
"Other ACPI device";
572 DPRINT("\tDeviceTextDescription :%ws\n", Buffer
);
574 Irp
->IoStatus
.Information
= (ULONG_PTR
) Buffer
;
576 status
= STATUS_SUCCESS
;
580 status
= Irp
->IoStatus
.Status
;
589 Bus_PDO_QueryResources(
590 PPDO_DEVICE_DATA DeviceData
,
594 ULONG NumberOfResources
= 0;
595 PCM_RESOURCE_LIST ResourceList
;
596 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor
;
597 ACPI_STATUS AcpiStatus
;
599 ACPI_RESOURCE
* resource
;
600 ULONG ResourceListSize
;
603 ULONG RequirementsListSize
;
604 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
605 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor
;
608 /* Get current resources */
610 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
611 if (!ACPI_SUCCESS(AcpiStatus
))
613 return STATUS_SUCCESS
;
615 if (Buffer
.Length
> 0)
617 Buffer
.Pointer
= ExAllocatePool(PagedPool
, Buffer
.Length
);
622 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
623 if (!ACPI_SUCCESS(AcpiStatus
))
629 resource
= Buffer
.Pointer
;
630 /* Count number of resources */
634 switch (resource
->Type
)
636 case ACPI_RESOURCE_TYPE_IRQ
:
638 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
639 NumberOfResources
+= irq_data
->InterruptCount
;
642 case ACPI_RESOURCE_TYPE_DMA
:
644 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
645 NumberOfResources
+= dma_data
->ChannelCount
;
648 case ACPI_RESOURCE_TYPE_IO
:
653 case ACPI_RESOURCE_TYPE_END_TAG
:
663 resource
= ACPI_NEXT_RESOURCE(resource
);
666 /* Allocate memory */
667 ResourceListSize
= sizeof(CM_RESOURCE_LIST
) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) * (NumberOfResources
- 1);
668 ResourceList
= (PCM_RESOURCE_LIST
)ExAllocatePool(PagedPool
, ResourceListSize
);
672 ResourceList
->Count
= 1;
673 ResourceList
->List
[0].InterfaceType
= Internal
; /* FIXME */
674 ResourceList
->List
[0].BusNumber
= 0; /* We're the only ACPI bus device in the system */
675 ResourceList
->List
[0].PartialResourceList
.Version
= 1;
676 ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
677 ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
678 ResourceDescriptor
= ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
;
680 RequirementsListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
) + sizeof(IO_RESOURCE_DESCRIPTOR
) * (NumberOfResources
- 1);
681 RequirementsList
= (PIO_RESOURCE_REQUIREMENTS_LIST
)ExAllocatePool(PagedPool
, RequirementsListSize
);
683 if (!RequirementsList
)
685 ExFreePool(ResourceList
);
686 return STATUS_SUCCESS
;
688 RequirementsList
->ListSize
= RequirementsListSize
;
689 RequirementsList
->InterfaceType
= Internal
;
690 RequirementsList
->BusNumber
= 0;
691 RequirementsList
->SlotNumber
= 0; /* Not used by WDM drivers */
692 RequirementsList
->AlternativeLists
= 1;
693 RequirementsList
->List
[0].Version
= 1;
694 RequirementsList
->List
[0].Revision
= 1;
695 RequirementsList
->List
[0].Count
= NumberOfResources
;
696 RequirementDescriptor
= RequirementsList
->List
[0].Descriptors
;
698 /* Fill resources list structure */
702 switch (resource
->Type
)
704 case ACPI_RESOURCE_TYPE_IRQ
:
706 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
707 for (i
= 0; i
< irq_data
->InterruptCount
; i
++)
709 ResourceDescriptor
->Type
= CmResourceTypeInterrupt
;
711 ResourceDescriptor
->ShareDisposition
=
712 (irq_data
->Sharable
== ACPI_SHARED
? CmResourceShareShared
: CmResourceShareDeviceExclusive
);
713 ResourceDescriptor
->Flags
=
714 (irq_data
->Triggering
== ACPI_LEVEL_SENSITIVE
? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
: CM_RESOURCE_INTERRUPT_LATCHED
);
715 ResourceDescriptor
->u
.Interrupt
.Level
= irq_data
->Interrupts
[i
];
716 ResourceDescriptor
->u
.Interrupt
.Vector
= 0;
717 ResourceDescriptor
->u
.Interrupt
.Affinity
= (KAFFINITY
)(-1);
719 RequirementDescriptor
->Option
= 0; /* Required */
720 RequirementDescriptor
->Type
= ResourceDescriptor
->Type
;
721 RequirementDescriptor
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
722 RequirementDescriptor
->Flags
= ResourceDescriptor
->Flags
;
723 RequirementDescriptor
->u
.Interrupt
.MinimumVector
= RequirementDescriptor
->u
.Interrupt
.MaximumVector
724 = irq_data
->Interrupts
[i
];
726 ResourceDescriptor
++;
727 RequirementDescriptor
++;
731 case ACPI_RESOURCE_TYPE_DMA
:
733 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
734 for (i
= 0; i
< dma_data
->ChannelCount
; i
++)
736 ResourceDescriptor
->Type
= CmResourceTypeDma
;
737 ResourceDescriptor
->Flags
= 0;
738 switch (dma_data
->Type
)
740 case ACPI_TYPE_A
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_A
; break;
741 case ACPI_TYPE_B
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_B
; break;
742 case ACPI_TYPE_F
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_F
; break;
744 if (dma_data
->BusMaster
== ACPI_BUS_MASTER
)
745 ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_BUS_MASTER
;
746 switch (dma_data
->Transfer
)
748 case ACPI_TRANSFER_8
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_8
; break;
749 case ACPI_TRANSFER_16
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_16
; break;
750 case ACPI_TRANSFER_8_16
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_8_AND_16
; break;
752 ResourceDescriptor
->u
.Dma
.Channel
= dma_data
->Channels
[i
];
754 RequirementDescriptor
->Option
= 0; /* Required */
755 RequirementDescriptor
->Type
= ResourceDescriptor
->Type
;
756 RequirementDescriptor
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
757 RequirementDescriptor
->Flags
= ResourceDescriptor
->Flags
;
758 RequirementDescriptor
->u
.Dma
.MinimumChannel
= RequirementDescriptor
->u
.Dma
.MaximumChannel
759 = ResourceDescriptor
->u
.Dma
.Channel
;
761 ResourceDescriptor
++;
762 RequirementDescriptor
++;
766 case ACPI_RESOURCE_TYPE_IO
:
768 ACPI_RESOURCE_IO
*io_data
= (ACPI_RESOURCE_IO
*) &resource
->Data
;
769 ResourceDescriptor
->Type
= CmResourceTypePort
;
770 ResourceDescriptor
->ShareDisposition
= CmResourceShareDriverExclusive
;
771 ResourceDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
772 if (io_data
->IoDecode
== ACPI_DECODE_16
)
773 ResourceDescriptor
->Flags
|= CM_RESOURCE_PORT_16_BIT_DECODE
;
775 ResourceDescriptor
->Flags
|= CM_RESOURCE_PORT_10_BIT_DECODE
;
776 ResourceDescriptor
->u
.Port
.Start
.u
.HighPart
= 0;
777 ResourceDescriptor
->u
.Port
.Start
.u
.LowPart
= io_data
->Minimum
;
778 ResourceDescriptor
->u
.Port
.Length
= io_data
->AddressLength
;
780 RequirementDescriptor
->Option
= 0; /* Required */
781 RequirementDescriptor
->Type
= ResourceDescriptor
->Type
;
782 RequirementDescriptor
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
783 RequirementDescriptor
->Flags
= ResourceDescriptor
->Flags
;
784 RequirementDescriptor
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
785 RequirementDescriptor
->u
.Port
.Alignment
= 1; /* Start address is specified, so it doesn't matter */
786 RequirementDescriptor
->u
.Port
.MinimumAddress
= RequirementDescriptor
->u
.Port
.MaximumAddress
787 = ResourceDescriptor
->u
.Port
.Start
;
789 ResourceDescriptor
++;
790 RequirementDescriptor
++;
793 case ACPI_RESOURCE_TYPE_END_TAG
:
800 DPRINT1("Unhandled resource type\n");
804 resource
= ACPI_NEXT_RESOURCE(resource
);
807 ExFreePool(Buffer
.Pointer
);
808 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
809 return STATUS_SUCCESS
;
813 Bus_PDO_QueryResourceRequirements(
814 PPDO_DEVICE_DATA DeviceData
,
818 ULONG NumberOfResources
= 0;
819 ACPI_STATUS AcpiStatus
;
821 ACPI_RESOURCE
* resource
;
822 ULONG i
, RequirementsListSize
;
823 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
824 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor
;
829 /* Get current resources */
831 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
832 if (!ACPI_SUCCESS(AcpiStatus
))
834 return STATUS_SUCCESS
;
836 if (Buffer
.Length
> 0)
838 Buffer
.Pointer
= ExAllocatePool(PagedPool
, Buffer
.Length
);
843 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
844 if (!ACPI_SUCCESS(AcpiStatus
))
850 resource
= Buffer
.Pointer
;
851 /* Count number of resources */
855 switch (resource
->Type
)
857 case ACPI_RESOURCE_TYPE_IRQ
:
859 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
860 NumberOfResources
+= irq_data
->InterruptCount
;
863 case ACPI_RESOURCE_TYPE_DMA
:
865 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
866 NumberOfResources
+= dma_data
->ChannelCount
;
869 case ACPI_RESOURCE_TYPE_IO
:
874 case ACPI_RESOURCE_TYPE_END_TAG
:
884 resource
= ACPI_NEXT_RESOURCE(resource
);
887 RequirementsListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
) + sizeof(IO_RESOURCE_DESCRIPTOR
) * (NumberOfResources
- 1);
888 RequirementsList
= (PIO_RESOURCE_REQUIREMENTS_LIST
)ExAllocatePool(PagedPool
, RequirementsListSize
);
890 if (!RequirementsList
)
892 ExFreePool(Buffer
.Pointer
);
893 return STATUS_SUCCESS
;
895 RequirementsList
->ListSize
= RequirementsListSize
;
896 RequirementsList
->InterfaceType
= Internal
;
897 RequirementsList
->BusNumber
= 0;
898 RequirementsList
->SlotNumber
= 0; /* Not used by WDM drivers */
899 RequirementsList
->AlternativeLists
= 1;
900 RequirementsList
->List
[0].Version
= 1;
901 RequirementsList
->List
[0].Revision
= 1;
902 RequirementsList
->List
[0].Count
= NumberOfResources
;
903 RequirementDescriptor
= RequirementsList
->List
[0].Descriptors
;
905 /* Fill resources list structure */
909 switch (resource
->Type
)
911 case ACPI_RESOURCE_TYPE_IRQ
:
913 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
914 for (i
= 0; i
< irq_data
->InterruptCount
; i
++)
916 RequirementDescriptor
->Option
= 0; /* Required */
917 RequirementDescriptor
->Type
= CmResourceTypeInterrupt
;
918 RequirementDescriptor
->ShareDisposition
= (irq_data
->Sharable
== ACPI_SHARED
? CmResourceShareShared
: CmResourceShareDeviceExclusive
);
919 RequirementDescriptor
->Flags
=(irq_data
->Triggering
== ACPI_LEVEL_SENSITIVE
? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
: CM_RESOURCE_INTERRUPT_LATCHED
);
920 RequirementDescriptor
->u
.Interrupt
.MinimumVector
= irq_data
->Interrupts
[i
];
922 RequirementDescriptor
++;
926 case ACPI_RESOURCE_TYPE_DMA
:
928 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
929 for (i
= 0; i
< dma_data
->ChannelCount
; i
++)
931 RequirementDescriptor
->Type
= CmResourceTypeDma
;
932 RequirementDescriptor
->Flags
= 0;
933 switch (dma_data
->Type
)
935 case ACPI_TYPE_A
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_A
; break;
936 case ACPI_TYPE_B
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_B
; break;
937 case ACPI_TYPE_F
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_F
; break;
939 if (dma_data
->BusMaster
== ACPI_BUS_MASTER
)
940 RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_BUS_MASTER
;
941 switch (dma_data
->Transfer
)
943 case ACPI_TRANSFER_8
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_8
; break;
944 case ACPI_TRANSFER_16
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_16
; break;
945 case ACPI_TRANSFER_8_16
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_8_AND_16
; break;
948 RequirementDescriptor
->Option
= 0; /* Required */
949 RequirementDescriptor
->ShareDisposition
= CmResourceShareDriverExclusive
;
950 RequirementDescriptor
->u
.Dma
.MinimumChannel
= dma_data
->Channels
[i
];
951 RequirementDescriptor
++;
955 case ACPI_RESOURCE_TYPE_IO
:
957 ACPI_RESOURCE_IO
*io_data
= (ACPI_RESOURCE_IO
*) &resource
->Data
;
958 RequirementDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
959 if (io_data
->IoDecode
== ACPI_DECODE_16
)
960 RequirementDescriptor
->Flags
|= CM_RESOURCE_PORT_16_BIT_DECODE
;
962 RequirementDescriptor
->Flags
|= CM_RESOURCE_PORT_10_BIT_DECODE
;
964 RequirementDescriptor
->u
.Port
.Length
= io_data
->AddressLength
;
966 RequirementDescriptor
->Option
= 0; /* Required */
967 RequirementDescriptor
->Type
= CmResourceTypePort
;
968 RequirementDescriptor
->ShareDisposition
= CmResourceShareDriverExclusive
;
969 RequirementDescriptor
->u
.Port
.Alignment
= 1; /* Start address is specified, so it doesn't matter */
970 RequirementDescriptor
->u
.Port
.MinimumAddress
.QuadPart
= io_data
->Minimum
;
971 RequirementDescriptor
->u
.Port
.MaximumAddress
.QuadPart
= io_data
->Maximum
;
973 RequirementDescriptor
++;
976 case ACPI_RESOURCE_TYPE_END_TAG
:
983 DPRINT1("Unhandled resource type\n");
987 resource
= ACPI_NEXT_RESOURCE(resource
);
989 ExFreePool(Buffer
.Pointer
);
991 return STATUS_SUCCESS
;
995 Bus_PDO_QueryDeviceRelations(
996 PPDO_DEVICE_DATA DeviceData
,
1000 Routine Description:
1002 The PnP Manager sends this IRP to gather information about
1003 devices with a relationship to the specified device.
1004 Bus drivers must handle this request for TargetDeviceRelation
1005 for their child devices (child PDOs).
1007 If a driver returns relations in response to this IRP,
1008 it allocates a DEVICE_RELATIONS structure from paged
1009 memory containing a count and the appropriate number of
1010 device object pointers. The PnP Manager frees the structure
1011 when it is no longer needed. If a driver replaces a
1012 DEVICE_RELATIONS structure allocated by another driver,
1013 it must free the previous structure.
1015 A driver must reference the PDO of any device that it
1016 reports in this IRP (ObReferenceObject). The PnP Manager
1017 removes the reference when appropriate.
1021 DeviceData - Pointer to the PDO's device extension.
1022 Irp - Pointer to the irp.
1031 PIO_STACK_LOCATION stack
;
1032 PDEVICE_RELATIONS deviceRelations
;
1037 stack
= IoGetCurrentIrpStackLocation (Irp
);
1039 switch (stack
->Parameters
.QueryDeviceRelations
.Type
) {
1041 case TargetDeviceRelation
:
1043 deviceRelations
= (PDEVICE_RELATIONS
) Irp
->IoStatus
.Information
;
1044 if (deviceRelations
) {
1046 // Only PDO can handle this request. Somebody above
1047 // is not playing by rule.
1049 ASSERTMSG("Someone above is handling TargetDeviceRelation", !deviceRelations
);
1052 deviceRelations
= (PDEVICE_RELATIONS
)
1053 ExAllocatePoolWithTag (PagedPool
,
1054 sizeof(DEVICE_RELATIONS
),
1056 if (!deviceRelations
) {
1057 status
= STATUS_INSUFFICIENT_RESOURCES
;
1062 // There is only one PDO pointer in the structure
1063 // for this relation type. The PnP Manager removes
1064 // the reference to the PDO when the driver or application
1065 // un-registers for notification on the device.
1068 deviceRelations
->Count
= 1;
1069 deviceRelations
->Objects
[0] = DeviceData
->Common
.Self
;
1070 ObReferenceObject(DeviceData
->Common
.Self
);
1072 status
= STATUS_SUCCESS
;
1073 Irp
->IoStatus
.Information
= (ULONG_PTR
) deviceRelations
;
1076 case BusRelations
: // Not handled by PDO
1077 case EjectionRelations
: // optional for PDO
1078 case RemovalRelations
: // // optional for PDO
1080 status
= Irp
->IoStatus
.Status
;
1087 Bus_PDO_QueryBusInformation(
1088 PPDO_DEVICE_DATA DeviceData
,
1092 Routine Description:
1094 The PnP Manager uses this IRP to request the type and
1095 instance number of a device's parent bus. Bus drivers
1096 should handle this request for their child devices (PDOs).
1100 DeviceData - Pointer to the PDO's device extension.
1101 Irp - Pointer to the irp.
1110 PPNP_BUS_INFORMATION busInfo
;
1114 busInfo
= ExAllocatePoolWithTag (PagedPool
, sizeof(PNP_BUS_INFORMATION
),
1117 if (busInfo
== NULL
) {
1118 return STATUS_INSUFFICIENT_RESOURCES
;
1121 busInfo
->BusTypeGuid
= GUID_ACPI_INTERFACE_STANDARD
;
1123 busInfo
->LegacyBusType
= InternalPowerBus
;
1125 busInfo
->BusNumber
= 0; //fixme
1127 Irp
->IoStatus
.Information
= (ULONG_PTR
)busInfo
;
1129 return STATUS_SUCCESS
;
1134 Bus_GetDeviceCapabilities(
1135 PDEVICE_OBJECT DeviceObject
,
1136 PDEVICE_CAPABILITIES DeviceCapabilities
1139 IO_STATUS_BLOCK ioStatus
;
1142 PDEVICE_OBJECT targetObject
;
1143 PIO_STACK_LOCATION irpStack
;
1149 // Initialize the capabilities that we will send down
1151 RtlZeroMemory( DeviceCapabilities
, sizeof(DEVICE_CAPABILITIES
) );
1152 DeviceCapabilities
->Size
= sizeof(DEVICE_CAPABILITIES
);
1153 DeviceCapabilities
->Version
= 1;
1154 DeviceCapabilities
->Address
= -1;
1155 DeviceCapabilities
->UINumber
= -1;
1158 // Initialize the event
1160 KeInitializeEvent( &pnpEvent
, NotificationEvent
, FALSE
);
1162 targetObject
= IoGetAttachedDeviceReference( DeviceObject
);
1167 pnpIrp
= IoBuildSynchronousFsdRequest(
1176 if (pnpIrp
== NULL
) {
1178 status
= STATUS_INSUFFICIENT_RESOURCES
;
1179 goto GetDeviceCapabilitiesExit
;
1184 // Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
1186 pnpIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
1189 // Get the top of stack
1191 irpStack
= IoGetNextIrpStackLocation( pnpIrp
);
1194 // Set the top of stack
1196 RtlZeroMemory( irpStack
, sizeof(IO_STACK_LOCATION
) );
1197 irpStack
->MajorFunction
= IRP_MJ_PNP
;
1198 irpStack
->MinorFunction
= IRP_MN_QUERY_CAPABILITIES
;
1199 irpStack
->Parameters
.DeviceCapabilities
.Capabilities
= DeviceCapabilities
;
1204 status
= IoCallDriver( targetObject
, pnpIrp
);
1205 if (status
== STATUS_PENDING
) {
1208 // Block until the irp comes back.
1209 // Important thing to note here is when you allocate
1210 // the memory for an event in the stack you must do a
1211 // KernelMode wait instead of UserMode to prevent
1212 // the stack from getting paged out.
1215 KeWaitForSingleObject(
1222 status
= ioStatus
.Status
;
1226 GetDeviceCapabilitiesExit
:
1228 // Done with reference
1230 ObDereferenceObject( targetObject
);