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
;
331 deviceCapabilities
->EjectSupported
= FALSE
;
332 deviceCapabilities
->HardwareDisabled
= FALSE
;
333 deviceCapabilities
->Removable
= FALSE
;
334 deviceCapabilities
->SurpriseRemovalOK
= FALSE
;
335 deviceCapabilities
->UniqueID
= FALSE
;
336 deviceCapabilities
->NoDisplayInUI
= FALSE
;
337 deviceCapabilities
->Address
= 0;
340 deviceCapabilities
->SilentInstall
= FALSE
;
341 deviceCapabilities
->UINumber
= (ULONG
)-1;
343 return STATUS_SUCCESS
;
348 Bus_PDO_QueryDeviceId(
349 PPDO_DEVICE_DATA DeviceData
,
352 PIO_STACK_LOCATION stack
;
356 NTSTATUS status
= STATUS_SUCCESS
;
357 struct acpi_device
*Device
;
361 stack
= IoGetCurrentIrpStackLocation (Irp
);
363 switch (stack
->Parameters
.QueryId
.IdType
) {
365 case BusQueryDeviceID
:
366 if (DeviceData
->AcpiHandle
)
368 acpi_bus_get_device(DeviceData
->AcpiHandle
, &Device
);
370 length
= swprintf(temp
,
372 Device
->pnp
.hardware_id
);
376 /* We know it's a fixed feature button because
377 * these are direct children of the ACPI root device
378 * and therefore have no handle
380 length
= swprintf(temp
,
381 L
"ACPI\\FixedButton");
384 temp
[++length
] = UNICODE_NULL
;
386 buffer
= ExAllocatePoolWithTag (PagedPool
, length
* sizeof(WCHAR
), 'IPCA');
389 status
= STATUS_INSUFFICIENT_RESOURCES
;
393 RtlCopyMemory (buffer
, temp
, length
* sizeof(WCHAR
));
394 Irp
->IoStatus
.Information
= (ULONG_PTR
) buffer
;
395 DPRINT("BusQueryDeviceID: %ls\n",buffer
);
398 case BusQueryInstanceID
:
399 /* See comment in BusQueryDeviceID case */
400 if(DeviceData
->AcpiHandle
)
402 acpi_bus_get_device(DeviceData
->AcpiHandle
, &Device
);
404 if (Device
->flags
.unique_id
)
405 length
= swprintf(temp
,
407 Device
->pnp
.unique_id
);
409 /* FIXME: Generate unique id! */
410 length
= swprintf(temp
, L
"%ls", L
"0000");
413 /* FIXME: Generate unique id! */
414 length
= swprintf(temp
, L
"%ls", L
"0000");
416 temp
[++length
] = UNICODE_NULL
;
418 buffer
= ExAllocatePoolWithTag (PagedPool
, length
* sizeof (WCHAR
), 'IPCA');
420 status
= STATUS_INSUFFICIENT_RESOURCES
;
424 RtlCopyMemory (buffer
, temp
, length
* sizeof (WCHAR
));
425 DPRINT("BusQueryInstanceID: %ls\n",buffer
);
426 Irp
->IoStatus
.Information
= (ULONG_PTR
) buffer
;
429 case BusQueryHardwareIDs
:
432 /* See comment in BusQueryDeviceID case */
433 if (DeviceData
->AcpiHandle
)
435 acpi_bus_get_device(DeviceData
->AcpiHandle
, &Device
);
437 length
+= swprintf(&temp
[length
],
439 Device
->pnp
.hardware_id
);
442 length
+= swprintf(&temp
[length
],
444 Device
->pnp
.hardware_id
);
449 length
+= swprintf(&temp
[length
],
450 L
"ACPI\\FixedButton");
453 length
+= swprintf(&temp
[length
],
458 temp
[length
] = UNICODE_NULL
;
462 temp
[length
] = UNICODE_NULL
;
464 buffer
= ExAllocatePoolWithTag (PagedPool
, length
* sizeof(WCHAR
), 'IPCA');
467 status
= STATUS_INSUFFICIENT_RESOURCES
;
471 RtlCopyMemory (buffer
, temp
, length
* sizeof(WCHAR
));
472 Irp
->IoStatus
.Information
= (ULONG_PTR
) buffer
;
473 DPRINT("BusQueryHardwareIDs: %ls\n",buffer
);
477 status
= Irp
->IoStatus
.Status
;
483 Bus_PDO_QueryDeviceText(
484 PPDO_DEVICE_DATA DeviceData
,
488 PIO_STACK_LOCATION stack
;
492 stack
= IoGetCurrentIrpStackLocation (Irp
);
494 switch (stack
->Parameters
.QueryDeviceText
.DeviceTextType
) {
496 case DeviceTextDescription
:
498 if (!Irp
->IoStatus
.Information
) {
499 if (wcsstr (DeviceData
->HardwareIDs
, L
"PNP000") != 0)
500 Buffer
= L
"Programmable interrupt controller";
501 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP010") != 0)
502 Buffer
= L
"System timer";
503 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP020") != 0)
504 Buffer
= L
"DMA controller";
505 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP03") != 0)
506 Buffer
= L
"Keyboard";
507 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP040") != 0)
508 Buffer
= L
"Parallel port";
509 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP05") != 0)
510 Buffer
= L
"Serial port";
511 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP06") != 0)
512 Buffer
= L
"Disk controller";
513 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP07") != 0)
514 Buffer
= L
"Disk controller";
515 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP09") != 0)
516 Buffer
= L
"Display adapter";
517 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0A0") != 0)
518 Buffer
= L
"Bus controller";
519 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0E0") != 0)
520 Buffer
= L
"PCMCIA controller";
521 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0F") != 0)
522 Buffer
= L
"Mouse device";
523 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP8") != 0)
524 Buffer
= L
"Network adapter";
525 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNPA0") != 0)
526 Buffer
= L
"SCSI controller";
527 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNPB0") != 0)
528 Buffer
= L
"Multimedia device";
529 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNPC00") != 0)
531 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0C") != 0)
532 Buffer
= L
"Power Button";
533 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0E") != 0)
534 Buffer
= L
"Sleep Button";
535 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0D") != 0)
536 Buffer
= L
"Lid Switch";
537 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C09") != 0)
538 Buffer
= L
"ACPI Embedded Controller";
539 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0B") != 0)
540 Buffer
= L
"ACPI Fan";
541 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0A03") != 0)
542 Buffer
= L
"PCI Root Bridge";
543 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0A") != 0)
544 Buffer
= L
"ACPI Battery";
545 else if (wcsstr(DeviceData
->HardwareIDs
, L
"PNP0C0F") != 0)
546 Buffer
= L
"PCI Interrupt Link";
547 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ACPI_PWR") != 0)
548 Buffer
= L
"ACPI Power Resource";
549 else if (wcsstr(DeviceData
->HardwareIDs
, L
"Processor") != 0)
550 Buffer
= L
"Processor";
551 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ACPI_SYS") != 0)
552 Buffer
= L
"ACPI System";
553 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ThermalZone") != 0)
554 Buffer
= L
"ACPI Thermal Zone";
555 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ACPI0002") != 0)
556 Buffer
= L
"Smart Battery";
557 else if (wcsstr(DeviceData
->HardwareIDs
, L
"ACPI0003") != 0)
558 Buffer
= L
"AC Adapter";
559 /* Simply checking if AcpiHandle is NULL eliminates the need to check
560 * for the 4 different names that ACPI knows the fixed feature button as internally
562 else if (!DeviceData
->AcpiHandle
)
563 Buffer
= L
"ACPI Fixed Feature Button";
565 Buffer
= L
"Other ACPI device";
567 DPRINT("\tDeviceTextDescription :%ws\n", Buffer
);
569 Irp
->IoStatus
.Information
= (ULONG_PTR
) Buffer
;
571 status
= STATUS_SUCCESS
;
575 status
= Irp
->IoStatus
.Status
;
584 Bus_PDO_QueryResources(
585 PPDO_DEVICE_DATA DeviceData
,
589 ULONG NumberOfResources
= 0;
590 PCM_RESOURCE_LIST ResourceList
;
591 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor
;
592 ACPI_STATUS AcpiStatus
;
594 ACPI_RESOURCE
* resource
;
595 ULONG ResourceListSize
;
598 ULONG RequirementsListSize
;
599 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
600 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor
;
603 /* Get current resources */
605 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
606 if (!ACPI_SUCCESS(AcpiStatus
))
608 return STATUS_SUCCESS
;
610 if (Buffer
.Length
> 0)
612 Buffer
.Pointer
= ExAllocatePool(PagedPool
, Buffer
.Length
);
617 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
618 if (!ACPI_SUCCESS(AcpiStatus
))
624 resource
= Buffer
.Pointer
;
625 /* Count number of resources */
629 switch (resource
->Type
)
631 case ACPI_RESOURCE_TYPE_IRQ
:
633 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
634 NumberOfResources
+= irq_data
->InterruptCount
;
637 case ACPI_RESOURCE_TYPE_DMA
:
639 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
640 NumberOfResources
+= dma_data
->ChannelCount
;
643 case ACPI_RESOURCE_TYPE_IO
:
648 case ACPI_RESOURCE_TYPE_END_TAG
:
658 resource
= ACPI_NEXT_RESOURCE(resource
);
661 /* Allocate memory */
662 ResourceListSize
= sizeof(CM_RESOURCE_LIST
) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) * (NumberOfResources
- 1);
663 ResourceList
= (PCM_RESOURCE_LIST
)ExAllocatePool(PagedPool
, ResourceListSize
);
667 ResourceList
->Count
= 1;
668 ResourceList
->List
[0].InterfaceType
= Internal
; /* FIXME */
669 ResourceList
->List
[0].BusNumber
= 0; /* We're the only ACPI bus device in the system */
670 ResourceList
->List
[0].PartialResourceList
.Version
= 1;
671 ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
672 ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
673 ResourceDescriptor
= ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
;
675 RequirementsListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
) + sizeof(IO_RESOURCE_DESCRIPTOR
) * (NumberOfResources
- 1);
676 RequirementsList
= (PIO_RESOURCE_REQUIREMENTS_LIST
)ExAllocatePool(PagedPool
, RequirementsListSize
);
678 if (!RequirementsList
)
680 ExFreePool(ResourceList
);
681 return STATUS_SUCCESS
;
683 RequirementsList
->ListSize
= RequirementsListSize
;
684 RequirementsList
->InterfaceType
= Internal
;
685 RequirementsList
->BusNumber
= 0;
686 RequirementsList
->SlotNumber
= 0; /* Not used by WDM drivers */
687 RequirementsList
->AlternativeLists
= 1;
688 RequirementsList
->List
[0].Version
= 1;
689 RequirementsList
->List
[0].Revision
= 1;
690 RequirementsList
->List
[0].Count
= NumberOfResources
;
691 RequirementDescriptor
= RequirementsList
->List
[0].Descriptors
;
693 /* Fill resources list structure */
697 switch (resource
->Type
)
699 case ACPI_RESOURCE_TYPE_IRQ
:
701 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
702 for (i
= 0; i
< irq_data
->InterruptCount
; i
++)
704 ResourceDescriptor
->Type
= CmResourceTypeInterrupt
;
706 ResourceDescriptor
->ShareDisposition
=
707 (irq_data
->Sharable
== ACPI_SHARED
? CmResourceShareShared
: CmResourceShareDeviceExclusive
);
708 ResourceDescriptor
->Flags
=
709 (irq_data
->Triggering
== ACPI_LEVEL_SENSITIVE
? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
: CM_RESOURCE_INTERRUPT_LATCHED
);
710 ResourceDescriptor
->u
.Interrupt
.Level
= irq_data
->Interrupts
[i
];
711 ResourceDescriptor
->u
.Interrupt
.Vector
= 0;
712 ResourceDescriptor
->u
.Interrupt
.Affinity
= (KAFFINITY
)(-1);
714 RequirementDescriptor
->Option
= 0; /* Required */
715 RequirementDescriptor
->Type
= ResourceDescriptor
->Type
;
716 RequirementDescriptor
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
717 RequirementDescriptor
->Flags
= ResourceDescriptor
->Flags
;
718 RequirementDescriptor
->u
.Interrupt
.MinimumVector
= RequirementDescriptor
->u
.Interrupt
.MaximumVector
719 = irq_data
->Interrupts
[i
];
721 ResourceDescriptor
++;
722 RequirementDescriptor
++;
726 case ACPI_RESOURCE_TYPE_DMA
:
728 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
729 for (i
= 0; i
< dma_data
->ChannelCount
; i
++)
731 ResourceDescriptor
->Type
= CmResourceTypeDma
;
732 ResourceDescriptor
->Flags
= 0;
733 switch (dma_data
->Type
)
735 case ACPI_TYPE_A
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_A
; break;
736 case ACPI_TYPE_B
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_B
; break;
737 case ACPI_TYPE_F
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_F
; break;
739 if (dma_data
->BusMaster
== ACPI_BUS_MASTER
)
740 ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_BUS_MASTER
;
741 switch (dma_data
->Transfer
)
743 case ACPI_TRANSFER_8
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_8
; break;
744 case ACPI_TRANSFER_16
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_16
; break;
745 case ACPI_TRANSFER_8_16
: ResourceDescriptor
->Flags
|= CM_RESOURCE_DMA_8_AND_16
; break;
747 ResourceDescriptor
->u
.Dma
.Channel
= dma_data
->Channels
[i
];
749 RequirementDescriptor
->Option
= 0; /* Required */
750 RequirementDescriptor
->Type
= ResourceDescriptor
->Type
;
751 RequirementDescriptor
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
752 RequirementDescriptor
->Flags
= ResourceDescriptor
->Flags
;
753 RequirementDescriptor
->u
.Dma
.MinimumChannel
= RequirementDescriptor
->u
.Dma
.MaximumChannel
754 = ResourceDescriptor
->u
.Dma
.Channel
;
756 ResourceDescriptor
++;
757 RequirementDescriptor
++;
761 case ACPI_RESOURCE_TYPE_IO
:
763 ACPI_RESOURCE_IO
*io_data
= (ACPI_RESOURCE_IO
*) &resource
->Data
;
764 ResourceDescriptor
->Type
= CmResourceTypePort
;
765 ResourceDescriptor
->ShareDisposition
= CmResourceShareDriverExclusive
;
766 ResourceDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
767 if (io_data
->IoDecode
== ACPI_DECODE_16
)
768 ResourceDescriptor
->Flags
|= CM_RESOURCE_PORT_16_BIT_DECODE
;
770 ResourceDescriptor
->Flags
|= CM_RESOURCE_PORT_10_BIT_DECODE
;
771 ResourceDescriptor
->u
.Port
.Start
.u
.HighPart
= 0;
772 ResourceDescriptor
->u
.Port
.Start
.u
.LowPart
= io_data
->Minimum
;
773 ResourceDescriptor
->u
.Port
.Length
= io_data
->AddressLength
;
775 RequirementDescriptor
->Option
= 0; /* Required */
776 RequirementDescriptor
->Type
= ResourceDescriptor
->Type
;
777 RequirementDescriptor
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
778 RequirementDescriptor
->Flags
= ResourceDescriptor
->Flags
;
779 RequirementDescriptor
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
780 RequirementDescriptor
->u
.Port
.Alignment
= 1; /* Start address is specified, so it doesn't matter */
781 RequirementDescriptor
->u
.Port
.MinimumAddress
= RequirementDescriptor
->u
.Port
.MaximumAddress
782 = ResourceDescriptor
->u
.Port
.Start
;
784 ResourceDescriptor
++;
785 RequirementDescriptor
++;
788 case ACPI_RESOURCE_TYPE_END_TAG
:
795 DPRINT1("Unhandled resource type\n");
799 resource
= ACPI_NEXT_RESOURCE(resource
);
802 ExFreePool(Buffer
.Pointer
);
803 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
804 return STATUS_SUCCESS
;
808 Bus_PDO_QueryResourceRequirements(
809 PPDO_DEVICE_DATA DeviceData
,
813 ULONG NumberOfResources
= 0;
814 ACPI_STATUS AcpiStatus
;
816 ACPI_RESOURCE
* resource
;
817 ULONG i
, RequirementsListSize
;
818 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
819 PIO_RESOURCE_DESCRIPTOR RequirementDescriptor
;
824 /* Get current resources */
826 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
827 if (!ACPI_SUCCESS(AcpiStatus
))
829 return STATUS_SUCCESS
;
831 if (Buffer
.Length
> 0)
833 Buffer
.Pointer
= ExAllocatePool(PagedPool
, Buffer
.Length
);
838 AcpiStatus
= AcpiGetCurrentResources(DeviceData
->AcpiHandle
, &Buffer
);
839 if (!ACPI_SUCCESS(AcpiStatus
))
845 resource
= Buffer
.Pointer
;
846 /* Count number of resources */
850 switch (resource
->Type
)
852 case ACPI_RESOURCE_TYPE_IRQ
:
854 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
855 NumberOfResources
+= irq_data
->InterruptCount
;
858 case ACPI_RESOURCE_TYPE_DMA
:
860 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
861 NumberOfResources
+= dma_data
->ChannelCount
;
864 case ACPI_RESOURCE_TYPE_IO
:
869 case ACPI_RESOURCE_TYPE_END_TAG
:
879 resource
= ACPI_NEXT_RESOURCE(resource
);
882 RequirementsListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
) + sizeof(IO_RESOURCE_DESCRIPTOR
) * (NumberOfResources
- 1);
883 RequirementsList
= (PIO_RESOURCE_REQUIREMENTS_LIST
)ExAllocatePool(PagedPool
, RequirementsListSize
);
885 if (!RequirementsList
)
887 ExFreePool(Buffer
.Pointer
);
888 return STATUS_SUCCESS
;
890 RequirementsList
->ListSize
= RequirementsListSize
;
891 RequirementsList
->InterfaceType
= Internal
;
892 RequirementsList
->BusNumber
= 0;
893 RequirementsList
->SlotNumber
= 0; /* Not used by WDM drivers */
894 RequirementsList
->AlternativeLists
= 1;
895 RequirementsList
->List
[0].Version
= 1;
896 RequirementsList
->List
[0].Revision
= 1;
897 RequirementsList
->List
[0].Count
= NumberOfResources
;
898 RequirementDescriptor
= RequirementsList
->List
[0].Descriptors
;
900 /* Fill resources list structure */
904 switch (resource
->Type
)
906 case ACPI_RESOURCE_TYPE_IRQ
:
908 ACPI_RESOURCE_IRQ
*irq_data
= (ACPI_RESOURCE_IRQ
*) &resource
->Data
;
909 for (i
= 0; i
< irq_data
->InterruptCount
; i
++)
911 RequirementDescriptor
->Option
= 0; /* Required */
912 RequirementDescriptor
->Type
= CmResourceTypeInterrupt
;
913 RequirementDescriptor
->ShareDisposition
= (irq_data
->Sharable
== ACPI_SHARED
? CmResourceShareShared
: CmResourceShareDeviceExclusive
);
914 RequirementDescriptor
->Flags
=(irq_data
->Triggering
== ACPI_LEVEL_SENSITIVE
? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
: CM_RESOURCE_INTERRUPT_LATCHED
);
915 RequirementDescriptor
->u
.Interrupt
.MinimumVector
= irq_data
->Interrupts
[i
];
917 RequirementDescriptor
++;
921 case ACPI_RESOURCE_TYPE_DMA
:
923 ACPI_RESOURCE_DMA
*dma_data
= (ACPI_RESOURCE_DMA
*) &resource
->Data
;
924 for (i
= 0; i
< dma_data
->ChannelCount
; i
++)
926 RequirementDescriptor
->Type
= CmResourceTypeDma
;
927 RequirementDescriptor
->Flags
= 0;
928 switch (dma_data
->Type
)
930 case ACPI_TYPE_A
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_A
; break;
931 case ACPI_TYPE_B
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_B
; break;
932 case ACPI_TYPE_F
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_TYPE_F
; break;
934 if (dma_data
->BusMaster
== ACPI_BUS_MASTER
)
935 RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_BUS_MASTER
;
936 switch (dma_data
->Transfer
)
938 case ACPI_TRANSFER_8
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_8
; break;
939 case ACPI_TRANSFER_16
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_16
; break;
940 case ACPI_TRANSFER_8_16
: RequirementDescriptor
->Flags
|= CM_RESOURCE_DMA_8_AND_16
; break;
943 RequirementDescriptor
->Option
= 0; /* Required */
944 RequirementDescriptor
->ShareDisposition
= CmResourceShareDriverExclusive
;
945 RequirementDescriptor
->u
.Dma
.MinimumChannel
= dma_data
->Channels
[i
];
946 RequirementDescriptor
++;
950 case ACPI_RESOURCE_TYPE_IO
:
952 ACPI_RESOURCE_IO
*io_data
= (ACPI_RESOURCE_IO
*) &resource
->Data
;
953 RequirementDescriptor
->Flags
= CM_RESOURCE_PORT_IO
;
954 if (io_data
->IoDecode
== ACPI_DECODE_16
)
955 RequirementDescriptor
->Flags
|= CM_RESOURCE_PORT_16_BIT_DECODE
;
957 RequirementDescriptor
->Flags
|= CM_RESOURCE_PORT_10_BIT_DECODE
;
959 RequirementDescriptor
->u
.Port
.Length
= io_data
->AddressLength
;
961 RequirementDescriptor
->Option
= 0; /* Required */
962 RequirementDescriptor
->Type
= CmResourceTypePort
;
963 RequirementDescriptor
->ShareDisposition
= CmResourceShareDriverExclusive
;
964 RequirementDescriptor
->u
.Port
.Alignment
= 1; /* Start address is specified, so it doesn't matter */
965 RequirementDescriptor
->u
.Port
.MinimumAddress
.QuadPart
= io_data
->Minimum
;
966 RequirementDescriptor
->u
.Port
.MaximumAddress
.QuadPart
= io_data
->Maximum
;
968 RequirementDescriptor
++;
971 case ACPI_RESOURCE_TYPE_END_TAG
:
978 DPRINT1("Unhandled resource type\n");
982 resource
= ACPI_NEXT_RESOURCE(resource
);
984 ExFreePool(Buffer
.Pointer
);
986 return STATUS_SUCCESS
;
990 Bus_PDO_QueryDeviceRelations(
991 PPDO_DEVICE_DATA DeviceData
,
997 The PnP Manager sends this IRP to gather information about
998 devices with a relationship to the specified device.
999 Bus drivers must handle this request for TargetDeviceRelation
1000 for their child devices (child PDOs).
1002 If a driver returns relations in response to this IRP,
1003 it allocates a DEVICE_RELATIONS structure from paged
1004 memory containing a count and the appropriate number of
1005 device object pointers. The PnP Manager frees the structure
1006 when it is no longer needed. If a driver replaces a
1007 DEVICE_RELATIONS structure allocated by another driver,
1008 it must free the previous structure.
1010 A driver must reference the PDO of any device that it
1011 reports in this IRP (ObReferenceObject). The PnP Manager
1012 removes the reference when appropriate.
1016 DeviceData - Pointer to the PDO's device extension.
1017 Irp - Pointer to the irp.
1026 PIO_STACK_LOCATION stack
;
1027 PDEVICE_RELATIONS deviceRelations
;
1032 stack
= IoGetCurrentIrpStackLocation (Irp
);
1034 switch (stack
->Parameters
.QueryDeviceRelations
.Type
) {
1036 case TargetDeviceRelation
:
1038 deviceRelations
= (PDEVICE_RELATIONS
) Irp
->IoStatus
.Information
;
1039 if (deviceRelations
) {
1041 // Only PDO can handle this request. Somebody above
1042 // is not playing by rule.
1044 ASSERTMSG("Someone above is handling TargetDeviceRelation", !deviceRelations
);
1047 deviceRelations
= (PDEVICE_RELATIONS
)
1048 ExAllocatePoolWithTag (PagedPool
,
1049 sizeof(DEVICE_RELATIONS
),
1051 if (!deviceRelations
) {
1052 status
= STATUS_INSUFFICIENT_RESOURCES
;
1057 // There is only one PDO pointer in the structure
1058 // for this relation type. The PnP Manager removes
1059 // the reference to the PDO when the driver or application
1060 // un-registers for notification on the device.
1063 deviceRelations
->Count
= 1;
1064 deviceRelations
->Objects
[0] = DeviceData
->Common
.Self
;
1065 ObReferenceObject(DeviceData
->Common
.Self
);
1067 status
= STATUS_SUCCESS
;
1068 Irp
->IoStatus
.Information
= (ULONG_PTR
) deviceRelations
;
1071 case BusRelations
: // Not handled by PDO
1072 case EjectionRelations
: // optional for PDO
1073 case RemovalRelations
: // // optional for PDO
1075 status
= Irp
->IoStatus
.Status
;
1082 Bus_PDO_QueryBusInformation(
1083 PPDO_DEVICE_DATA DeviceData
,
1087 Routine Description:
1089 The PnP Manager uses this IRP to request the type and
1090 instance number of a device's parent bus. Bus drivers
1091 should handle this request for their child devices (PDOs).
1095 DeviceData - Pointer to the PDO's device extension.
1096 Irp - Pointer to the irp.
1105 PPNP_BUS_INFORMATION busInfo
;
1109 busInfo
= ExAllocatePoolWithTag (PagedPool
, sizeof(PNP_BUS_INFORMATION
),
1112 if (busInfo
== NULL
) {
1113 return STATUS_INSUFFICIENT_RESOURCES
;
1116 busInfo
->BusTypeGuid
= GUID_ACPI_INTERFACE_STANDARD
;
1118 busInfo
->LegacyBusType
= InternalPowerBus
;
1120 busInfo
->BusNumber
= 0; //fixme
1122 Irp
->IoStatus
.Information
= (ULONG_PTR
)busInfo
;
1124 return STATUS_SUCCESS
;
1129 Bus_GetDeviceCapabilities(
1130 PDEVICE_OBJECT DeviceObject
,
1131 PDEVICE_CAPABILITIES DeviceCapabilities
1134 IO_STATUS_BLOCK ioStatus
;
1137 PDEVICE_OBJECT targetObject
;
1138 PIO_STACK_LOCATION irpStack
;
1144 // Initialize the capabilities that we will send down
1146 RtlZeroMemory( DeviceCapabilities
, sizeof(DEVICE_CAPABILITIES
) );
1147 DeviceCapabilities
->Size
= sizeof(DEVICE_CAPABILITIES
);
1148 DeviceCapabilities
->Version
= 1;
1149 DeviceCapabilities
->Address
= -1;
1150 DeviceCapabilities
->UINumber
= -1;
1153 // Initialize the event
1155 KeInitializeEvent( &pnpEvent
, NotificationEvent
, FALSE
);
1157 targetObject
= IoGetAttachedDeviceReference( DeviceObject
);
1162 pnpIrp
= IoBuildSynchronousFsdRequest(
1171 if (pnpIrp
== NULL
) {
1173 status
= STATUS_INSUFFICIENT_RESOURCES
;
1174 goto GetDeviceCapabilitiesExit
;
1179 // Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
1181 pnpIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
1184 // Get the top of stack
1186 irpStack
= IoGetNextIrpStackLocation( pnpIrp
);
1189 // Set the top of stack
1191 RtlZeroMemory( irpStack
, sizeof(IO_STACK_LOCATION
) );
1192 irpStack
->MajorFunction
= IRP_MJ_PNP
;
1193 irpStack
->MinorFunction
= IRP_MN_QUERY_CAPABILITIES
;
1194 irpStack
->Parameters
.DeviceCapabilities
.Capabilities
= DeviceCapabilities
;
1199 status
= IoCallDriver( targetObject
, pnpIrp
);
1200 if (status
== STATUS_PENDING
) {
1203 // Block until the irp comes back.
1204 // Important thing to note here is when you allocate
1205 // the memory for an event in the stack you must do a
1206 // KernelMode wait instead of UserMode to prevent
1207 // the stack from getting paged out.
1210 KeWaitForSingleObject(
1217 status
= ioStatus
.Status
;
1221 GetDeviceCapabilitiesExit
:
1223 // Done with reference
1225 ObDereferenceObject( targetObject
);