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