2 * Copyright 2009, Vincent Duvert, vincent.duvert@free.fr
3 * Copyright 2009, Clemens Zeidler, haiku@clemens-zeidler.de
4 * Copyright 2008-2015, Axel Dörfler, axeld@pinc-software.de.
5 * Copyright 2006, Bryan Varner. All rights reserved.
6 * Copyright 2005, Nathan Whitehorn. All rights reserved.
8 * Distributed under the terms of the MIT License.
19 #include <KernelExport.h>
30 #include "ACPIPrivate.h"
32 //#define TRACE_ACPI_BUS
34 #define TRACE(x...) dprintf("acpi: " x)
39 #define ERROR(x...) dprintf("acpi: " x)
44 #define ACPI_DEVICE_ID_LENGTH 0x08
46 extern pci_module_info
* gPCIManager
;
47 extern dpc_module_info
* gDPC
;
48 void* gDPCHandle
= NULL
;
52 checkAndLogFailure(const ACPI_STATUS status
, const char* msg
)
54 bool failure
= ACPI_FAILURE(status
);
56 dprintf("acpi: %s %s\n", msg
, AcpiFormatException(status
));
63 get_device_by_hid_callback(ACPI_HANDLE object
, UINT32 depth
, void* context
,
66 uint32
* counter
= (uint32
*)context
;
69 TRACE("get_device_by_hid_callback %p, %d, %p\n", object
, depth
, context
);
73 if (counter
[0] == counter
[1]) {
75 buffer
.Pointer
= malloc(255);
77 if (checkAndLogFailure(AcpiGetName(object
, ACPI_FULL_PATHNAME
, &buffer
),
78 "Failed to find device")) {
80 return AE_CTRL_TERMINATE
;
83 ((char*)buffer
.Pointer
)[buffer
.Length
] = '\0';
84 *_returnValue
= buffer
.Pointer
;
85 return AE_CTRL_TERMINATE
;
93 #ifdef ACPI_DEBUG_OUTPUT
97 globalGPEHandler(UINT32 eventType
, ACPI_HANDLE device
, UINT32 eventNumber
,
101 char deviceName
[256];
102 path
.Length
= sizeof(deviceName
);
103 path
.Pointer
= deviceName
;
105 ACPI_STATUS status
= AcpiNsHandleToPathname(device
, &path
);
106 if (ACPI_FAILURE(status
))
107 strcpy(deviceName
, "(missing)");
110 case ACPI_EVENT_TYPE_GPE
:
111 dprintf("acpi: GPE Event %d for %s\n", eventNumber
, deviceName
);
114 case ACPI_EVENT_TYPE_FIXED
:
116 switch (eventNumber
) {
117 case ACPI_EVENT_PMTIMER
:
118 dprintf("acpi: PMTIMER(%d) event for %s\n", eventNumber
,
122 case ACPI_EVENT_GLOBAL
:
123 dprintf("acpi: Global(%d) event for %s\n", eventNumber
,
127 case ACPI_EVENT_POWER_BUTTON
:
128 dprintf("acpi: Powerbutton(%d) event for %s\n", eventNumber
,
132 case ACPI_EVENT_SLEEP_BUTTON
:
133 dprintf("acpi: sleepbutton(%d) event for %s\n", eventNumber
,
138 dprintf("acpi: RTC(%d) event for %s\n", eventNumber
,
143 dprintf("acpi: unknown fixed(%d) event for %s\n",
144 eventNumber
, deviceName
);
150 dprintf("acpi: unknown event type (%d:%d) event for %s\n",
151 eventType
, eventNumber
, deviceName
);
156 static void globalNotifyHandler(ACPI_HANDLE device
, UINT32 value
, void* context
)
159 char deviceName
[256];
160 path
.Length
= sizeof(deviceName
);
161 path
.Pointer
= deviceName
;
163 ACPI_STATUS status
= AcpiNsHandleToPathname(device
, &path
);
164 if (ACPI_FAILURE(status
))
165 strcpy(deviceName
, "(missing)");
167 dprintf("acpi: Notify event %d for %s\n", value
, deviceName
);
174 // #pragma mark - ACPI bus manager API
178 acpi_std_ops(int32 op
,...)
184 ACPI_OBJECT_LIST parameter
;
186 bool acpiDisabled
= false;
187 AcpiGbl_CopyDsdtLocally
= true;
189 settings
= load_driver_settings("kernel");
190 if (settings
!= NULL
) {
191 acpiDisabled
= !get_driver_boolean_parameter(settings
, "acpi",
193 unload_driver_settings(settings
);
197 // check if safemode settings disable ACPI
198 settings
= load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS
);
199 if (settings
!= NULL
) {
200 acpiDisabled
= get_driver_boolean_parameter(settings
,
201 B_SAFEMODE_DISABLE_ACPI
, false, false);
202 unload_driver_settings(settings
);
207 ERROR("ACPI disabled\n");
211 if (gDPC
->new_dpc_queue(&gDPCHandle
, "acpi_task",
212 B_URGENT_DISPLAY_PRIORITY
+ 1) != B_OK
) {
213 ERROR("failed to create os execution queue\n");
217 #ifdef ACPI_DEBUG_OUTPUT
218 AcpiDbgLevel
= ACPI_DEBUG_ALL
| ACPI_LV_VERBOSE
;
219 AcpiDbgLayer
= ACPI_ALL_COMPONENTS
;
222 if (checkAndLogFailure(AcpiInitializeSubsystem(),
223 "AcpiInitializeSubsystem failed"))
226 if (checkAndLogFailure(AcpiInitializeTables(NULL
, 0, TRUE
),
227 "AcpiInitializeTables failed"))
230 if (checkAndLogFailure(AcpiLoadTables(),
231 "AcpiLoadTables failed"))
234 /* Install the default address space handlers. */
235 if (checkAndLogFailure(AcpiInstallAddressSpaceHandler(
236 ACPI_ROOT_OBJECT
, ACPI_ADR_SPACE_SYSTEM_MEMORY
,
237 ACPI_DEFAULT_HANDLER
, NULL
, NULL
),
238 "Could not initialise SystemMemory handler:"))
241 if (checkAndLogFailure(AcpiInstallAddressSpaceHandler(
242 ACPI_ROOT_OBJECT
, ACPI_ADR_SPACE_SYSTEM_IO
,
243 ACPI_DEFAULT_HANDLER
, NULL
, NULL
),
244 "Could not initialise SystemIO handler:"))
247 if (checkAndLogFailure(AcpiInstallAddressSpaceHandler(
248 ACPI_ROOT_OBJECT
, ACPI_ADR_SPACE_PCI_CONFIG
,
249 ACPI_DEFAULT_HANDLER
, NULL
, NULL
),
250 "Could not initialise PciConfig handler:"))
253 arg
.Integer
.Type
= ACPI_TYPE_INTEGER
;
254 arg
.Integer
.Value
= apic_available() ? APIC_MODE
: PIC_MODE
;
257 parameter
.Pointer
= &arg
;
259 AcpiEvaluateObject(NULL
, "\\_PIC", ¶meter
, NULL
);
261 if (checkAndLogFailure(AcpiEnableSubsystem(
262 ACPI_FULL_INITIALIZATION
),
263 "AcpiEnableSubsystem failed"))
266 if (checkAndLogFailure(AcpiInitializeObjects(
267 ACPI_FULL_INITIALIZATION
),
268 "AcpiInitializeObjects failed"))
271 //TODO: Walk namespace init ALL _PRW's
273 #ifdef ACPI_DEBUG_OUTPUT
275 AcpiInstallGlobalEventHandler(globalGPEHandler
, NULL
),
276 "Failed to install global GPE-handler.");
278 checkAndLogFailure(AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT
,
279 ACPI_ALL_NOTIFY
, globalNotifyHandler
, NULL
),
280 "Failed to install global Notify-handler.");
282 checkAndLogFailure(AcpiEnableAllRuntimeGpes(),
283 "Failed to enable all runtime Gpes");
285 checkAndLogFailure(AcpiUpdateAllGpes(),
286 "Failed to update all Gpes");
288 TRACE("ACPI initialized\n");
295 case B_MODULE_UNINIT
:
297 if (checkAndLogFailure(AcpiTerminate(),
298 "Could not bring system out of ACPI mode. Oh well."));
300 gDPC
->delete_dpc_queue(gDPCHandle
);
313 get_handle(acpi_handle parent
, const char *pathname
, acpi_handle
*retHandle
)
315 return AcpiGetHandle(parent
, (ACPI_STRING
)pathname
, retHandle
) == AE_OK
321 get_name(acpi_handle handle
, uint32 nameType
, char* returnedName
,
324 ACPI_BUFFER buffer
= {bufferLength
, (void*)returnedName
};
325 return AcpiGetName(handle
, nameType
, &buffer
) == AE_OK
? B_OK
: B_ERROR
;
330 acquire_global_lock(uint16 timeout
, uint32
*handle
)
332 return AcpiAcquireGlobalLock(timeout
, (UINT32
*)handle
) == AE_OK
338 release_global_lock(uint32 handle
)
340 return AcpiReleaseGlobalLock(handle
) == AE_OK
? B_OK
: B_ERROR
;
345 install_notify_handler(acpi_handle device
, uint32 handlerType
,
346 acpi_notify_handler handler
, void *context
)
348 return AcpiInstallNotifyHandler(device
, handlerType
,
349 (ACPI_NOTIFY_HANDLER
)handler
, context
) == AE_OK
? B_OK
: B_ERROR
;
354 remove_notify_handler(acpi_handle device
, uint32 handlerType
,
355 acpi_notify_handler handler
)
357 return AcpiRemoveNotifyHandler(device
, handlerType
,
358 (ACPI_NOTIFY_HANDLER
)handler
) == AE_OK
? B_OK
: B_ERROR
;
365 return AcpiUpdateAllGpes() == AE_OK
? B_OK
: B_ERROR
;
370 enable_gpe(acpi_handle handle
, uint32 gpeNumber
)
372 return AcpiEnableGpe(handle
, gpeNumber
) == AE_OK
? B_OK
: B_ERROR
;
377 disable_gpe(acpi_handle handle
, uint32 gpeNumber
)
379 return AcpiDisableGpe(handle
, gpeNumber
) == AE_OK
? B_OK
: B_ERROR
;
384 clear_gpe(acpi_handle handle
, uint32 gpeNumber
)
386 return AcpiClearGpe(handle
, gpeNumber
) == AE_OK
? B_OK
: B_ERROR
;
391 set_gpe(acpi_handle handle
, uint32 gpeNumber
, uint8 action
)
393 return AcpiSetGpe(handle
, gpeNumber
, action
) == AE_OK
? B_OK
: B_ERROR
;
398 finish_gpe(acpi_handle handle
, uint32 gpeNumber
)
400 return AcpiFinishGpe(handle
, gpeNumber
) == AE_OK
? B_OK
: B_ERROR
;
405 install_gpe_handler(acpi_handle handle
, uint32 gpeNumber
, uint32 type
,
406 acpi_gpe_handler handler
, void *data
)
408 return AcpiInstallGpeHandler(handle
, gpeNumber
, type
,
409 (ACPI_GPE_HANDLER
)handler
, data
) == AE_OK
? B_OK
: B_ERROR
;
414 remove_gpe_handler(acpi_handle handle
, uint32 gpeNumber
,
415 acpi_gpe_handler address
)
417 return AcpiRemoveGpeHandler(handle
, gpeNumber
, (ACPI_GPE_HANDLER
)address
)
418 == AE_OK
? B_OK
: B_ERROR
;
423 install_address_space_handler(acpi_handle handle
, uint32 spaceId
,
424 acpi_adr_space_handler handler
, acpi_adr_space_setup setup
, void *data
)
426 return AcpiInstallAddressSpaceHandler(handle
, spaceId
,
427 (ACPI_ADR_SPACE_HANDLER
)handler
, (ACPI_ADR_SPACE_SETUP
)setup
, data
)
428 == AE_OK
? B_OK
: B_ERROR
;
433 remove_address_space_handler(acpi_handle handle
, uint32 spaceId
,
434 acpi_adr_space_handler handler
)
436 return AcpiRemoveAddressSpaceHandler(handle
, spaceId
,
437 (ACPI_ADR_SPACE_HANDLER
)handler
) == AE_OK
? B_OK
: B_ERROR
;
442 enable_fixed_event(uint32 event
)
444 AcpiEnableEvent(event
, 0);
449 disable_fixed_event(uint32 event
)
451 AcpiDisableEvent(event
, 0);
456 fixed_event_status(uint32 event
)
458 ACPI_EVENT_STATUS status
= 0;
459 AcpiGetEventStatus(event
, &status
);
460 return status
/* & ACPI_EVENT_FLAG_SET*/;
465 reset_fixed_event(uint32 event
)
467 AcpiClearEvent(event
);
472 install_fixed_event_handler(uint32 event
, acpi_event_handler handler
,
475 return AcpiInstallFixedEventHandler(event
, (ACPI_EVENT_HANDLER
)handler
, data
) == AE_OK
481 remove_fixed_event_handler(uint32 event
, acpi_event_handler handler
)
483 return AcpiRemoveFixedEventHandler(event
, (ACPI_EVENT_HANDLER
)handler
) == AE_OK
489 get_next_entry(uint32 objectType
, const char *base
, char *result
,
490 size_t length
, void **counter
)
492 ACPI_HANDLE parent
, child
, newChild
;
496 TRACE("get_next_entry %ld, %s\n", objectType
, base
);
498 if (base
== NULL
|| !strcmp(base
, "\\")) {
499 parent
= ACPI_ROOT_OBJECT
;
501 status
= AcpiGetHandle(NULL
, (ACPI_STRING
)base
, &parent
);
503 return B_ENTRY_NOT_FOUND
;
508 status
= AcpiGetNextObject(objectType
, parent
, child
, &newChild
);
510 return B_ENTRY_NOT_FOUND
;
513 buffer
.Length
= length
;
514 buffer
.Pointer
= result
;
516 status
= AcpiGetName(newChild
, ACPI_FULL_PATHNAME
, &buffer
);
518 return B_NO_MEMORY
; /* Corresponds to AE_BUFFER_OVERFLOW */
525 get_next_object(uint32 objectType
, acpi_handle parent
,
526 acpi_handle
* currentChild
)
528 acpi_handle child
= *currentChild
;
529 return AcpiGetNextObject(objectType
, parent
, child
, currentChild
) == AE_OK
535 get_device(const char* hid
, uint32 index
, char* result
, size_t resultLength
)
538 uint32 counter
[2] = {index
, 0};
541 TRACE("get_device %s, index %ld\n", hid
, index
);
542 status
= AcpiGetDevices((ACPI_STRING
)hid
, (ACPI_WALK_CALLBACK
)&get_device_by_hid_callback
,
543 counter
, (void**)&buffer
);
544 if (status
!= AE_OK
|| buffer
== NULL
)
545 return B_ENTRY_NOT_FOUND
;
547 strlcpy(result
, buffer
, resultLength
);
554 get_device_hid(const char *path
, char *hid
, size_t bufferLength
)
557 ACPI_DEVICE_INFO
*info
;
559 TRACE("get_device_hid: path %s, hid %s\n", path
, hid
);
560 if (AcpiGetHandle(NULL
, (ACPI_STRING
)path
, &handle
) != AE_OK
)
561 return B_ENTRY_NOT_FOUND
;
563 if (bufferLength
< ACPI_DEVICE_ID_LENGTH
)
564 return B_BUFFER_OVERFLOW
;
566 if (AcpiGetObjectInfo(handle
, &info
) != AE_OK
)
569 if ((info
->Valid
& ACPI_VALID_HID
) != 0)
570 strlcpy(hid
, info
->HardwareId
.String
, bufferLength
);
579 get_object_type(const char* path
)
582 ACPI_OBJECT_TYPE type
;
584 if (AcpiGetHandle(NULL
, (ACPI_STRING
)path
, &handle
) != AE_OK
)
585 return B_ENTRY_NOT_FOUND
;
587 AcpiGetType(handle
, &type
);
593 get_object(const char* path
, acpi_object_type
** _returnValue
)
599 status
= AcpiGetHandle(NULL
, (ACPI_STRING
)path
, &handle
);
601 return B_ENTRY_NOT_FOUND
;
603 buffer
.Pointer
= NULL
;
604 buffer
.Length
= ACPI_ALLOCATE_BUFFER
;
606 status
= AcpiEvaluateObject(handle
, NULL
, NULL
, &buffer
);
608 *_returnValue
= (acpi_object_type
*)buffer
.Pointer
;
609 return status
== AE_OK
? B_OK
: B_ERROR
;
614 get_object_typed(const char* path
, acpi_object_type
** _returnValue
,
621 status
= AcpiGetHandle(NULL
, (ACPI_STRING
)path
, &handle
);
623 return B_ENTRY_NOT_FOUND
;
625 buffer
.Pointer
= NULL
;
626 buffer
.Length
= ACPI_ALLOCATE_BUFFER
;
628 status
= AcpiEvaluateObjectTyped(handle
, NULL
, NULL
, &buffer
, objectType
);
630 *_returnValue
= (acpi_object_type
*)buffer
.Pointer
;
631 return status
== AE_OK
? B_OK
: B_ERROR
;
636 ns_handle_to_pathname(acpi_handle targetHandle
, acpi_data
*buffer
)
638 status_t status
= AcpiNsHandleToPathname(targetHandle
,
639 (ACPI_BUFFER
*)buffer
);
640 return status
== AE_OK
? B_OK
: B_ERROR
;
645 evaluate_object(acpi_handle handle
, const char* object
, acpi_objects
*args
,
646 acpi_object_type
* returnValue
, size_t bufferLength
)
651 buffer
.Pointer
= returnValue
;
652 buffer
.Length
= bufferLength
;
654 status
= AcpiEvaluateObject(handle
, (ACPI_STRING
)object
,
655 (ACPI_OBJECT_LIST
*)args
, returnValue
!= NULL
? &buffer
: NULL
);
656 if (status
== AE_BUFFER_OVERFLOW
)
657 dprintf("evaluate_object: the passed buffer is too small!\n");
659 return status
== AE_OK
? B_OK
: B_ERROR
;
664 evaluate_method(acpi_handle handle
, const char* method
,
665 acpi_objects
*args
, acpi_data
*returnValue
)
669 status
= AcpiEvaluateObject(handle
, (ACPI_STRING
)method
,
670 (ACPI_OBJECT_LIST
*)args
, (ACPI_BUFFER
*)returnValue
);
671 if (status
== AE_BUFFER_OVERFLOW
)
672 dprintf("evaluate_method: the passed buffer is too small!\n");
674 return status
== AE_OK
? B_OK
: B_ERROR
;
679 get_irq_routing_table(acpi_handle busDeviceHandle
, acpi_data
*retBuffer
)
683 status
= AcpiGetIrqRoutingTable(busDeviceHandle
, (ACPI_BUFFER
*)retBuffer
);
684 if (status
== AE_BUFFER_OVERFLOW
)
685 dprintf("evaluate_method: the passed buffer is too small!\n");
687 return status
== AE_OK
? B_OK
: B_ERROR
;
692 get_current_resources(acpi_handle busDeviceHandle
, acpi_data
*retBuffer
)
694 return AcpiGetCurrentResources(busDeviceHandle
, (ACPI_BUFFER
*)retBuffer
)
695 == AE_OK
? B_OK
: B_ERROR
;
700 get_possible_resources(acpi_handle busDeviceHandle
, acpi_data
*retBuffer
)
702 return AcpiGetPossibleResources(busDeviceHandle
, (ACPI_BUFFER
*)retBuffer
)
703 == AE_OK
? B_OK
: B_ERROR
;
708 set_current_resources(acpi_handle busDeviceHandle
, acpi_data
*buffer
)
710 return AcpiSetCurrentResources(busDeviceHandle
, (ACPI_BUFFER
*)buffer
)
711 == AE_OK
? B_OK
: B_ERROR
;
716 walk_resources(acpi_handle busDeviceHandle
, char* method
,
717 acpi_walk_resources_callback callback
, void* context
)
719 return AcpiWalkResources(busDeviceHandle
, method
,
720 (ACPI_WALK_RESOURCE_CALLBACK
)callback
, context
);
725 prepare_sleep_state(uint8 state
, void (*wakeFunc
)(void), size_t size
)
727 ACPI_STATUS acpiStatus
;
729 TRACE("prepare_sleep_state %d, %p, %ld\n", state
, wakeFunc
, size
);
731 if (state
!= ACPI_POWER_STATE_OFF
) {
732 physical_entry wakeVector
;
735 // Note: The supplied code must already be locked into memory.
736 status
= get_memory_map((const void*)wakeFunc
, size
, &wakeVector
, 1);
740 #if ACPI_MACHINE_WIDTH == 32
741 # if B_HAIKU_PHYSICAL_BITS > 32
742 if (wakeVector
.address
>= 0x100000000LL
) {
743 ERROR("prepare_sleep_state(): ACPI_MACHINE_WIDTH == 32, but we "
744 "have a physical address >= 4 GB\n");
747 acpiStatus
= AcpiSetFirmwareWakingVector(wakeVector
.address
);
749 acpiStatus
= AcpiSetFirmwareWakingVector64(wakeVector
.address
);
751 if (acpiStatus
!= AE_OK
)
755 acpiStatus
= AcpiEnterSleepStatePrep(state
);
756 if (acpiStatus
!= AE_OK
)
764 enter_sleep_state(uint8 state
)
768 TRACE("enter_sleep_state %d\n", state
);
770 cpu_status cpu
= disable_interrupts();
771 status
= AcpiEnterSleepState(state
);
772 restore_interrupts(cpu
);
773 panic("AcpiEnterSleepState should not return.");
777 /*status = AcpiLeaveSleepState(state);
792 status
= AcpiReset();
793 if (status
== AE_NOT_EXIST
)
794 return B_UNSUPPORTED
;
796 if (status
!= AE_OK
) {
797 ERROR("Reset failed, status = %d\n", status
);
802 ERROR("Reset failed, timeout\n");
808 get_table(const char* signature
, uint32 instance
, void** tableHeader
)
810 return AcpiGetTable((char*)signature
, instance
,
811 (ACPI_TABLE_HEADER
**)tableHeader
) == AE_OK
? B_OK
: B_ERROR
;
816 read_bit_register(uint32 regid
, uint32
*val
)
818 return AcpiReadBitRegister(regid
, (UINT32
*)val
);
823 write_bit_register(uint32 regid
, uint32 val
)
825 return AcpiWriteBitRegister(regid
, val
);
829 struct acpi_module_info gACPIModule
= {
840 install_notify_handler
,
841 remove_notify_handler
,
850 install_address_space_handler
,
851 remove_address_space_handler
,
856 install_fixed_event_handler
,
857 remove_fixed_event_handler
,
865 ns_handle_to_pathname
,
868 get_irq_routing_table
,
869 get_current_resources
,
870 get_possible_resources
,
871 set_current_resources
,