1/* 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. 7 * 8 * Distributed under the terms of the MIT License. 9 */ 10 11 12#include <stdio.h> 13#include <stdlib.h> 14#include <string.h> 15 16#include <ACPI.h> 17#include <dpc.h> 18#include <KernelExport.h> 19#include <PCI.h> 20 21#include <safemode.h> 22 23extern "C" { 24#include "acpi.h" 25#include "accommon.h" 26#include "acdisasm.h" 27#include "acnamesp.h" 28} 29#include "ACPIPrivate.h" 30 31#include "arch_init.h" 32 33 34//#define TRACE_ACPI_BUS 35#ifdef TRACE_ACPI_BUS 36#define TRACE(x...) dprintf("acpi: " x) 37#else 38#define TRACE(x...) 39#endif 40 41#define ERROR(x...) dprintf("acpi: " x) 42 43#define ACPI_DEVICE_ID_LENGTH 0x08 44 45extern dpc_module_info* gDPC; 46void* gDPCHandle = NULL; 47 48 49static bool 50checkAndLogFailure(const ACPI_STATUS status, const char* msg) 51{ 52 bool failure = ACPI_FAILURE(status); 53 if (failure) 54 dprintf("acpi: %s %s\n", msg, AcpiFormatException(status)); 55 56 return failure; 57} 58 59 60static ACPI_STATUS 61get_device_by_hid_callback(ACPI_HANDLE object, UINT32 depth, void* context, 62 void** _returnValue) 63{ 64 uint32* counter = (uint32*)context; 65 ACPI_BUFFER buffer; 66 67 TRACE("get_device_by_hid_callback %p, %d, %p\n", object, depth, context); 68 69 *_returnValue = NULL; 70 71 if (counter[0] == counter[1]) { 72 buffer.Length = 254; 73 buffer.Pointer = malloc(255); 74 75 if (checkAndLogFailure(AcpiGetName(object, ACPI_FULL_PATHNAME, &buffer), 76 "Failed to find device")) { 77 free(buffer.Pointer); 78 return AE_CTRL_TERMINATE; 79 } 80 81 ((char*)buffer.Pointer)[buffer.Length] = '\0'; 82 *_returnValue = buffer.Pointer; 83 return AE_CTRL_TERMINATE; 84 } 85 86 counter[1]++; 87 return AE_OK; 88} 89 90 91#ifdef ACPI_DEBUG_OUTPUT 92 93 94static void 95globalGPEHandler(UINT32 eventType, ACPI_HANDLE device, UINT32 eventNumber, 96 void* context) 97{ 98 ACPI_BUFFER path; 99 char deviceName[256]; 100 path.Length = sizeof(deviceName); 101 path.Pointer = deviceName; 102 103 ACPI_STATUS status = AcpiNsHandleToPathname(device, &path); 104 if (ACPI_FAILURE(status)) 105 strcpy(deviceName, "(missing)"); 106 107 switch (eventType) { 108 case ACPI_EVENT_TYPE_GPE: 109 dprintf("acpi: GPE Event %d for %s\n", eventNumber, deviceName); 110 break; 111 112 case ACPI_EVENT_TYPE_FIXED: 113 { 114 switch (eventNumber) { 115 case ACPI_EVENT_PMTIMER: 116 dprintf("acpi: PMTIMER(%d) event for %s\n", eventNumber, 117 deviceName); 118 break; 119 120 case ACPI_EVENT_GLOBAL: 121 dprintf("acpi: Global(%d) event for %s\n", eventNumber, 122 deviceName); 123 break; 124 125 case ACPI_EVENT_POWER_BUTTON: 126 dprintf("acpi: Powerbutton(%d) event for %s\n", eventNumber, 127 deviceName); 128 break; 129 130 case ACPI_EVENT_SLEEP_BUTTON: 131 dprintf("acpi: sleepbutton(%d) event for %s\n", eventNumber, 132 deviceName); 133 break; 134 135 case ACPI_EVENT_RTC: 136 dprintf("acpi: RTC(%d) event for %s\n", eventNumber, 137 deviceName); 138 break; 139 140 default: 141 dprintf("acpi: unknown fixed(%d) event for %s\n", 142 eventNumber, deviceName); 143 } 144 break; 145 } 146 147 default: 148 dprintf("acpi: unknown event type (%d:%d) event for %s\n", 149 eventType, eventNumber, deviceName); 150 } 151} 152 153 154static void globalNotifyHandler(ACPI_HANDLE device, UINT32 value, void* context) 155{ 156 ACPI_BUFFER path; 157 char deviceName[256]; 158 path.Length = sizeof(deviceName); 159 path.Pointer = deviceName; 160 161 ACPI_STATUS status = AcpiNsHandleToPathname(device, &path); 162 if (ACPI_FAILURE(status)) 163 strcpy(deviceName, "(missing)"); 164 165 dprintf("acpi: Notify event %d for %s\n", value, deviceName); 166} 167 168 169#endif 170 171 172// #pragma mark - ACPI bus manager API 173 174 175static status_t 176acpi_std_ops(int32 op,...) 177{ 178 switch (op) { 179 case B_MODULE_INIT: 180 { 181 void *settings; 182 bool acpiDisabled = false; 183 AcpiGbl_CopyDsdtLocally = true; 184 185 settings = load_driver_settings("kernel"); 186 if (settings != NULL) { 187 acpiDisabled = !get_driver_boolean_parameter(settings, "acpi", 188 true, true); 189 unload_driver_settings(settings); 190 } 191 192 if (!acpiDisabled) { 193 // check if safemode settings disable ACPI 194 settings = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS); 195 if (settings != NULL) { 196 acpiDisabled = get_driver_boolean_parameter(settings, 197 B_SAFEMODE_DISABLE_ACPI, false, false); 198 unload_driver_settings(settings); 199 } 200 } 201 202 if (acpiDisabled) { 203 ERROR("ACPI disabled\n"); 204 return ENOSYS; 205 } 206 207 if (gDPC->new_dpc_queue(&gDPCHandle, "acpi_task", 208 B_URGENT_DISPLAY_PRIORITY + 1) != B_OK) { 209 ERROR("failed to create os execution queue\n"); 210 return B_ERROR; 211 } 212 213#ifdef ACPI_DEBUG_OUTPUT 214 AcpiDbgLevel = ACPI_DEBUG_ALL | ACPI_LV_VERBOSE; 215 AcpiDbgLayer = ACPI_ALL_COMPONENTS; 216#endif 217 218 if (checkAndLogFailure(AcpiInitializeSubsystem(), 219 "AcpiInitializeSubsystem failed")) 220 goto err_dpc; 221 222 if (checkAndLogFailure(AcpiInitializeTables(NULL, 0, TRUE), 223 "AcpiInitializeTables failed")) 224 goto err_acpi; 225 226 if (checkAndLogFailure(AcpiLoadTables(), 227 "AcpiLoadTables failed")) 228 goto err_acpi; 229 230 /* Install the default address space handlers. */ 231 232 arch_init_interrupt_controller(); 233 234 if (checkAndLogFailure(AcpiEnableSubsystem( 235 ACPI_FULL_INITIALIZATION), 236 "AcpiEnableSubsystem failed")) 237 goto err_acpi; 238 239 if (checkAndLogFailure(AcpiInitializeObjects( 240 ACPI_FULL_INITIALIZATION), 241 "AcpiInitializeObjects failed")) 242 goto err_acpi; 243 244 //TODO: Walk namespace init ALL _PRW's 245 246#ifdef ACPI_DEBUG_OUTPUT 247 checkAndLogFailure( 248 AcpiInstallGlobalEventHandler(globalGPEHandler, NULL), 249 "Failed to install global GPE-handler."); 250 251 checkAndLogFailure(AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, 252 ACPI_ALL_NOTIFY, globalNotifyHandler, NULL), 253 "Failed to install global Notify-handler."); 254#endif 255 checkAndLogFailure(AcpiEnableAllRuntimeGpes(), 256 "Failed to enable all runtime Gpes"); 257 258 checkAndLogFailure(AcpiUpdateAllGpes(), 259 "Failed to update all Gpes"); 260 261 TRACE("ACPI initialized\n"); 262 return B_OK; 263 264 err_acpi: 265 checkAndLogFailure(AcpiTerminate(), "AcpiTerminate failed"); 266 267 err_dpc: 268 gDPC->delete_dpc_queue(gDPCHandle); 269 gDPCHandle = NULL; 270 271 return B_ERROR; 272 } 273 274 case B_MODULE_UNINIT: 275 { 276 checkAndLogFailure(AcpiTerminate(), 277 "Could not bring system out of ACPI mode. Oh well."); 278 279 gDPC->delete_dpc_queue(gDPCHandle); 280 gDPCHandle = NULL; 281 break; 282 } 283 284 default: 285 return B_ERROR; 286 } 287 return B_OK; 288} 289 290 291status_t 292get_handle(acpi_handle parent, const char *pathname, acpi_handle *retHandle) 293{ 294 return AcpiGetHandle(parent, (ACPI_STRING)pathname, retHandle) == AE_OK 295 ? B_OK : B_ERROR; 296} 297 298 299status_t 300get_name(acpi_handle handle, uint32 nameType, char* returnedName, 301 size_t bufferLength) 302{ 303 ACPI_BUFFER buffer = {bufferLength, (void*)returnedName}; 304 return AcpiGetName(handle, nameType, &buffer) == AE_OK ? B_OK : B_ERROR; 305} 306 307 308status_t 309acquire_global_lock(uint16 timeout, uint32 *handle) 310{ 311 return AcpiAcquireGlobalLock(timeout, (UINT32*)handle) == AE_OK 312 ? B_OK : B_ERROR; 313} 314 315 316status_t 317release_global_lock(uint32 handle) 318{ 319 return AcpiReleaseGlobalLock(handle) == AE_OK ? B_OK : B_ERROR; 320} 321 322 323status_t 324install_notify_handler(acpi_handle device, uint32 handlerType, 325 acpi_notify_handler handler, void *context) 326{ 327 return AcpiInstallNotifyHandler(device, handlerType, 328 (ACPI_NOTIFY_HANDLER)handler, context) == AE_OK ? B_OK : B_ERROR; 329} 330 331 332status_t 333remove_notify_handler(acpi_handle device, uint32 handlerType, 334 acpi_notify_handler handler) 335{ 336 return AcpiRemoveNotifyHandler(device, handlerType, 337 (ACPI_NOTIFY_HANDLER)handler) == AE_OK ? B_OK : B_ERROR; 338} 339 340 341status_t 342update_all_gpes() 343{ 344 return AcpiUpdateAllGpes() == AE_OK ? B_OK : B_ERROR; 345} 346 347 348status_t 349enable_gpe(acpi_handle handle, uint32 gpeNumber) 350{ 351 return AcpiEnableGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR; 352} 353 354 355status_t 356disable_gpe(acpi_handle handle, uint32 gpeNumber) 357{ 358 return AcpiDisableGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR; 359} 360 361 362status_t 363clear_gpe(acpi_handle handle, uint32 gpeNumber) 364{ 365 return AcpiClearGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR; 366} 367 368 369status_t 370set_gpe(acpi_handle handle, uint32 gpeNumber, uint8 action) 371{ 372 return AcpiSetGpe(handle, gpeNumber, action) == AE_OK ? B_OK : B_ERROR; 373} 374 375 376status_t 377finish_gpe(acpi_handle handle, uint32 gpeNumber) 378{ 379 return AcpiFinishGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR; 380} 381 382 383status_t 384install_gpe_handler(acpi_handle handle, uint32 gpeNumber, uint32 type, 385 acpi_gpe_handler handler, void *data) 386{ 387 return AcpiInstallGpeHandler(handle, gpeNumber, type, 388 (ACPI_GPE_HANDLER)handler, data) == AE_OK ? B_OK : B_ERROR; 389} 390 391 392status_t 393remove_gpe_handler(acpi_handle handle, uint32 gpeNumber, 394 acpi_gpe_handler address) 395{ 396 return AcpiRemoveGpeHandler(handle, gpeNumber, (ACPI_GPE_HANDLER)address) 397 == AE_OK ? B_OK : B_ERROR; 398} 399 400 401status_t 402install_address_space_handler(acpi_handle handle, uint32 spaceId, 403 acpi_adr_space_handler handler, acpi_adr_space_setup setup, void *data) 404{ 405 return AcpiInstallAddressSpaceHandler(handle, spaceId, 406 (ACPI_ADR_SPACE_HANDLER)handler, (ACPI_ADR_SPACE_SETUP)setup, data) 407 == AE_OK ? B_OK : B_ERROR; 408} 409 410 411status_t 412remove_address_space_handler(acpi_handle handle, uint32 spaceId, 413 acpi_adr_space_handler handler) 414{ 415 return AcpiRemoveAddressSpaceHandler(handle, spaceId, 416 (ACPI_ADR_SPACE_HANDLER)handler) == AE_OK ? B_OK : B_ERROR; 417} 418 419 420void 421enable_fixed_event(uint32 event) 422{ 423 AcpiEnableEvent(event, 0); 424} 425 426 427void 428disable_fixed_event(uint32 event) 429{ 430 AcpiDisableEvent(event, 0); 431} 432 433 434uint32 435fixed_event_status(uint32 event) 436{ 437 ACPI_EVENT_STATUS status = 0; 438 AcpiGetEventStatus(event, &status); 439 return status/* & ACPI_EVENT_FLAG_SET*/; 440} 441 442 443void 444reset_fixed_event(uint32 event) 445{ 446 AcpiClearEvent(event); 447} 448 449 450status_t 451install_fixed_event_handler(uint32 event, acpi_event_handler handler, 452 void *data) 453{ 454 return AcpiInstallFixedEventHandler(event, (ACPI_EVENT_HANDLER)handler, data) == AE_OK 455 ? B_OK : B_ERROR; 456} 457 458 459status_t 460remove_fixed_event_handler(uint32 event, acpi_event_handler handler) 461{ 462 return AcpiRemoveFixedEventHandler(event, (ACPI_EVENT_HANDLER)handler) == AE_OK 463 ? B_OK : B_ERROR; 464} 465 466 467status_t 468get_next_entry(uint32 objectType, const char *base, char *result, 469 size_t length, void **counter) 470{ 471 ACPI_HANDLE parent, child, newChild; 472 ACPI_BUFFER buffer; 473 ACPI_STATUS status; 474 475 TRACE("get_next_entry %ld, %s\n", objectType, base); 476 477 if (base == NULL || !strcmp(base, "\\")) { 478 parent = ACPI_ROOT_OBJECT; 479 } else { 480 status = AcpiGetHandle(NULL, (ACPI_STRING)base, &parent); 481 if (status != AE_OK) 482 return B_ENTRY_NOT_FOUND; 483 } 484 485 child = *counter; 486 487 status = AcpiGetNextObject(objectType, parent, child, &newChild); 488 if (status != AE_OK) 489 return B_ENTRY_NOT_FOUND; 490 491 *counter = newChild; 492 buffer.Length = length; 493 buffer.Pointer = result; 494 495 status = AcpiGetName(newChild, ACPI_FULL_PATHNAME, &buffer); 496 if (status != AE_OK) 497 return B_NO_MEMORY; /* Corresponds to AE_BUFFER_OVERFLOW */ 498 499 return B_OK; 500} 501 502 503status_t 504get_next_object(uint32 objectType, acpi_handle parent, 505 acpi_handle* currentChild) 506{ 507 acpi_handle child = *currentChild; 508 return AcpiGetNextObject(objectType, parent, child, currentChild) == AE_OK 509 ? B_OK : B_ERROR; 510} 511 512 513status_t 514get_device(const char* hid, uint32 index, char* result, size_t resultLength) 515{ 516 ACPI_STATUS status; 517 uint32 counter[2] = {index, 0}; 518 char *buffer = NULL; 519 520 TRACE("get_device %s, index %ld\n", hid, index); 521 status = AcpiGetDevices((ACPI_STRING)hid, (ACPI_WALK_CALLBACK)&get_device_by_hid_callback, 522 counter, (void**)&buffer); 523 if (status != AE_OK || buffer == NULL) 524 return B_ENTRY_NOT_FOUND; 525 526 strlcpy(result, buffer, resultLength); 527 free(buffer); 528 return B_OK; 529} 530 531 532status_t 533get_device_info(const char *path, char** hid, char** cidList, 534 size_t cidListCount, char** uid, char** cls) 535{ 536 ACPI_HANDLE handle; 537 ACPI_DEVICE_INFO *info; 538 539 TRACE("get_device_info: path %s\n", path); 540 if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK) 541 return B_ENTRY_NOT_FOUND; 542 543 if (AcpiGetObjectInfo(handle, &info) != AE_OK) 544 return B_BAD_TYPE; 545 546 if ((info->Valid & ACPI_VALID_HID) != 0 && hid != NULL) 547 *hid = strndup(info->HardwareId.String, info->HardwareId.Length); 548 549 if ((info->Valid & ACPI_VALID_CID) != 0 && cidList != NULL) { 550 if (cidListCount > info->CompatibleIdList.Count) 551 cidListCount = info->CompatibleIdList.Count; 552 for (size_t i = 0; i < cidListCount; i++) { 553 cidList[i] = strndup(info->CompatibleIdList.Ids[i].String, 554 info->CompatibleIdList.Ids[i].Length); 555 } 556 } 557 558 if ((info->Valid & ACPI_VALID_UID) != 0 && uid != NULL) 559 *uid = strndup(info->UniqueId.String, info->UniqueId.Length); 560 561 if ((info->Valid & ACPI_VALID_CLS) != 0 && cls != NULL 562 && info->ClassCode.Length >= ACPI_PCICLS_STRING_SIZE) { 563 *cls = strndup(info->ClassCode.String, info->ClassCode.Length); 564 } 565 566 AcpiOsFree(info); 567 return B_OK; 568} 569 570 571status_t 572get_device_addr(const char *path, uint32 *addr) 573{ 574 ACPI_HANDLE handle; 575 576 TRACE("get_device_adr: path %s, hid %s\n", path, hid); 577 if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK) 578 return B_ENTRY_NOT_FOUND; 579 580 status_t status = B_BAD_VALUE; 581 acpi_data buf; 582 acpi_object_type object; 583 buf.pointer = &object; 584 buf.length = sizeof(acpi_object_type); 585 if (addr != NULL 586 && evaluate_method(handle, "_ADR", NULL, &buf) == B_OK 587 && object.object_type == ACPI_TYPE_INTEGER) { 588 status = B_OK; 589 *addr = object.integer.integer; 590 } 591 return status; 592} 593 594 595uint32 596get_object_type(const char* path) 597{ 598 ACPI_HANDLE handle; 599 ACPI_OBJECT_TYPE type; 600 601 if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK) 602 return B_ENTRY_NOT_FOUND; 603 604 AcpiGetType(handle, &type); 605 return type; 606} 607 608 609status_t 610get_object(const char* path, acpi_object_type** _returnValue) 611{ 612 ACPI_HANDLE handle; 613 ACPI_BUFFER buffer; 614 ACPI_STATUS status; 615 616 status = AcpiGetHandle(NULL, (ACPI_STRING)path, &handle); 617 if (status != AE_OK) 618 return B_ENTRY_NOT_FOUND; 619 620 buffer.Pointer = NULL; 621 buffer.Length = ACPI_ALLOCATE_BUFFER; 622 623 status = AcpiEvaluateObject(handle, NULL, NULL, &buffer); 624 625 *_returnValue = (acpi_object_type*)buffer.Pointer; 626 return status == AE_OK ? B_OK : B_ERROR; 627} 628 629 630status_t 631get_object_typed(const char* path, acpi_object_type** _returnValue, 632 uint32 objectType) 633{ 634 ACPI_HANDLE handle; 635 ACPI_BUFFER buffer; 636 ACPI_STATUS status; 637 638 status = AcpiGetHandle(NULL, (ACPI_STRING)path, &handle); 639 if (status != AE_OK) 640 return B_ENTRY_NOT_FOUND; 641 642 buffer.Pointer = NULL; 643 buffer.Length = ACPI_ALLOCATE_BUFFER; 644 645 status = AcpiEvaluateObjectTyped(handle, NULL, NULL, &buffer, objectType); 646 647 *_returnValue = (acpi_object_type*)buffer.Pointer; 648 return status == AE_OK ? B_OK : B_ERROR; 649} 650 651 652status_t 653ns_handle_to_pathname(acpi_handle targetHandle, acpi_data *buffer) 654{ 655 status_t status = AcpiNsHandleToPathname(targetHandle, 656 (ACPI_BUFFER*)buffer, false); 657 return status == AE_OK ? B_OK : B_ERROR; 658} 659 660 661status_t 662evaluate_object(acpi_handle handle, const char* object, acpi_objects *args, 663 acpi_object_type* returnValue, size_t bufferLength) 664{ 665 ACPI_BUFFER buffer; 666 ACPI_STATUS status; 667 668 buffer.Pointer = returnValue; 669 buffer.Length = bufferLength; 670 671 status = AcpiEvaluateObject(handle, (ACPI_STRING)object, 672 (ACPI_OBJECT_LIST*)args, returnValue != NULL ? &buffer : NULL); 673 if (status == AE_BUFFER_OVERFLOW) 674 dprintf("evaluate_object: the passed buffer is too small!\n"); 675 676 return status == AE_OK ? B_OK : B_ERROR; 677} 678 679 680status_t 681evaluate_method(acpi_handle handle, const char* method, 682 acpi_objects *args, acpi_data *returnValue) 683{ 684 ACPI_STATUS status; 685 686 status = AcpiEvaluateObject(handle, (ACPI_STRING)method, 687 (ACPI_OBJECT_LIST*)args, (ACPI_BUFFER*)returnValue); 688 if (status == AE_BUFFER_OVERFLOW) 689 dprintf("evaluate_method: the passed buffer is too small!\n"); 690 691 return status == AE_OK ? B_OK : B_ERROR; 692} 693 694 695status_t 696get_irq_routing_table(acpi_handle busDeviceHandle, acpi_data *retBuffer) 697{ 698 ACPI_STATUS status; 699 700 status = AcpiGetIrqRoutingTable(busDeviceHandle, (ACPI_BUFFER*)retBuffer); 701 if (status == AE_BUFFER_OVERFLOW) 702 dprintf("get_irq_routing_table: the passed buffer is too small!\n"); 703 704 return status == AE_OK ? B_OK : B_ERROR; 705} 706 707 708status_t 709get_current_resources(acpi_handle busDeviceHandle, acpi_data *retBuffer) 710{ 711 return AcpiGetCurrentResources(busDeviceHandle, (ACPI_BUFFER*)retBuffer) 712 == AE_OK ? B_OK : B_ERROR; 713} 714 715 716status_t 717get_possible_resources(acpi_handle busDeviceHandle, acpi_data *retBuffer) 718{ 719 return AcpiGetPossibleResources(busDeviceHandle, (ACPI_BUFFER*)retBuffer) 720 == AE_OK ? B_OK : B_ERROR; 721} 722 723 724status_t 725set_current_resources(acpi_handle busDeviceHandle, acpi_data *buffer) 726{ 727 return AcpiSetCurrentResources(busDeviceHandle, (ACPI_BUFFER*)buffer) 728 == AE_OK ? B_OK : B_ERROR; 729} 730 731 732status_t 733walk_resources(acpi_handle busDeviceHandle, char* method, 734 acpi_walk_resources_callback callback, void* context) 735{ 736 return AcpiWalkResources(busDeviceHandle, method, 737 (ACPI_WALK_RESOURCE_CALLBACK)callback, context); 738} 739 740 741status_t 742walk_namespace(acpi_handle busDeviceHandle, uint32 objectType, 743 uint32 maxDepth, acpi_walk_callback descendingCallback, 744 acpi_walk_callback ascendingCallback, void* context, void** returnValue) 745{ 746 return AcpiWalkNamespace(objectType, busDeviceHandle, maxDepth, 747 (ACPI_WALK_CALLBACK)descendingCallback, 748 (ACPI_WALK_CALLBACK)ascendingCallback, context, returnValue); 749} 750 751 752status_t 753prepare_sleep_state(uint8 state, void (*wakeFunc)(void), size_t size) 754{ 755 ACPI_STATUS acpiStatus; 756 757 TRACE("prepare_sleep_state %d, %p, %ld\n", state, wakeFunc, size); 758 759 if (state != ACPI_POWER_STATE_OFF) { 760 physical_entry wakeVector; 761 status_t status; 762 763 // Note: The supplied code must already be locked into memory. 764 status = get_memory_map((const void*)wakeFunc, size, &wakeVector, 1); 765 if (status != B_OK) 766 return status; 767 768# if B_HAIKU_PHYSICAL_BITS > 32 769 if (wakeVector.address >= 0x100000000LL) { 770 ERROR("prepare_sleep_state(): ACPI 2.0c says use 32 bit " 771 "vector, but we have a physical address >= 4 GB\n"); 772 } 773# endif 774 acpiStatus = AcpiSetFirmwareWakingVector(wakeVector.address, 775 wakeVector.address); 776 if (acpiStatus != AE_OK) 777 return B_ERROR; 778 } 779 780 acpiStatus = AcpiEnterSleepStatePrep(state); 781 if (acpiStatus != AE_OK) 782 return B_ERROR; 783 784 return B_OK; 785} 786 787 788status_t 789enter_sleep_state(uint8 state) 790{ 791 ACPI_STATUS status; 792 793 TRACE("enter_sleep_state %d\n", state); 794 795 cpu_status cpu = disable_interrupts(); 796 status = AcpiEnterSleepState(state); 797 restore_interrupts(cpu); 798 panic("AcpiEnterSleepState should not return."); 799 if (status != AE_OK) 800 return B_ERROR; 801 802 /*status = AcpiLeaveSleepState(state); 803 if (status != AE_OK) 804 return B_ERROR;*/ 805 806 return B_OK; 807} 808 809 810status_t 811reboot(void) 812{ 813 ACPI_STATUS status; 814 815 TRACE("reboot\n"); 816 817 status = AcpiReset(); 818 if (status == AE_NOT_EXIST) 819 return B_UNSUPPORTED; 820 821 if (status != AE_OK) { 822 ERROR("Reset failed, status = %d\n", status); 823 return B_ERROR; 824 } 825 826 snooze(1000000); 827 ERROR("Reset failed, timeout\n"); 828 return B_ERROR; 829} 830 831 832status_t 833get_table(const char* signature, uint32 instance, void** tableHeader) 834{ 835 return AcpiGetTable((char*)signature, instance, 836 (ACPI_TABLE_HEADER**)tableHeader) == AE_OK ? B_OK : B_ERROR; 837} 838 839 840status_t 841read_bit_register(uint32 regid, uint32 *val) 842{ 843 return AcpiReadBitRegister(regid, (UINT32 *)val); 844} 845 846 847status_t 848write_bit_register(uint32 regid, uint32 val) 849{ 850 return AcpiWriteBitRegister(regid, val); 851} 852 853 854struct acpi_module_info gACPIModule = { 855 { 856 B_ACPI_MODULE_NAME, 857 B_KEEP_LOADED, 858 acpi_std_ops 859 }, 860 861 get_handle, 862 get_name, 863 acquire_global_lock, 864 release_global_lock, 865 install_notify_handler, 866 remove_notify_handler, 867 update_all_gpes, 868 enable_gpe, 869 disable_gpe, 870 clear_gpe, 871 set_gpe, 872 finish_gpe, 873 install_gpe_handler, 874 remove_gpe_handler, 875 install_address_space_handler, 876 remove_address_space_handler, 877 enable_fixed_event, 878 disable_fixed_event, 879 fixed_event_status, 880 reset_fixed_event, 881 install_fixed_event_handler, 882 remove_fixed_event_handler, 883 get_next_entry, 884 get_next_object, 885 walk_namespace, 886 get_device, 887 get_device_info, 888 get_object_type, 889 get_object, 890 get_object_typed, 891 ns_handle_to_pathname, 892 evaluate_object, 893 evaluate_method, 894 get_irq_routing_table, 895 get_current_resources, 896 get_possible_resources, 897 set_current_resources, 898 walk_resources, 899 prepare_sleep_state, 900 enter_sleep_state, 901 reboot, 902 get_table, 903 read_bit_register, 904 write_bit_register 905}; 906