3 * PROJECT: ReactOS ACPI bus driver
4 * FILE: acpi/ospm/fdo.c
5 * PURPOSE: ACPI device object dispatch routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * 08-08-2001 CSH Created
17 FADT_DESCRIPTOR_REV2 acpi_fadt
;
19 /*** PRIVATE *****************************************************************/
23 AcpiCreateUnicodeString(
24 PUNICODE_STRING Destination
,
32 RtlInitUnicodeString(Destination
, NULL
);
36 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
38 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
39 if (Destination
->Buffer
== NULL
)
44 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
46 Destination
->MaximumLength
= Length
;
48 Destination
->Length
= Length
- sizeof(WCHAR
);
54 AcpiCreateDeviceIDString(PUNICODE_STRING DeviceID
,
63 if (!AcpiCreateUnicodeString(DeviceID
, Buffer
, PagedPool
))
73 AcpiCreateHardwareIDsString(PUNICODE_STRING HardwareIDs
,
81 Index
+= swprintf(&Buffer
[Index
],
86 Index
+= swprintf(&Buffer
[Index
],
90 Buffer
[Index
] = UNICODE_NULL
;
92 Length
= (Index
+ 1) * sizeof(WCHAR
);
93 HardwareIDs
->Buffer
= ExAllocatePool(PagedPool
, Length
);
94 if (HardwareIDs
->Buffer
== NULL
)
99 HardwareIDs
->Length
= Length
- sizeof(WCHAR
);
100 HardwareIDs
->MaximumLength
= Length
;
101 RtlCopyMemory(HardwareIDs
->Buffer
, Buffer
, Length
);
108 AcpiCreateInstanceIDString(PUNICODE_STRING InstanceID
,
111 /* FIXME: Create unique instnce id. */
112 return AcpiCreateUnicodeString(InstanceID
, L
"0000", PagedPool
);
117 FdoQueryBusRelations(
118 IN PDEVICE_OBJECT DeviceObject
,
120 PIO_STACK_LOCATION IrpSp
)
122 PPDO_DEVICE_EXTENSION PdoDeviceExtension
;
123 PFDO_DEVICE_EXTENSION DeviceExtension
;
124 PDEVICE_RELATIONS Relations
;
125 PLIST_ENTRY CurrentEntry
;
126 ANSI_STRING AnsiString
;
127 ACPI_STATUS AcpiStatus
;
136 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
138 Size
= sizeof(DEVICE_RELATIONS
) + sizeof(Relations
->Objects
) *
139 (DeviceExtension
->DeviceListCount
- 1);
140 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, Size
);
142 return STATUS_INSUFFICIENT_RESOURCES
;
144 Relations
->Count
= DeviceExtension
->DeviceListCount
;
147 CurrentEntry
= DeviceExtension
->DeviceListHead
.Flink
;
148 while (CurrentEntry
!= &DeviceExtension
->DeviceListHead
)
150 Device
= CONTAINING_RECORD(CurrentEntry
, ACPI_DEVICE
, DeviceListEntry
);
152 /* FIXME: For ACPI namespace devices on the motherboard create filter DOs
153 and attach them just above the ACPI bus device object (PDO) */
155 /* FIXME: For other devices in ACPI namespace, but not on motherboard,
160 /* Create a physical device object for the
161 device as it does not already have one */
162 Status
= IoCreateDevice(DeviceObject
->DriverObject
,
163 sizeof(PDO_DEVICE_EXTENSION
),
165 FILE_DEVICE_CONTROLLER
,
166 FILE_AUTOGENERATED_DEVICE_NAME
,
169 if (!NT_SUCCESS(Status
))
171 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status
);
172 /* FIXME: Cleanup all new PDOs created in this call */
173 ExFreePool(Relations
);
177 PdoDeviceExtension
= (PPDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
179 RtlZeroMemory(PdoDeviceExtension
, sizeof(PDO_DEVICE_EXTENSION
));
181 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
183 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
185 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
187 PdoDeviceExtension
->Common
.DeviceObject
= Device
->Pdo
;
189 PdoDeviceExtension
->Common
.DevicePowerState
= PowerDeviceD0
;
191 // PdoDeviceExtension->Common.Ldo = IoAttachDeviceToDeviceStack(DeviceObject,
194 RtlInitUnicodeString(&PdoDeviceExtension
->DeviceID
, NULL
);
195 RtlInitUnicodeString(&PdoDeviceExtension
->InstanceID
, NULL
);
196 RtlInitUnicodeString(&PdoDeviceExtension
->HardwareIDs
, NULL
);
198 AcpiStatus
= bm_get_node(Device
->BmHandle
, 0, &Node
);
199 if (ACPI_SUCCESS(AcpiStatus
))
201 /* Add Device ID string */
202 if (!AcpiCreateDeviceIDString(&PdoDeviceExtension
->DeviceID
,
206 // ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
207 // ErrorOccurred = TRUE;
211 if (!AcpiCreateInstanceIDString(&PdoDeviceExtension
->InstanceID
,
215 // ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
216 // ErrorOccurred = TRUE;
220 if (!AcpiCreateHardwareIDsString(&PdoDeviceExtension
->HardwareIDs
,
224 // ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
225 // ErrorOccurred = TRUE;
231 /* Reference the physical device object. The PnP manager
232 will dereference it again when it is no longer needed */
233 ObReferenceObject(Device
->Pdo
);
235 Relations
->Objects
[i
] = Device
->Pdo
;
239 CurrentEntry
= CurrentEntry
->Flink
;
242 Irp
->IoStatus
.Information
= (ULONG
)Relations
;
250 PFDO_DEVICE_EXTENSION DeviceExtension
)
252 DbgPrint("ACPI: System firmware supports:\n");
255 * Print out basic system information
257 DbgPrint("+------------------------------------------------------------\n");
258 DbgPrint("| Sx states: %cS0 %cS1 %cS2 %cS3 %cS4 %cS5\n",
259 (DeviceExtension
->SystemStates
[0]?'+':'-'),
260 (DeviceExtension
->SystemStates
[1]?'+':'-'),
261 (DeviceExtension
->SystemStates
[2]?'+':'-'),
262 (DeviceExtension
->SystemStates
[3]?'+':'-'),
263 (DeviceExtension
->SystemStates
[4]?'+':'-'),
264 (DeviceExtension
->SystemStates
[5]?'+':'-'));
265 DbgPrint("+------------------------------------------------------------\n");
270 ACPIInitializeInternalDriver(
271 PFDO_DEVICE_EXTENSION DeviceExtension
,
272 ACPI_DRIVER_FUNCTION Initialize
,
273 ACPI_DRIVER_FUNCTION Terminate
)
275 ACPI_STATUS AcpiStatus
;
277 AcpiStatus
= Initialize();
278 if (!ACPI_SUCCESS(AcpiStatus
)) {
279 DPRINT("BN init status 0x%X\n", AcpiStatus
);
280 return STATUS_UNSUCCESSFUL
;
283 AcpiDevice
= (PACPI_DEVICE
)ExAllocatePool(
284 NonPagedPool
, sizeof(ACPI_DEVICE
));
286 return STATUS_INSUFFICIENT_RESOURCES
;
289 AcpiDevice
->Initialize
= Initialize
;
290 AcpiDevice
->Terminate
= Terminate
;
292 /* FIXME: Create PDO */
294 AcpiDevice
->Pdo
= NULL
;
295 //AcpiDevice->BmHandle = HandleList.handles[i];
297 ExInterlockedInsertHeadList(&DeviceExtension
->DeviceListHead
,
298 &AcpiDevice
->ListEntry
, &DeviceExtension
->DeviceListLock
);
300 return STATUS_SUCCESS
;
305 ACPIInitializeInternalDrivers(
306 PFDO_DEVICE_EXTENSION DeviceExtension
)
310 Status
= ACPIInitializeInternalDriver(DeviceExtension
,
311 bn_initialize
, bn_terminate
);
313 return STATUS_SUCCESS
;
319 IN PDEVICE_OBJECT DeviceObject
,
322 PFDO_DEVICE_EXTENSION DeviceExtension
;
323 ACPI_PHYSICAL_ADDRESS rsdp
;
324 ACPI_SYSTEM_INFO SysInfo
;
325 ACPI_STATUS AcpiStatus
;
332 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
334 ASSERT(DeviceExtension
->State
== dsStopped
);
336 AcpiStatus
= acpi_initialize_subsystem();
337 if (!ACPI_SUCCESS(AcpiStatus
)) {
338 DPRINT("acpi_initialize_subsystem() failed with status 0x%X\n", AcpiStatus
);
339 return STATUS_UNSUCCESSFUL
;
342 AcpiStatus
= acpi_find_root_pointer(&rsdp
);
343 if (!ACPI_SUCCESS(AcpiStatus
)) {
344 DPRINT("acpi_find_root_pointer() failed with status 0x%X\n", AcpiStatus
);
345 return STATUS_UNSUCCESSFUL
;
348 /* From this point on, on error we must call acpi_terminate() */
350 AcpiStatus
= acpi_load_tables(rsdp
);
351 if (!ACPI_SUCCESS(AcpiStatus
)) {
352 DPRINT("acpi_load_tables() failed with status 0x%X\n", AcpiStatus
);
354 return STATUS_UNSUCCESSFUL
;
357 Buffer
.length
= sizeof(SysInfo
);
358 Buffer
.pointer
= &SysInfo
;
360 AcpiStatus
= acpi_get_system_info(&Buffer
);
361 if (!ACPI_SUCCESS(AcpiStatus
)) {
362 DPRINT("acpi_get_system_info() failed with status 0x%X\n", AcpiStatus
);
364 return STATUS_UNSUCCESSFUL
;
367 DPRINT("ACPI CA Core Subsystem version 0x%X\n", SysInfo
.acpi_ca_version
);
369 ASSERT(SysInfo
.num_table_types
> ACPI_TABLE_FADT
);
371 RtlMoveMemory(&acpi_fadt
,
372 &SysInfo
.table_info
[ACPI_TABLE_FADT
],
373 sizeof(FADT_DESCRIPTOR_REV2
));
375 AcpiStatus
= acpi_enable_subsystem(ACPI_FULL_INITIALIZATION
);
376 if (!ACPI_SUCCESS(AcpiStatus
)) {
377 DPRINT("acpi_enable_subsystem() failed with status 0x%X\n", AcpiStatus
);
379 return STATUS_UNSUCCESSFUL
;
382 DPRINT("ACPI CA Core Subsystem enabled\n");
387 * Figure out which Sx states are supported
389 for (i
=0; i
<=ACPI_S_STATES_MAX
; i
++) {
390 AcpiStatus
= acpi_hw_obtain_sleep_type_register_data(
394 DPRINT("acpi_hw_obtain_sleep_type_register_data (%d) status 0x%X\n",
396 if (ACPI_SUCCESS(AcpiStatus
)) {
397 DeviceExtension
->SystemStates
[i
] = TRUE
;
401 ACPIPrintInfo(DeviceExtension
);
403 /* Initialize ACPI bus manager */
404 AcpiStatus
= bm_initialize();
405 if (!ACPI_SUCCESS(AcpiStatus
)) {
406 DPRINT("bm_initialize() failed with status 0x%X\n", AcpiStatus
);
408 return STATUS_UNSUCCESSFUL
;
411 InitializeListHead(&DeviceExtension
->DeviceListHead
);
412 KeInitializeSpinLock(&DeviceExtension
->DeviceListLock
);
413 DeviceExtension
->DeviceListCount
= 0;
415 ACPIEnumerateDevices(DeviceExtension
);
417 ACPIInitializeInternalDrivers(DeviceExtension
);
419 DeviceExtension
->State
= dsStarted
;
421 return STATUS_SUCCESS
;
427 IN PDEVICE_OBJECT DeviceObject
,
429 PIO_STACK_LOCATION IrpSp
)
431 PFDO_DEVICE_EXTENSION DeviceExtension
;
432 ACPI_STATUS AcpiStatus
;
438 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
440 if (IrpSp
->Parameters
.Power
.Type
== SystemPowerState
) {
441 Status
= STATUS_SUCCESS
;
442 switch (IrpSp
->Parameters
.Power
.State
.SystemState
) {
443 case PowerSystemSleeping1
:
444 AcpiState
= ACPI_STATE_S1
;
446 case PowerSystemSleeping2
:
447 AcpiState
= ACPI_STATE_S2
;
449 case PowerSystemSleeping3
:
450 AcpiState
= ACPI_STATE_S3
;
452 case PowerSystemHibernate
:
453 AcpiState
= ACPI_STATE_S4
;
455 case PowerSystemShutdown
:
456 AcpiState
= ACPI_STATE_S5
;
459 Status
= STATUS_UNSUCCESSFUL
;
461 if (!DeviceExtension
->SystemStates
[AcpiState
]) {
462 DPRINT("System sleep state S%d is not supported by hardware\n", AcpiState
);
463 Status
= STATUS_UNSUCCESSFUL
;
466 if (NT_SUCCESS(Status
)) {
467 DPRINT("Trying to enter sleep state %d\n", AcpiState
);
469 AcpiStatus
= acpi_enter_sleep_state(AcpiState
);
470 if (!ACPI_SUCCESS(AcpiStatus
)) {
471 DPRINT("Failed to enter sleep state %d (Status 0x%X)\n",
472 AcpiState
, AcpiStatus
);
473 Status
= STATUS_UNSUCCESSFUL
;
477 Status
= STATUS_UNSUCCESSFUL
;
484 /*** PUBLIC ******************************************************************/
489 PDEVICE_OBJECT DeviceObject
,
492 * FUNCTION: Handle Plug and Play IRPs for the ACPI device
494 * DeviceObject = Pointer to functional device object of the ACPI driver
495 * Irp = Pointer to IRP that should be handled
500 PIO_STACK_LOCATION IrpSp
;
505 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
506 switch (IrpSp
->MinorFunction
) {
507 case IRP_MN_CANCEL_REMOVE_DEVICE
:
508 Status
= STATUS_NOT_IMPLEMENTED
;
511 case IRP_MN_CANCEL_STOP_DEVICE
:
512 Status
= STATUS_NOT_IMPLEMENTED
;
515 case IRP_MN_DEVICE_USAGE_NOTIFICATION
:
516 Status
= STATUS_NOT_IMPLEMENTED
;
519 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
520 Status
= STATUS_NOT_IMPLEMENTED
;
523 case IRP_MN_QUERY_DEVICE_RELATIONS
:
524 Status
= FdoQueryBusRelations(DeviceObject
, Irp
, IrpSp
);
527 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
528 Status
= STATUS_NOT_IMPLEMENTED
;
531 case IRP_MN_QUERY_REMOVE_DEVICE
:
532 Status
= STATUS_NOT_IMPLEMENTED
;
535 case IRP_MN_QUERY_STOP_DEVICE
:
536 Status
= STATUS_NOT_IMPLEMENTED
;
539 case IRP_MN_REMOVE_DEVICE
:
540 Status
= STATUS_NOT_IMPLEMENTED
;
543 case IRP_MN_START_DEVICE
:
544 DPRINT("IRP_MN_START_DEVICE received\n");
545 Status
= FdoStartDevice(DeviceObject
, Irp
);
548 case IRP_MN_STOP_DEVICE
:
549 /* Currently not supported */
551 Status
= STATUS_UNSUCCESSFUL
;
554 case IRP_MN_SURPRISE_REMOVAL
:
555 Status
= STATUS_NOT_IMPLEMENTED
;
559 DPRINT("Unknown IOCTL 0x%X\n", IrpSp
->MinorFunction
);
560 Status
= STATUS_NOT_IMPLEMENTED
;
564 if (Status
!= STATUS_PENDING
) {
565 Irp
->IoStatus
.Status
= Status
;
566 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
569 DPRINT("Leaving. Status 0x%X\n", Status
);
578 PDEVICE_OBJECT DeviceObject
,
581 * FUNCTION: Handle power management IRPs for the ACPI device
583 * DeviceObject = Pointer to functional device object of the ACPI driver
584 * Irp = Pointer to IRP that should be handled
589 PIO_STACK_LOCATION IrpSp
;
594 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
596 switch (IrpSp
->MinorFunction
) {
597 case IRP_MN_SET_POWER
:
598 Status
= FdoSetPower(DeviceObject
, Irp
, IrpSp
);
602 DPRINT("Unknown IOCTL 0x%X\n", IrpSp
->MinorFunction
);
603 Status
= STATUS_NOT_IMPLEMENTED
;
607 if (Status
!= STATUS_PENDING
) {
608 Irp
->IoStatus
.Status
= Status
;
609 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
612 DPRINT("Leaving. Status 0x%X\n", Status
);