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 23 extern "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 45 extern dpc_module_info* gDPC; 46 void* gDPCHandle = NULL; 47 48 49 static bool 50 checkAndLogFailure(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 60 static ACPI_STATUS 61 get_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 94 static void 95 globalGPEHandler(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 154 static 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 175 static status_t 176 acpi_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 291 status_t 292 get_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 299 status_t 300 get_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 308 status_t 309 acquire_global_lock(uint16 timeout, uint32 *handle) 310 { 311 return AcpiAcquireGlobalLock(timeout, (UINT32*)handle) == AE_OK 312 ? B_OK : B_ERROR; 313 } 314 315 316 status_t 317 release_global_lock(uint32 handle) 318 { 319 return AcpiReleaseGlobalLock(handle) == AE_OK ? B_OK : B_ERROR; 320 } 321 322 323 status_t 324 install_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 332 status_t 333 remove_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 341 status_t 342 update_all_gpes() 343 { 344 return AcpiUpdateAllGpes() == AE_OK ? B_OK : B_ERROR; 345 } 346 347 348 status_t 349 enable_gpe(acpi_handle handle, uint32 gpeNumber) 350 { 351 return AcpiEnableGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR; 352 } 353 354 355 status_t 356 disable_gpe(acpi_handle handle, uint32 gpeNumber) 357 { 358 return AcpiDisableGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR; 359 } 360 361 362 status_t 363 clear_gpe(acpi_handle handle, uint32 gpeNumber) 364 { 365 return AcpiClearGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR; 366 } 367 368 369 status_t 370 set_gpe(acpi_handle handle, uint32 gpeNumber, uint8 action) 371 { 372 return AcpiSetGpe(handle, gpeNumber, action) == AE_OK ? B_OK : B_ERROR; 373 } 374 375 376 status_t 377 finish_gpe(acpi_handle handle, uint32 gpeNumber) 378 { 379 return AcpiFinishGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR; 380 } 381 382 383 status_t 384 install_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 392 status_t 393 remove_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 401 status_t 402 install_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 411 status_t 412 remove_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 420 void 421 enable_fixed_event(uint32 event) 422 { 423 AcpiEnableEvent(event, 0); 424 } 425 426 427 void 428 disable_fixed_event(uint32 event) 429 { 430 AcpiDisableEvent(event, 0); 431 } 432 433 434 uint32 435 fixed_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 443 void 444 reset_fixed_event(uint32 event) 445 { 446 AcpiClearEvent(event); 447 } 448 449 450 status_t 451 install_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 459 status_t 460 remove_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 467 status_t 468 get_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 503 status_t 504 get_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 513 status_t 514 get_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 532 status_t 533 get_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 571 status_t 572 get_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 595 uint32 596 get_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 609 status_t 610 get_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 630 status_t 631 get_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 652 status_t 653 ns_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 661 status_t 662 evaluate_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 680 status_t 681 evaluate_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 695 status_t 696 get_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 708 status_t 709 get_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 716 status_t 717 get_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 724 status_t 725 set_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 732 status_t 733 walk_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 741 status_t 742 walk_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 752 status_t 753 prepare_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 788 status_t 789 enter_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 810 status_t 811 reboot(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 832 status_t 833 get_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 840 status_t 841 read_bit_register(uint32 regid, uint32 *val) 842 { 843 return AcpiReadBitRegister(regid, (UINT32 *)val); 844 } 845 846 847 status_t 848 write_bit_register(uint32 regid, uint32 val) 849 { 850 return AcpiWriteBitRegister(regid, val); 851 } 852 853 854 struct 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