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; 221 222 if (checkAndLogFailure(AcpiInitializeTables(NULL, 0, TRUE), 223 "AcpiInitializeTables failed")) 224 goto err; 225 226 if (checkAndLogFailure(AcpiLoadTables(), 227 "AcpiLoadTables failed")) 228 goto err; 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; 238 239 if (checkAndLogFailure(AcpiInitializeObjects( 240 ACPI_FULL_INITIALIZATION), 241 "AcpiInitializeObjects failed")) 242 goto err; 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: 265 return B_ERROR; 266 } 267 268 case B_MODULE_UNINIT: 269 { 270 checkAndLogFailure(AcpiTerminate(), 271 "Could not bring system out of ACPI mode. Oh well."); 272 273 gDPC->delete_dpc_queue(gDPCHandle); 274 gDPCHandle = NULL; 275 break; 276 } 277 278 default: 279 return B_ERROR; 280 } 281 return B_OK; 282 } 283 284 285 status_t 286 get_handle(acpi_handle parent, const char *pathname, acpi_handle *retHandle) 287 { 288 return AcpiGetHandle(parent, (ACPI_STRING)pathname, retHandle) == AE_OK 289 ? B_OK : B_ERROR; 290 } 291 292 293 status_t 294 get_name(acpi_handle handle, uint32 nameType, char* returnedName, 295 size_t bufferLength) 296 { 297 ACPI_BUFFER buffer = {bufferLength, (void*)returnedName}; 298 return AcpiGetName(handle, nameType, &buffer) == AE_OK ? B_OK : B_ERROR; 299 } 300 301 302 status_t 303 acquire_global_lock(uint16 timeout, uint32 *handle) 304 { 305 return AcpiAcquireGlobalLock(timeout, (UINT32*)handle) == AE_OK 306 ? B_OK : B_ERROR; 307 } 308 309 310 status_t 311 release_global_lock(uint32 handle) 312 { 313 return AcpiReleaseGlobalLock(handle) == AE_OK ? B_OK : B_ERROR; 314 } 315 316 317 status_t 318 install_notify_handler(acpi_handle device, uint32 handlerType, 319 acpi_notify_handler handler, void *context) 320 { 321 return AcpiInstallNotifyHandler(device, handlerType, 322 (ACPI_NOTIFY_HANDLER)handler, context) == AE_OK ? B_OK : B_ERROR; 323 } 324 325 326 status_t 327 remove_notify_handler(acpi_handle device, uint32 handlerType, 328 acpi_notify_handler handler) 329 { 330 return AcpiRemoveNotifyHandler(device, handlerType, 331 (ACPI_NOTIFY_HANDLER)handler) == AE_OK ? B_OK : B_ERROR; 332 } 333 334 335 status_t 336 update_all_gpes() 337 { 338 return AcpiUpdateAllGpes() == AE_OK ? B_OK : B_ERROR; 339 } 340 341 342 status_t 343 enable_gpe(acpi_handle handle, uint32 gpeNumber) 344 { 345 return AcpiEnableGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR; 346 } 347 348 349 status_t 350 disable_gpe(acpi_handle handle, uint32 gpeNumber) 351 { 352 return AcpiDisableGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR; 353 } 354 355 356 status_t 357 clear_gpe(acpi_handle handle, uint32 gpeNumber) 358 { 359 return AcpiClearGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR; 360 } 361 362 363 status_t 364 set_gpe(acpi_handle handle, uint32 gpeNumber, uint8 action) 365 { 366 return AcpiSetGpe(handle, gpeNumber, action) == AE_OK ? B_OK : B_ERROR; 367 } 368 369 370 status_t 371 finish_gpe(acpi_handle handle, uint32 gpeNumber) 372 { 373 return AcpiFinishGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR; 374 } 375 376 377 status_t 378 install_gpe_handler(acpi_handle handle, uint32 gpeNumber, uint32 type, 379 acpi_gpe_handler handler, void *data) 380 { 381 return AcpiInstallGpeHandler(handle, gpeNumber, type, 382 (ACPI_GPE_HANDLER)handler, data) == AE_OK ? B_OK : B_ERROR; 383 } 384 385 386 status_t 387 remove_gpe_handler(acpi_handle handle, uint32 gpeNumber, 388 acpi_gpe_handler address) 389 { 390 return AcpiRemoveGpeHandler(handle, gpeNumber, (ACPI_GPE_HANDLER)address) 391 == AE_OK ? B_OK : B_ERROR; 392 } 393 394 395 status_t 396 install_address_space_handler(acpi_handle handle, uint32 spaceId, 397 acpi_adr_space_handler handler, acpi_adr_space_setup setup, void *data) 398 { 399 return AcpiInstallAddressSpaceHandler(handle, spaceId, 400 (ACPI_ADR_SPACE_HANDLER)handler, (ACPI_ADR_SPACE_SETUP)setup, data) 401 == AE_OK ? B_OK : B_ERROR; 402 } 403 404 405 status_t 406 remove_address_space_handler(acpi_handle handle, uint32 spaceId, 407 acpi_adr_space_handler handler) 408 { 409 return AcpiRemoveAddressSpaceHandler(handle, spaceId, 410 (ACPI_ADR_SPACE_HANDLER)handler) == AE_OK ? B_OK : B_ERROR; 411 } 412 413 414 void 415 enable_fixed_event(uint32 event) 416 { 417 AcpiEnableEvent(event, 0); 418 } 419 420 421 void 422 disable_fixed_event(uint32 event) 423 { 424 AcpiDisableEvent(event, 0); 425 } 426 427 428 uint32 429 fixed_event_status(uint32 event) 430 { 431 ACPI_EVENT_STATUS status = 0; 432 AcpiGetEventStatus(event, &status); 433 return status/* & ACPI_EVENT_FLAG_SET*/; 434 } 435 436 437 void 438 reset_fixed_event(uint32 event) 439 { 440 AcpiClearEvent(event); 441 } 442 443 444 status_t 445 install_fixed_event_handler(uint32 event, acpi_event_handler handler, 446 void *data) 447 { 448 return AcpiInstallFixedEventHandler(event, (ACPI_EVENT_HANDLER)handler, data) == AE_OK 449 ? B_OK : B_ERROR; 450 } 451 452 453 status_t 454 remove_fixed_event_handler(uint32 event, acpi_event_handler handler) 455 { 456 return AcpiRemoveFixedEventHandler(event, (ACPI_EVENT_HANDLER)handler) == AE_OK 457 ? B_OK : B_ERROR; 458 } 459 460 461 status_t 462 get_next_entry(uint32 objectType, const char *base, char *result, 463 size_t length, void **counter) 464 { 465 ACPI_HANDLE parent, child, newChild; 466 ACPI_BUFFER buffer; 467 ACPI_STATUS status; 468 469 TRACE("get_next_entry %ld, %s\n", objectType, base); 470 471 if (base == NULL || !strcmp(base, "\\")) { 472 parent = ACPI_ROOT_OBJECT; 473 } else { 474 status = AcpiGetHandle(NULL, (ACPI_STRING)base, &parent); 475 if (status != AE_OK) 476 return B_ENTRY_NOT_FOUND; 477 } 478 479 child = *counter; 480 481 status = AcpiGetNextObject(objectType, parent, child, &newChild); 482 if (status != AE_OK) 483 return B_ENTRY_NOT_FOUND; 484 485 *counter = newChild; 486 buffer.Length = length; 487 buffer.Pointer = result; 488 489 status = AcpiGetName(newChild, ACPI_FULL_PATHNAME, &buffer); 490 if (status != AE_OK) 491 return B_NO_MEMORY; /* Corresponds to AE_BUFFER_OVERFLOW */ 492 493 return B_OK; 494 } 495 496 497 status_t 498 get_next_object(uint32 objectType, acpi_handle parent, 499 acpi_handle* currentChild) 500 { 501 acpi_handle child = *currentChild; 502 return AcpiGetNextObject(objectType, parent, child, currentChild) == AE_OK 503 ? B_OK : B_ERROR; 504 } 505 506 507 status_t 508 get_device(const char* hid, uint32 index, char* result, size_t resultLength) 509 { 510 ACPI_STATUS status; 511 uint32 counter[2] = {index, 0}; 512 char *buffer = NULL; 513 514 TRACE("get_device %s, index %ld\n", hid, index); 515 status = AcpiGetDevices((ACPI_STRING)hid, (ACPI_WALK_CALLBACK)&get_device_by_hid_callback, 516 counter, (void**)&buffer); 517 if (status != AE_OK || buffer == NULL) 518 return B_ENTRY_NOT_FOUND; 519 520 strlcpy(result, buffer, resultLength); 521 free(buffer); 522 return B_OK; 523 } 524 525 526 status_t 527 get_device_info(const char *path, char** hid, char** cidList, 528 size_t cidListCount, char** uid, char** cls) 529 { 530 ACPI_HANDLE handle; 531 ACPI_DEVICE_INFO *info; 532 533 TRACE("get_device_info: path %s\n", path); 534 if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK) 535 return B_ENTRY_NOT_FOUND; 536 537 if (AcpiGetObjectInfo(handle, &info) != AE_OK) 538 return B_BAD_TYPE; 539 540 if ((info->Valid & ACPI_VALID_HID) != 0 && hid != NULL) 541 *hid = strndup(info->HardwareId.String, info->HardwareId.Length); 542 543 if ((info->Valid & ACPI_VALID_CID) != 0 && cidList != NULL) { 544 if (cidListCount > info->CompatibleIdList.Count) 545 cidListCount = info->CompatibleIdList.Count; 546 for (size_t i = 0; i < cidListCount; i++) { 547 cidList[i] = strndup(info->CompatibleIdList.Ids[i].String, 548 info->CompatibleIdList.Ids[i].Length); 549 } 550 } 551 552 if ((info->Valid & ACPI_VALID_UID) != 0 && uid != NULL) 553 *uid = strndup(info->UniqueId.String, info->UniqueId.Length); 554 555 if ((info->Valid & ACPI_VALID_CLS) != 0 && cls != NULL 556 && info->ClassCode.Length >= ACPI_PCICLS_STRING_SIZE) { 557 *cls = strndup(info->ClassCode.String, info->ClassCode.Length); 558 } 559 560 AcpiOsFree(info); 561 return B_OK; 562 } 563 564 565 status_t 566 get_device_addr(const char *path, uint32 *addr) 567 { 568 ACPI_HANDLE handle; 569 570 TRACE("get_device_adr: path %s, hid %s\n", path, hid); 571 if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK) 572 return B_ENTRY_NOT_FOUND; 573 574 status_t status = B_BAD_VALUE; 575 acpi_data buf; 576 acpi_object_type object; 577 buf.pointer = &object; 578 buf.length = sizeof(acpi_object_type); 579 if (addr != NULL 580 && evaluate_method(handle, "_ADR", NULL, &buf) == B_OK 581 && object.object_type == ACPI_TYPE_INTEGER) { 582 status = B_OK; 583 *addr = object.integer.integer; 584 } 585 return status; 586 } 587 588 589 uint32 590 get_object_type(const char* path) 591 { 592 ACPI_HANDLE handle; 593 ACPI_OBJECT_TYPE type; 594 595 if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK) 596 return B_ENTRY_NOT_FOUND; 597 598 AcpiGetType(handle, &type); 599 return type; 600 } 601 602 603 status_t 604 get_object(const char* path, acpi_object_type** _returnValue) 605 { 606 ACPI_HANDLE handle; 607 ACPI_BUFFER buffer; 608 ACPI_STATUS status; 609 610 status = AcpiGetHandle(NULL, (ACPI_STRING)path, &handle); 611 if (status != AE_OK) 612 return B_ENTRY_NOT_FOUND; 613 614 buffer.Pointer = NULL; 615 buffer.Length = ACPI_ALLOCATE_BUFFER; 616 617 status = AcpiEvaluateObject(handle, NULL, NULL, &buffer); 618 619 *_returnValue = (acpi_object_type*)buffer.Pointer; 620 return status == AE_OK ? B_OK : B_ERROR; 621 } 622 623 624 status_t 625 get_object_typed(const char* path, acpi_object_type** _returnValue, 626 uint32 objectType) 627 { 628 ACPI_HANDLE handle; 629 ACPI_BUFFER buffer; 630 ACPI_STATUS status; 631 632 status = AcpiGetHandle(NULL, (ACPI_STRING)path, &handle); 633 if (status != AE_OK) 634 return B_ENTRY_NOT_FOUND; 635 636 buffer.Pointer = NULL; 637 buffer.Length = ACPI_ALLOCATE_BUFFER; 638 639 status = AcpiEvaluateObjectTyped(handle, NULL, NULL, &buffer, objectType); 640 641 *_returnValue = (acpi_object_type*)buffer.Pointer; 642 return status == AE_OK ? B_OK : B_ERROR; 643 } 644 645 646 status_t 647 ns_handle_to_pathname(acpi_handle targetHandle, acpi_data *buffer) 648 { 649 status_t status = AcpiNsHandleToPathname(targetHandle, 650 (ACPI_BUFFER*)buffer, false); 651 return status == AE_OK ? B_OK : B_ERROR; 652 } 653 654 655 status_t 656 evaluate_object(acpi_handle handle, const char* object, acpi_objects *args, 657 acpi_object_type* returnValue, size_t bufferLength) 658 { 659 ACPI_BUFFER buffer; 660 ACPI_STATUS status; 661 662 buffer.Pointer = returnValue; 663 buffer.Length = bufferLength; 664 665 status = AcpiEvaluateObject(handle, (ACPI_STRING)object, 666 (ACPI_OBJECT_LIST*)args, returnValue != NULL ? &buffer : NULL); 667 if (status == AE_BUFFER_OVERFLOW) 668 dprintf("evaluate_object: the passed buffer is too small!\n"); 669 670 return status == AE_OK ? B_OK : B_ERROR; 671 } 672 673 674 status_t 675 evaluate_method(acpi_handle handle, const char* method, 676 acpi_objects *args, acpi_data *returnValue) 677 { 678 ACPI_STATUS status; 679 680 status = AcpiEvaluateObject(handle, (ACPI_STRING)method, 681 (ACPI_OBJECT_LIST*)args, (ACPI_BUFFER*)returnValue); 682 if (status == AE_BUFFER_OVERFLOW) 683 dprintf("evaluate_method: the passed buffer is too small!\n"); 684 685 return status == AE_OK ? B_OK : B_ERROR; 686 } 687 688 689 status_t 690 get_irq_routing_table(acpi_handle busDeviceHandle, acpi_data *retBuffer) 691 { 692 ACPI_STATUS status; 693 694 status = AcpiGetIrqRoutingTable(busDeviceHandle, (ACPI_BUFFER*)retBuffer); 695 if (status == AE_BUFFER_OVERFLOW) 696 dprintf("get_irq_routing_table: the passed buffer is too small!\n"); 697 698 return status == AE_OK ? B_OK : B_ERROR; 699 } 700 701 702 status_t 703 get_current_resources(acpi_handle busDeviceHandle, acpi_data *retBuffer) 704 { 705 return AcpiGetCurrentResources(busDeviceHandle, (ACPI_BUFFER*)retBuffer) 706 == AE_OK ? B_OK : B_ERROR; 707 } 708 709 710 status_t 711 get_possible_resources(acpi_handle busDeviceHandle, acpi_data *retBuffer) 712 { 713 return AcpiGetPossibleResources(busDeviceHandle, (ACPI_BUFFER*)retBuffer) 714 == AE_OK ? B_OK : B_ERROR; 715 } 716 717 718 status_t 719 set_current_resources(acpi_handle busDeviceHandle, acpi_data *buffer) 720 { 721 return AcpiSetCurrentResources(busDeviceHandle, (ACPI_BUFFER*)buffer) 722 == AE_OK ? B_OK : B_ERROR; 723 } 724 725 726 status_t 727 walk_resources(acpi_handle busDeviceHandle, char* method, 728 acpi_walk_resources_callback callback, void* context) 729 { 730 return AcpiWalkResources(busDeviceHandle, method, 731 (ACPI_WALK_RESOURCE_CALLBACK)callback, context); 732 } 733 734 735 status_t 736 walk_namespace(acpi_handle busDeviceHandle, uint32 objectType, 737 uint32 maxDepth, acpi_walk_callback descendingCallback, 738 acpi_walk_callback ascendingCallback, void* context, void** returnValue) 739 { 740 return AcpiWalkNamespace(objectType, busDeviceHandle, maxDepth, 741 (ACPI_WALK_CALLBACK)descendingCallback, 742 (ACPI_WALK_CALLBACK)ascendingCallback, context, returnValue); 743 } 744 745 746 status_t 747 prepare_sleep_state(uint8 state, void (*wakeFunc)(void), size_t size) 748 { 749 ACPI_STATUS acpiStatus; 750 751 TRACE("prepare_sleep_state %d, %p, %ld\n", state, wakeFunc, size); 752 753 if (state != ACPI_POWER_STATE_OFF) { 754 physical_entry wakeVector; 755 status_t status; 756 757 // Note: The supplied code must already be locked into memory. 758 status = get_memory_map((const void*)wakeFunc, size, &wakeVector, 1); 759 if (status != B_OK) 760 return status; 761 762 # if B_HAIKU_PHYSICAL_BITS > 32 763 if (wakeVector.address >= 0x100000000LL) { 764 ERROR("prepare_sleep_state(): ACPI 2.0c says use 32 bit " 765 "vector, but we have a physical address >= 4 GB\n"); 766 } 767 # endif 768 acpiStatus = AcpiSetFirmwareWakingVector(wakeVector.address, 769 wakeVector.address); 770 if (acpiStatus != AE_OK) 771 return B_ERROR; 772 } 773 774 acpiStatus = AcpiEnterSleepStatePrep(state); 775 if (acpiStatus != AE_OK) 776 return B_ERROR; 777 778 return B_OK; 779 } 780 781 782 status_t 783 enter_sleep_state(uint8 state) 784 { 785 ACPI_STATUS status; 786 787 TRACE("enter_sleep_state %d\n", state); 788 789 cpu_status cpu = disable_interrupts(); 790 status = AcpiEnterSleepState(state); 791 restore_interrupts(cpu); 792 panic("AcpiEnterSleepState should not return."); 793 if (status != AE_OK) 794 return B_ERROR; 795 796 /*status = AcpiLeaveSleepState(state); 797 if (status != AE_OK) 798 return B_ERROR;*/ 799 800 return B_OK; 801 } 802 803 804 status_t 805 reboot(void) 806 { 807 ACPI_STATUS status; 808 809 TRACE("reboot\n"); 810 811 status = AcpiReset(); 812 if (status == AE_NOT_EXIST) 813 return B_UNSUPPORTED; 814 815 if (status != AE_OK) { 816 ERROR("Reset failed, status = %d\n", status); 817 return B_ERROR; 818 } 819 820 snooze(1000000); 821 ERROR("Reset failed, timeout\n"); 822 return B_ERROR; 823 } 824 825 826 status_t 827 get_table(const char* signature, uint32 instance, void** tableHeader) 828 { 829 return AcpiGetTable((char*)signature, instance, 830 (ACPI_TABLE_HEADER**)tableHeader) == AE_OK ? B_OK : B_ERROR; 831 } 832 833 834 status_t 835 read_bit_register(uint32 regid, uint32 *val) 836 { 837 return AcpiReadBitRegister(regid, (UINT32 *)val); 838 } 839 840 841 status_t 842 write_bit_register(uint32 regid, uint32 val) 843 { 844 return AcpiWriteBitRegister(regid, val); 845 } 846 847 848 struct acpi_module_info gACPIModule = { 849 { 850 B_ACPI_MODULE_NAME, 851 B_KEEP_LOADED, 852 acpi_std_ops 853 }, 854 855 get_handle, 856 get_name, 857 acquire_global_lock, 858 release_global_lock, 859 install_notify_handler, 860 remove_notify_handler, 861 update_all_gpes, 862 enable_gpe, 863 disable_gpe, 864 clear_gpe, 865 set_gpe, 866 finish_gpe, 867 install_gpe_handler, 868 remove_gpe_handler, 869 install_address_space_handler, 870 remove_address_space_handler, 871 enable_fixed_event, 872 disable_fixed_event, 873 fixed_event_status, 874 reset_fixed_event, 875 install_fixed_event_handler, 876 remove_fixed_event_handler, 877 get_next_entry, 878 get_next_object, 879 walk_namespace, 880 get_device, 881 get_device_info, 882 get_object_type, 883 get_object, 884 get_object_typed, 885 ns_handle_to_pathname, 886 evaluate_object, 887 evaluate_method, 888 get_irq_routing_table, 889 get_current_resources, 890 get_possible_resources, 891 set_current_resources, 892 walk_resources, 893 prepare_sleep_state, 894 enter_sleep_state, 895 reboot, 896 get_table, 897 read_bit_register, 898 write_bit_register 899 }; 900