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) 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 AcpiOsFree(info); 556 return B_OK; 557 } 558 559 560 status_t 561 get_device_addr(const char *path, uint32 *addr) 562 { 563 ACPI_HANDLE handle; 564 565 TRACE("get_device_adr: path %s, hid %s\n", path, hid); 566 if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK) 567 return B_ENTRY_NOT_FOUND; 568 569 status_t status = B_BAD_VALUE; 570 acpi_data buf; 571 acpi_object_type object; 572 buf.pointer = &object; 573 buf.length = sizeof(acpi_object_type); 574 if (addr != NULL 575 && evaluate_method(handle, "_ADR", NULL, &buf) == B_OK 576 && object.object_type == ACPI_TYPE_INTEGER) { 577 status = B_OK; 578 *addr = object.integer.integer; 579 } 580 return status; 581 } 582 583 584 uint32 585 get_object_type(const char* path) 586 { 587 ACPI_HANDLE handle; 588 ACPI_OBJECT_TYPE type; 589 590 if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK) 591 return B_ENTRY_NOT_FOUND; 592 593 AcpiGetType(handle, &type); 594 return type; 595 } 596 597 598 status_t 599 get_object(const char* path, acpi_object_type** _returnValue) 600 { 601 ACPI_HANDLE handle; 602 ACPI_BUFFER buffer; 603 ACPI_STATUS status; 604 605 status = AcpiGetHandle(NULL, (ACPI_STRING)path, &handle); 606 if (status != AE_OK) 607 return B_ENTRY_NOT_FOUND; 608 609 buffer.Pointer = NULL; 610 buffer.Length = ACPI_ALLOCATE_BUFFER; 611 612 status = AcpiEvaluateObject(handle, NULL, NULL, &buffer); 613 614 *_returnValue = (acpi_object_type*)buffer.Pointer; 615 return status == AE_OK ? B_OK : B_ERROR; 616 } 617 618 619 status_t 620 get_object_typed(const char* path, acpi_object_type** _returnValue, 621 uint32 objectType) 622 { 623 ACPI_HANDLE handle; 624 ACPI_BUFFER buffer; 625 ACPI_STATUS status; 626 627 status = AcpiGetHandle(NULL, (ACPI_STRING)path, &handle); 628 if (status != AE_OK) 629 return B_ENTRY_NOT_FOUND; 630 631 buffer.Pointer = NULL; 632 buffer.Length = ACPI_ALLOCATE_BUFFER; 633 634 status = AcpiEvaluateObjectTyped(handle, NULL, NULL, &buffer, objectType); 635 636 *_returnValue = (acpi_object_type*)buffer.Pointer; 637 return status == AE_OK ? B_OK : B_ERROR; 638 } 639 640 641 status_t 642 ns_handle_to_pathname(acpi_handle targetHandle, acpi_data *buffer) 643 { 644 status_t status = AcpiNsHandleToPathname(targetHandle, 645 (ACPI_BUFFER*)buffer, false); 646 return status == AE_OK ? B_OK : B_ERROR; 647 } 648 649 650 status_t 651 evaluate_object(acpi_handle handle, const char* object, acpi_objects *args, 652 acpi_object_type* returnValue, size_t bufferLength) 653 { 654 ACPI_BUFFER buffer; 655 ACPI_STATUS status; 656 657 buffer.Pointer = returnValue; 658 buffer.Length = bufferLength; 659 660 status = AcpiEvaluateObject(handle, (ACPI_STRING)object, 661 (ACPI_OBJECT_LIST*)args, returnValue != NULL ? &buffer : NULL); 662 if (status == AE_BUFFER_OVERFLOW) 663 dprintf("evaluate_object: the passed buffer is too small!\n"); 664 665 return status == AE_OK ? B_OK : B_ERROR; 666 } 667 668 669 status_t 670 evaluate_method(acpi_handle handle, const char* method, 671 acpi_objects *args, acpi_data *returnValue) 672 { 673 ACPI_STATUS status; 674 675 status = AcpiEvaluateObject(handle, (ACPI_STRING)method, 676 (ACPI_OBJECT_LIST*)args, (ACPI_BUFFER*)returnValue); 677 if (status == AE_BUFFER_OVERFLOW) 678 dprintf("evaluate_method: the passed buffer is too small!\n"); 679 680 return status == AE_OK ? B_OK : B_ERROR; 681 } 682 683 684 status_t 685 get_irq_routing_table(acpi_handle busDeviceHandle, acpi_data *retBuffer) 686 { 687 ACPI_STATUS status; 688 689 status = AcpiGetIrqRoutingTable(busDeviceHandle, (ACPI_BUFFER*)retBuffer); 690 if (status == AE_BUFFER_OVERFLOW) 691 dprintf("get_irq_routing_table: the passed buffer is too small!\n"); 692 693 return status == AE_OK ? B_OK : B_ERROR; 694 } 695 696 697 status_t 698 get_current_resources(acpi_handle busDeviceHandle, acpi_data *retBuffer) 699 { 700 return AcpiGetCurrentResources(busDeviceHandle, (ACPI_BUFFER*)retBuffer) 701 == AE_OK ? B_OK : B_ERROR; 702 } 703 704 705 status_t 706 get_possible_resources(acpi_handle busDeviceHandle, acpi_data *retBuffer) 707 { 708 return AcpiGetPossibleResources(busDeviceHandle, (ACPI_BUFFER*)retBuffer) 709 == AE_OK ? B_OK : B_ERROR; 710 } 711 712 713 status_t 714 set_current_resources(acpi_handle busDeviceHandle, acpi_data *buffer) 715 { 716 return AcpiSetCurrentResources(busDeviceHandle, (ACPI_BUFFER*)buffer) 717 == AE_OK ? B_OK : B_ERROR; 718 } 719 720 721 status_t 722 walk_resources(acpi_handle busDeviceHandle, char* method, 723 acpi_walk_resources_callback callback, void* context) 724 { 725 return AcpiWalkResources(busDeviceHandle, method, 726 (ACPI_WALK_RESOURCE_CALLBACK)callback, context); 727 } 728 729 730 status_t 731 walk_namespace(acpi_handle busDeviceHandle, uint32 objectType, 732 uint32 maxDepth, acpi_walk_callback descendingCallback, 733 acpi_walk_callback ascendingCallback, void* context, void** returnValue) 734 { 735 return AcpiWalkNamespace(objectType, busDeviceHandle, maxDepth, 736 (ACPI_WALK_CALLBACK)descendingCallback, 737 (ACPI_WALK_CALLBACK)ascendingCallback, context, returnValue); 738 } 739 740 741 status_t 742 prepare_sleep_state(uint8 state, void (*wakeFunc)(void), size_t size) 743 { 744 ACPI_STATUS acpiStatus; 745 746 TRACE("prepare_sleep_state %d, %p, %ld\n", state, wakeFunc, size); 747 748 if (state != ACPI_POWER_STATE_OFF) { 749 physical_entry wakeVector; 750 status_t status; 751 752 // Note: The supplied code must already be locked into memory. 753 status = get_memory_map((const void*)wakeFunc, size, &wakeVector, 1); 754 if (status != B_OK) 755 return status; 756 757 # if B_HAIKU_PHYSICAL_BITS > 32 758 if (wakeVector.address >= 0x100000000LL) { 759 ERROR("prepare_sleep_state(): ACPI 2.0c says use 32 bit " 760 "vector, but we have a physical address >= 4 GB\n"); 761 } 762 # endif 763 acpiStatus = AcpiSetFirmwareWakingVector(wakeVector.address, 764 wakeVector.address); 765 if (acpiStatus != AE_OK) 766 return B_ERROR; 767 } 768 769 acpiStatus = AcpiEnterSleepStatePrep(state); 770 if (acpiStatus != AE_OK) 771 return B_ERROR; 772 773 return B_OK; 774 } 775 776 777 status_t 778 enter_sleep_state(uint8 state) 779 { 780 ACPI_STATUS status; 781 782 TRACE("enter_sleep_state %d\n", state); 783 784 cpu_status cpu = disable_interrupts(); 785 status = AcpiEnterSleepState(state); 786 restore_interrupts(cpu); 787 panic("AcpiEnterSleepState should not return."); 788 if (status != AE_OK) 789 return B_ERROR; 790 791 /*status = AcpiLeaveSleepState(state); 792 if (status != AE_OK) 793 return B_ERROR;*/ 794 795 return B_OK; 796 } 797 798 799 status_t 800 reboot(void) 801 { 802 ACPI_STATUS status; 803 804 TRACE("reboot\n"); 805 806 status = AcpiReset(); 807 if (status == AE_NOT_EXIST) 808 return B_UNSUPPORTED; 809 810 if (status != AE_OK) { 811 ERROR("Reset failed, status = %d\n", status); 812 return B_ERROR; 813 } 814 815 snooze(1000000); 816 ERROR("Reset failed, timeout\n"); 817 return B_ERROR; 818 } 819 820 821 status_t 822 get_table(const char* signature, uint32 instance, void** tableHeader) 823 { 824 return AcpiGetTable((char*)signature, instance, 825 (ACPI_TABLE_HEADER**)tableHeader) == AE_OK ? B_OK : B_ERROR; 826 } 827 828 829 status_t 830 read_bit_register(uint32 regid, uint32 *val) 831 { 832 return AcpiReadBitRegister(regid, (UINT32 *)val); 833 } 834 835 836 status_t 837 write_bit_register(uint32 regid, uint32 val) 838 { 839 return AcpiWriteBitRegister(regid, val); 840 } 841 842 843 struct acpi_module_info gACPIModule = { 844 { 845 B_ACPI_MODULE_NAME, 846 B_KEEP_LOADED, 847 acpi_std_ops 848 }, 849 850 get_handle, 851 get_name, 852 acquire_global_lock, 853 release_global_lock, 854 install_notify_handler, 855 remove_notify_handler, 856 update_all_gpes, 857 enable_gpe, 858 disable_gpe, 859 clear_gpe, 860 set_gpe, 861 finish_gpe, 862 install_gpe_handler, 863 remove_gpe_handler, 864 install_address_space_handler, 865 remove_address_space_handler, 866 enable_fixed_event, 867 disable_fixed_event, 868 fixed_event_status, 869 reset_fixed_event, 870 install_fixed_event_handler, 871 remove_fixed_event_handler, 872 get_next_entry, 873 get_next_object, 874 walk_namespace, 875 get_device, 876 get_device_info, 877 get_object_type, 878 get_object, 879 get_object_typed, 880 ns_handle_to_pathname, 881 evaluate_object, 882 evaluate_method, 883 get_irq_routing_table, 884 get_current_resources, 885 get_possible_resources, 886 set_current_resources, 887 walk_resources, 888 prepare_sleep_state, 889 enter_sleep_state, 890 reboot, 891 get_table, 892 read_bit_register, 893 write_bit_register 894 }; 895