1 /****************************************************************************** 2 * 3 * Module Name: oshaiku - Haiku OSL interfaces 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 *****************************************************************************/ 115 116 117 #include <stdio.h> 118 #include <sys/cdefs.h> 119 #include <time.h> 120 #include <unistd.h> 121 122 #include <OS.h> 123 124 #ifdef _KERNEL_MODE 125 # include <KernelExport.h> 126 127 # include <dpc.h> 128 # include <PCI.h> 129 130 # include <boot_item.h> 131 # include <kernel.h> 132 # include <vm/vm.h> 133 #endif 134 135 __BEGIN_DECLS 136 #include "acpi.h" 137 #include "accommon.h" 138 #include "amlcode.h" 139 #include "acparser.h" 140 #include "acdebug.h" 141 __END_DECLS 142 143 #include "arch_init.h" 144 145 146 ACPI_MODULE_NAME("Haiku ACPI Module") 147 148 #define _COMPONENT ACPI_OS_SERVICES 149 150 // verbosity level 0 = off, 1 = normal, 2 = all 151 #define DEBUG_OSHAIKU 0 152 153 #if DEBUG_OSHAIKU <= 0 154 // No debugging, do nothing 155 # define DEBUG_FUNCTION() 156 # define DEBUG_FUNCTION_F(x, y...) 157 # define DEBUG_FUNCTION_V() 158 # define DEBUG_FUNCTION_VF(x, y...) 159 #else 160 # define DEBUG_FUNCTION() \ 161 dprintf("acpi[%" B_PRId32 "]: %s\n", find_thread(NULL), __PRETTY_FUNCTION__); 162 # define DEBUG_FUNCTION_F(x, y...) \ 163 dprintf("acpi[%" B_PRId32 "]: %s(" x ")\n", find_thread(NULL), __PRETTY_FUNCTION__, y); 164 # if DEBUG_OSHAIKU == 1 165 // No verbose debugging, do nothing 166 # define DEBUG_FUNCTION_V() 167 # define DEBUG_FUNCTION_VF(x, y...) 168 # else 169 // Full debugging 170 # define DEBUG_FUNCTION_V() \ 171 dprintf("acpi[%" B_PRId32 "]: %s\n", find_thread(NULL), __PRETTY_FUNCTION__); 172 # define DEBUG_FUNCTION_VF(x, y...) \ 173 dprintf("acpi[%" B_PRId32 "]: %s(" x ")\n", find_thread(NULL), __PRETTY_FUNCTION__, y); 174 # endif 175 #endif 176 177 178 #ifdef _KERNEL_MODE 179 extern pci_module_info *gPCIManager; 180 extern dpc_module_info *gDPC; 181 extern void *gDPCHandle; 182 #endif 183 184 extern FILE *AcpiGbl_DebugFile; 185 FILE *AcpiGbl_OutputFile; 186 187 static ACPI_PHYSICAL_ADDRESS sACPIRoot = 0; 188 static void *sInterruptHandlerData[32]; 189 190 191 /****************************************************************************** 192 * 193 * FUNCTION: AcpiOsInitialize, AcpiOsTerminate 194 * 195 * PARAMETERS: None 196 * 197 * RETURN: Status 198 * 199 * DESCRIPTION: Init and terminate. Nothing to do. 200 * 201 *****************************************************************************/ 202 ACPI_STATUS 203 AcpiOsInitialize() 204 { 205 #ifndef _KERNEL_MODE 206 AcpiGbl_OutputFile = stdout; 207 #else 208 AcpiGbl_OutputFile = NULL; 209 #endif 210 DEBUG_FUNCTION(); 211 return AE_OK; 212 } 213 214 215 ACPI_STATUS 216 AcpiOsTerminate() 217 { 218 DEBUG_FUNCTION(); 219 return AE_OK; 220 } 221 222 223 /****************************************************************************** 224 * 225 * FUNCTION: AcpiOsGetRootPointer 226 * 227 * PARAMETERS: None 228 * 229 * RETURN: RSDP physical address 230 * 231 * DESCRIPTION: Gets the root pointer (RSDP) 232 * 233 *****************************************************************************/ 234 ACPI_PHYSICAL_ADDRESS 235 AcpiOsGetRootPointer() 236 { 237 #ifdef _KERNEL_MODE 238 DEBUG_FUNCTION(); 239 if (sACPIRoot == 0) { 240 phys_addr_t* acpiRootPointer = (phys_addr_t*)get_boot_item("ACPI_ROOT_POINTER", NULL); 241 if (acpiRootPointer != NULL) 242 sACPIRoot = *acpiRootPointer; 243 244 if (sACPIRoot == 0) 245 sACPIRoot = arch_init_find_root_pointer(); 246 } 247 return sACPIRoot; 248 #else 249 return AeLocalGetRootPointer(); 250 #endif 251 } 252 253 254 /****************************************************************************** 255 * 256 * FUNCTION: AcpiOsPredefinedOverride 257 * 258 * PARAMETERS: initVal - Initial value of the predefined object 259 * newVal - The new value for the object 260 * 261 * RETURN: Status, pointer to value. Null pointer returned if not 262 * overriding. 263 * 264 * DESCRIPTION: Allow the OS to override predefined names 265 * 266 *****************************************************************************/ 267 ACPI_STATUS 268 AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *initVal, 269 ACPI_STRING *newVal) 270 { 271 DEBUG_FUNCTION(); 272 if (!initVal || !newVal) 273 return AE_BAD_PARAMETER; 274 275 *newVal = NULL; 276 return AE_OK; 277 } 278 279 280 /****************************************************************************** 281 * 282 * FUNCTION: AcpiOsTableOverride 283 * 284 * PARAMETERS: existingTable - Header of current table (probably firmware) 285 * newTable - Where an entire new table is returned. 286 * 287 * RETURN: Status, pointer to new table. Null pointer returned if no 288 * table is available to override 289 * 290 * DESCRIPTION: Return a different version of a table if one is available 291 * 292 *****************************************************************************/ 293 ACPI_STATUS 294 AcpiOsTableOverride(ACPI_TABLE_HEADER *existingTable, 295 ACPI_TABLE_HEADER **newTable) 296 { 297 DEBUG_FUNCTION(); 298 if (!existingTable || !newTable) 299 return AE_BAD_PARAMETER; 300 301 *newTable = NULL; 302 303 #ifdef ACPI_EXEC_APP 304 AeTableOverride(existingTable, newTable); 305 return AE_OK; 306 #else 307 return AE_NO_ACPI_TABLES; 308 #endif 309 } 310 311 312 /****************************************************************************** 313 * 314 * FUNCTION: AcpiOsPhysicalTableOverride 315 * 316 * PARAMETERS: existingTable - Header of current table (probably firmware) 317 * newAddress - Where new table address is returned 318 * (Physical address) 319 * newTableLength - Where new table length is returned 320 * 321 * RETURN: Status, address/length of new table. Null pointer returned 322 * if no table is available to override. 323 * 324 * DESCRIPTION: Returns AE_SUPPORT, function not used in user space. 325 * 326 *****************************************************************************/ 327 328 ACPI_STATUS 329 AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *existingTable, 330 ACPI_PHYSICAL_ADDRESS *newAddress, UINT32 *newTableLength) 331 { 332 DEBUG_FUNCTION(); 333 return (AE_SUPPORT); 334 } 335 336 337 /****************************************************************************** 338 * 339 * FUNCTION: AcpiOsRedirectOutput 340 * 341 * PARAMETERS: destination - An open file handle/pointer 342 * 343 * RETURN: None 344 * 345 * DESCRIPTION: Causes redirect of AcpiOsPrintf and AcpiOsVprintf 346 * 347 *****************************************************************************/ 348 void 349 AcpiOsRedirectOutput(void *destination) 350 { 351 DEBUG_FUNCTION(); 352 AcpiGbl_OutputFile = (FILE*)destination; 353 } 354 355 356 /****************************************************************************** 357 * 358 * FUNCTION: AcpiOsPrintf 359 * 360 * PARAMETERS: fmt, ... Standard printf format 361 * 362 * RETURN: None 363 * 364 * DESCRIPTION: Formatted output 365 * 366 *****************************************************************************/ 367 void ACPI_INTERNAL_VAR_XFACE 368 AcpiOsPrintf(const char *fmt, ...) 369 { 370 va_list args; 371 372 DEBUG_FUNCTION(); 373 va_start(args, fmt); 374 AcpiOsVprintf(fmt, args); 375 va_end(args); 376 } 377 378 379 /****************************************************************************** 380 * 381 * FUNCTION: AcpiOsVprintf 382 * 383 * PARAMETERS: fmt Standard printf format 384 * args Argument list 385 * 386 * RETURN: None 387 * 388 * DESCRIPTION: Formatted output with argument list pointer 389 * 390 *****************************************************************************/ 391 void 392 AcpiOsVprintf(const char *fmt, va_list args) 393 { 394 #ifndef _KERNEL_MODE 395 UINT8 flags; 396 397 flags = AcpiGbl_DbOutputFlags; 398 if (flags & ACPI_DB_REDIRECTABLE_OUTPUT) { 399 // Output is directable to either a file (if open) or the console 400 if (AcpiGbl_DebugFile) { 401 // Output file is open, send the output there 402 vfprintf(AcpiGbl_DebugFile, fmt, args); 403 } else { 404 // No redirection, send output to console (once only!) 405 flags |= ACPI_DB_CONSOLE_OUTPUT; 406 } 407 } 408 409 if (flags & ACPI_DB_CONSOLE_OUTPUT) { 410 vfprintf(AcpiGbl_OutputFile, fmt, args); 411 } 412 #else 413 // Buffer the output until we have a complete line to send to syslog, this avoids added 414 // "KERN:" entries in the middle of the line, and mixing up of the ACPI output with other 415 // messages from other CPUs 416 static char outputBuffer[1024]; 417 418 // Append the new text to the buffer 419 size_t len = strlen(outputBuffer); 420 size_t printed = vsnprintf(outputBuffer + len, 1024 - len, fmt, args); 421 if (printed >= 1024 - len) { 422 // There was no space to fit the printed string in the outputBuffer. Remove what we added 423 // there, fush the buffer, and print the long string directly 424 outputBuffer[len] = '\0'; 425 dprintf("%s\n", outputBuffer); 426 outputBuffer[0] = '\0'; 427 dvprintf(fmt, args); 428 return; 429 } 430 431 // See if we have a complete line 432 char* eol = strchr(outputBuffer + len, '\n'); 433 while (eol != nullptr) { 434 // Print the completed line, then remove it from the buffer 435 *eol = 0; 436 dprintf("%s\n", outputBuffer); 437 memmove(outputBuffer, eol + 1, strlen(eol + 1) + 1); 438 // See if there is another line to print still in the buffer (in case ACPICA would call 439 // this function with a single string containing multiple newlines) 440 eol = strchr(outputBuffer, '\n'); 441 } 442 #endif 443 } 444 445 446 /****************************************************************************** 447 * 448 * FUNCTION: AcpiOsGetLine 449 * 450 * PARAMETERS: fmt Standard printf format 451 * args Argument list 452 * 453 * RETURN: Actual bytes read 454 * 455 * DESCRIPTION: Formatted input with argument list pointer 456 * 457 *****************************************************************************/ 458 UINT32 459 AcpiOsGetLine(char *buffer) 460 { 461 uint32 i = 0; 462 463 #ifndef _KERNEL_MODE 464 uint8 temp; 465 466 for (i = 0; ; i++) { 467 scanf("%1c", &temp); 468 if (!temp || temp == '\n') 469 break; 470 471 buffer[i] = temp; 472 } 473 #endif 474 475 buffer[i] = 0; 476 DEBUG_FUNCTION_F("buffer: \"%s\"; result: %" B_PRIu32, buffer, i); 477 return i; 478 } 479 480 481 /****************************************************************************** 482 * 483 * FUNCTION: AcpiOsMapMemory 484 * 485 * PARAMETERS: where Physical address of memory to be mapped 486 * length How much memory to map 487 * 488 * RETURN: Pointer to mapped memory. Null on error. 489 * 490 * DESCRIPTION: Map physical memory into caller's address space 491 * 492 *****************************************************************************/ 493 void * 494 AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS where, ACPI_SIZE length) 495 { 496 #ifdef _KERNEL_MODE 497 // map_physical_memory() defaults to uncached memory if no type is specified. 498 // But ACPICA handles flushing caches itself, so we don't need it uncached, 499 // and on some architectures (e.g. ARM) uncached memory does not support 500 // unaligned accesses. Hence we specify "writeback" to avoid the default. 501 void *there; 502 area_id area = map_physical_memory("acpi_physical_mem_area", (phys_addr_t)where, length, 503 B_ANY_KERNEL_ADDRESS | B_WRITE_BACK_MEMORY, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 504 &there); 505 506 DEBUG_FUNCTION_F("addr: 0x%08lx; length: %lu; mapped: %p; area: %" B_PRId32, 507 (addr_t)where, (size_t)length, there, area); 508 if (area < 0) { 509 dprintf("ACPI: cannot map memory at 0x%" B_PRIu64 ", length %" 510 B_PRIu64 "\n", (uint64)where, (uint64)length); 511 return NULL; 512 } 513 return there; 514 #else 515 return NULL; 516 #endif 517 518 // return ACPI_TO_POINTER((ACPI_SIZE) where); 519 } 520 521 522 /****************************************************************************** 523 * 524 * FUNCTION: AcpiOsUnmapMemory 525 * 526 * PARAMETERS: where Logical address of memory to be unmapped 527 * length How much memory to unmap 528 * 529 * RETURN: None. 530 * 531 * DESCRIPTION: Delete a previously created mapping. Where and Length must 532 * correspond to a previous mapping exactly. 533 * 534 *****************************************************************************/ 535 void 536 AcpiOsUnmapMemory(void *where, ACPI_SIZE length) 537 { 538 DEBUG_FUNCTION_F("mapped: %p; length: %lu", where, (size_t)length); 539 delete_area(area_for(where)); 540 } 541 542 543 /****************************************************************************** 544 * 545 * FUNCTION: AcpiOsAllocate 546 * 547 * PARAMETERS: size Amount to allocate, in bytes 548 * 549 * RETURN: Pointer to the new allocation. Null on error. 550 * 551 * DESCRIPTION: Allocate memory. Algorithm is dependent on the OS. 552 * 553 *****************************************************************************/ 554 void * 555 AcpiOsAllocate(ACPI_SIZE size) 556 { 557 void *mem = (void *) malloc(size); 558 DEBUG_FUNCTION_VF("result: %p", mem); 559 return mem; 560 } 561 562 563 /****************************************************************************** 564 * 565 * FUNCTION: AcpiOsFree 566 * 567 * PARAMETERS: mem Pointer to previously allocated memory 568 * 569 * RETURN: None. 570 * 571 * DESCRIPTION: Free memory allocated via AcpiOsAllocate 572 * 573 *****************************************************************************/ 574 void 575 AcpiOsFree(void *mem) 576 { 577 DEBUG_FUNCTION_VF("mem: %p", mem); 578 free(mem); 579 } 580 581 582 /****************************************************************************** 583 * 584 * FUNCTION: AcpiOsCreateSemaphore 585 * 586 * PARAMETERS: initialUnits - Units to be assigned to the new semaphore 587 * outHandle - Where a handle will be returned 588 * 589 * RETURN: Status 590 * 591 * DESCRIPTION: Create an OS semaphore 592 * 593 *****************************************************************************/ 594 ACPI_STATUS 595 AcpiOsCreateSemaphore(UINT32 maxUnits, UINT32 initialUnits, 596 ACPI_SEMAPHORE *outHandle) 597 { 598 if (!outHandle) 599 return AE_BAD_PARAMETER; 600 601 *outHandle = create_sem(initialUnits, "acpi_sem"); 602 DEBUG_FUNCTION_F("max: %" B_PRIu32 "; count: %" B_PRIu32 "; result: %" PRId32, 603 (uint32)maxUnits, (uint32)initialUnits, *outHandle); 604 605 if (*outHandle >= B_OK) 606 return AE_OK; 607 608 return *outHandle == B_BAD_VALUE ? AE_BAD_PARAMETER : AE_NO_MEMORY; 609 } 610 611 612 /****************************************************************************** 613 * 614 * FUNCTION: AcpiOsDeleteSemaphore 615 * 616 * PARAMETERS: handle - Handle returned by AcpiOsCreateSemaphore 617 * 618 * RETURN: Status 619 * 620 * DESCRIPTION: Delete an OS semaphore 621 * 622 *****************************************************************************/ 623 ACPI_STATUS 624 AcpiOsDeleteSemaphore(ACPI_SEMAPHORE handle) 625 { 626 DEBUG_FUNCTION_F("sem: %" B_PRId32, handle); 627 return delete_sem(handle) == B_OK ? AE_OK : AE_BAD_PARAMETER; 628 } 629 630 631 /****************************************************************************** 632 * 633 * FUNCTION: AcpiOsWaitSemaphore 634 * 635 * PARAMETERS: handle - Handle returned by AcpiOsCreateSemaphore 636 * units - How many units to wait for 637 * timeout - How long to wait 638 * 639 * RETURN: Status 640 * 641 * DESCRIPTION: Wait for units 642 * 643 *****************************************************************************/ 644 ACPI_STATUS 645 AcpiOsWaitSemaphore(ACPI_SEMAPHORE handle, UINT32 units, UINT16 timeout) 646 { 647 ACPI_STATUS result = AE_OK; 648 DEBUG_FUNCTION_VF("sem: %ld; count: %lu; timeout: %u", 649 handle, (uint32)units, timeout); 650 651 if (timeout == ACPI_WAIT_FOREVER) { 652 result = acquire_sem_etc(handle, units, 0, 0) 653 == B_OK ? AE_OK : AE_BAD_PARAMETER; 654 } else { 655 switch (acquire_sem_etc(handle, units, B_RELATIVE_TIMEOUT, 656 (bigtime_t)timeout * 1000)) { 657 case B_OK: 658 result = AE_OK; 659 break; 660 case B_INTERRUPTED: 661 case B_TIMED_OUT: 662 case B_WOULD_BLOCK: 663 result = AE_TIME; 664 break; 665 case B_BAD_VALUE: 666 default: 667 result = AE_BAD_PARAMETER; 668 break; 669 } 670 } 671 DEBUG_FUNCTION_VF("sem: %ld; count: %lu; timeout: %u result: %lu", 672 handle, (uint32)units, timeout, (uint32)result); 673 return result; 674 } 675 676 677 /****************************************************************************** 678 * 679 * FUNCTION: AcpiOsSignalSemaphore 680 * 681 * PARAMETERS: handle - Handle returned by AcpiOsCreateSemaphore 682 * units - Number of units to send 683 * 684 * RETURN: Status 685 * 686 * DESCRIPTION: Send units 687 * 688 *****************************************************************************/ 689 ACPI_STATUS 690 AcpiOsSignalSemaphore(ACPI_SEMAPHORE handle, UINT32 units) 691 { 692 status_t result; 693 DEBUG_FUNCTION_VF("sem: %ld; count: %lu", handle, (uint32)units); 694 // We can be called from interrupt handler, so don't reschedule 695 result = release_sem_etc(handle, units, B_DO_NOT_RESCHEDULE); 696 return result == B_OK ? AE_OK : AE_BAD_PARAMETER; 697 } 698 699 700 /****************************************************************************** 701 * 702 * FUNCTION: Spinlock interfaces 703 * 704 * DESCRIPTION: Map these interfaces to semaphore interfaces 705 * 706 *****************************************************************************/ 707 ACPI_STATUS 708 AcpiOsCreateLock(ACPI_SPINLOCK *outHandle) 709 { 710 *outHandle = (ACPI_SPINLOCK) malloc(sizeof(spinlock)); 711 DEBUG_FUNCTION_F("result: %p", *outHandle); 712 if (*outHandle == NULL) 713 return AE_NO_MEMORY; 714 715 B_INITIALIZE_SPINLOCK(*outHandle); 716 return AE_OK; 717 } 718 719 720 void 721 AcpiOsDeleteLock(ACPI_SPINLOCK handle) 722 { 723 DEBUG_FUNCTION(); 724 free((void*)handle); 725 } 726 727 728 ACPI_CPU_FLAGS 729 AcpiOsAcquireLock(ACPI_SPINLOCK handle) 730 { 731 cpu_status cpu; 732 DEBUG_FUNCTION_F("spinlock: %p", handle); 733 cpu = disable_interrupts(); 734 acquire_spinlock(handle); 735 return cpu; 736 } 737 738 739 void 740 AcpiOsReleaseLock(ACPI_SPINLOCK handle, ACPI_CPU_FLAGS flags) 741 { 742 release_spinlock(handle); 743 restore_interrupts(flags); 744 DEBUG_FUNCTION_F("spinlock: %p", handle); 745 } 746 747 748 /****************************************************************************** 749 * 750 * FUNCTION: AcpiOsInstallInterruptHandler 751 * 752 * PARAMETERS: interruptNumber Level handler should respond to. 753 * Isr Address of the ACPI interrupt handler 754 * ExceptPtr Where status is returned 755 * 756 * RETURN: Handle to the newly installed handler. 757 * 758 * DESCRIPTION: Install an interrupt handler. Used to install the ACPI 759 * OS-independent handler. 760 * 761 *****************************************************************************/ 762 UINT32 763 AcpiOsInstallInterruptHandler(UINT32 interruptNumber, 764 ACPI_OSD_HANDLER serviceRoutine, void *context) 765 { 766 status_t result; 767 DEBUG_FUNCTION_F("vector: %" B_PRIu32 "; handler: %p context %p", 768 (uint32)interruptNumber, serviceRoutine, context); 769 770 #ifdef _KERNEL_MODE 771 // It so happens that the Haiku and ACPI-CA interrupt handler routines 772 // return the same values with the same meanings 773 sInterruptHandlerData[interruptNumber] = context; 774 result = install_io_interrupt_handler(interruptNumber, 775 (interrupt_handler)serviceRoutine, context, 0); 776 777 DEBUG_FUNCTION_F("vector: %" B_PRIu32 "; handler: %p context %p returned %" B_PRId32, 778 (uint32)interruptNumber, serviceRoutine, context, (uint32)result); 779 780 return result == B_OK ? AE_OK : AE_BAD_PARAMETER; 781 #else 782 return AE_BAD_PARAMETER; 783 #endif 784 } 785 786 787 /****************************************************************************** 788 * 789 * FUNCTION: AcpiOsRemoveInterruptHandler 790 * 791 * PARAMETERS: Handle Returned when handler was installed 792 * 793 * RETURN: Status 794 * 795 * DESCRIPTION: Uninstalls an interrupt handler. 796 * 797 *****************************************************************************/ 798 ACPI_STATUS 799 AcpiOsRemoveInterruptHandler(UINT32 interruptNumber, 800 ACPI_OSD_HANDLER serviceRoutine) 801 { 802 DEBUG_FUNCTION_F("vector: %" B_PRIu32 "; handler: %p", (uint32)interruptNumber, 803 serviceRoutine); 804 #ifdef _KERNEL_MODE 805 return remove_io_interrupt_handler(interruptNumber, 806 (interrupt_handler)serviceRoutine, 807 sInterruptHandlerData[interruptNumber]) == B_OK ? AE_OK : AE_ERROR; 808 #else 809 return AE_ERROR; 810 #endif 811 } 812 813 814 /****************************************************************************** 815 * 816 * FUNCTION: AcpiOsExecute 817 * 818 * PARAMETERS: type - Type of execution 819 * function - Address of the function to execute 820 * context - Passed as a parameter to the function 821 * 822 * RETURN: Status. 823 * 824 * DESCRIPTION: Execute a new thread 825 * 826 *****************************************************************************/ 827 ACPI_STATUS 828 AcpiOsExecute(ACPI_EXECUTE_TYPE type, ACPI_OSD_EXEC_CALLBACK function, 829 void *context) 830 { 831 DEBUG_FUNCTION(); 832 /* TODO: Prioritize urgent? 833 switch (type) { 834 case OSL_GLOBAL_LOCK_HANDLER: 835 case OSL_NOTIFY_HANDLER: 836 case OSL_GPE_HANDLER: 837 case OSL_DEBUGGER_THREAD: 838 case OSL_EC_POLL_HANDLER: 839 case OSL_EC_BURST_HANDLER: 840 break; 841 } 842 */ 843 844 if (gDPC->queue_dpc(gDPCHandle, function, context) != B_OK) { 845 DEBUG_FUNCTION_F("Serious failure in AcpiOsExecute! function: %p", 846 function); 847 return AE_BAD_PARAMETER; 848 } 849 return AE_OK; 850 } 851 852 853 /****************************************************************************** 854 * 855 * FUNCTION: AcpiOsStall 856 * 857 * PARAMETERS: microseconds To sleep 858 * 859 * RETURN: Blocks until sleep is completed. 860 * 861 * DESCRIPTION: Sleep at microsecond granularity 862 * 863 *****************************************************************************/ 864 void 865 AcpiOsStall(UINT32 microseconds) 866 { 867 DEBUG_FUNCTION_F("microseconds: %" B_PRIu32, (uint32)microseconds); 868 if (microseconds) 869 spin(microseconds); 870 } 871 872 873 /****************************************************************************** 874 * 875 * FUNCTION: AcpiOsSleep 876 * 877 * PARAMETERS: milliseconds To sleep 878 * 879 * RETURN: Blocks until sleep is completed. 880 * 881 * DESCRIPTION: Sleep at millisecond granularity 882 * 883 *****************************************************************************/ 884 void 885 AcpiOsSleep(ACPI_INTEGER milliseconds) 886 { 887 DEBUG_FUNCTION_F("milliseconds: %" B_PRIu32, (uint32)milliseconds); 888 if (gKernelStartup) 889 spin(milliseconds * 1000); 890 else 891 snooze(milliseconds * 1000); 892 } 893 894 895 /****************************************************************************** 896 * 897 * FUNCTION: AcpiOsGetTimer 898 * 899 * PARAMETERS: None 900 * 901 * RETURN: Current time in 100 nanosecond units 902 * 903 * DESCRIPTION: Get the current system time 904 * 905 *****************************************************************************/ 906 UINT64 907 AcpiOsGetTimer() 908 { 909 DEBUG_FUNCTION(); 910 return system_time() * 10; 911 } 912 913 914 /****************************************************************************** 915 * 916 * FUNCTION: AcpiOsReadPciConfiguration 917 * 918 * PARAMETERS: pciId Seg/Bus/Dev 919 * reg Device Register 920 * value Buffer where value is placed 921 * width Number of bits 922 * 923 * RETURN: Status 924 * 925 * DESCRIPTION: Read data from PCI configuration space 926 * 927 *****************************************************************************/ 928 ACPI_STATUS 929 AcpiOsReadPciConfiguration(ACPI_PCI_ID *pciId, UINT32 reg, UINT64 *value, 930 UINT32 width) 931 { 932 #ifdef _KERNEL_MODE 933 DEBUG_FUNCTION(); 934 935 switch (width) { 936 case 8: 937 case 16: 938 case 32: 939 *value = gPCIManager->read_pci_config( 940 pciId->Bus, pciId->Device, pciId->Function, reg, width / 8); 941 break; 942 default: 943 return AE_ERROR; 944 } 945 return AE_OK; 946 #else 947 return AE_ERROR; 948 #endif 949 } 950 951 952 /****************************************************************************** 953 * 954 * FUNCTION: AcpiOsWritePciConfiguration 955 * 956 * PARAMETERS: pciId Seg/Bus/Dev 957 * reg Device Register 958 * value Value to be written 959 * width Number of bits 960 * 961 * RETURN: Status. 962 * 963 * DESCRIPTION: Write data to PCI configuration space 964 * 965 *****************************************************************************/ 966 ACPI_STATUS 967 AcpiOsWritePciConfiguration(ACPI_PCI_ID *pciId, UINT32 reg, 968 ACPI_INTEGER value, UINT32 width) 969 { 970 #ifdef _KERNEL_MODE 971 DEBUG_FUNCTION(); 972 gPCIManager->write_pci_config( 973 pciId->Bus, pciId->Device, pciId->Function, reg, width / 8, value); 974 return AE_OK; 975 #else 976 return AE_ERROR; 977 #endif 978 } 979 980 981 /****************************************************************************** 982 * 983 * FUNCTION: AcpiOsReadPort 984 * 985 * PARAMETERS: address Address of I/O port/register to read 986 * Value Where value is placed 987 * width Number of bits 988 * 989 * RETURN: Value read from port 990 * 991 * DESCRIPTION: Read data from an I/O port or register 992 * 993 *****************************************************************************/ 994 ACPI_STATUS 995 AcpiOsReadPort(ACPI_IO_ADDRESS address, UINT32 *value, UINT32 width) 996 { 997 #ifdef _KERNEL_MODE 998 DEBUG_FUNCTION_F("addr: 0x%08lx; width: %" B_PRIu32, (addr_t)address, (uint32)width); 999 switch (width) { 1000 case 8: 1001 *value = gPCIManager->read_io_8(address); 1002 break; 1003 1004 case 16: 1005 *value = gPCIManager->read_io_16(address); 1006 break; 1007 1008 case 32: 1009 *value = gPCIManager->read_io_32(address); 1010 break; 1011 1012 default: 1013 return AE_ERROR; 1014 } 1015 1016 return AE_OK; 1017 #else 1018 return AE_ERROR; 1019 #endif 1020 } 1021 1022 1023 /****************************************************************************** 1024 * 1025 * FUNCTION: AcpiOsWritePort 1026 * 1027 * PARAMETERS: address Address of I/O port/register to write 1028 * value Value to write 1029 * width Number of bits 1030 * 1031 * RETURN: None 1032 * 1033 * DESCRIPTION: Write data to an I/O port or register 1034 * 1035 *****************************************************************************/ 1036 ACPI_STATUS 1037 AcpiOsWritePort(ACPI_IO_ADDRESS address, UINT32 value, UINT32 width) 1038 { 1039 #ifdef _KERNEL_MODE 1040 DEBUG_FUNCTION_F("addr: 0x%08lx; value: %" B_PRIu32 "; width: %" B_PRIu32, 1041 (addr_t)address, (uint32)value, (uint32)width); 1042 switch (width) { 1043 case 8: 1044 gPCIManager->write_io_8(address, value); 1045 break; 1046 1047 case 16: 1048 gPCIManager->write_io_16(address,value); 1049 break; 1050 1051 case 32: 1052 gPCIManager->write_io_32(address,value); 1053 break; 1054 1055 default: 1056 return AE_ERROR; 1057 } 1058 1059 return AE_OK; 1060 #else 1061 return AE_ERROR; 1062 #endif 1063 } 1064 1065 1066 /****************************************************************************** 1067 * 1068 * FUNCTION: AcpiOsReadMemory 1069 * 1070 * PARAMETERS: address Physical Memory Address to read 1071 * value Where value is placed 1072 * width Number of bits 1073 * 1074 * RETURN: Value read from physical memory address 1075 * 1076 * DESCRIPTION: Read data from a physical memory address 1077 * 1078 *****************************************************************************/ 1079 ACPI_STATUS 1080 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 *value, UINT32 width) 1081 { 1082 #ifdef _KERNEL_MODE 1083 if (vm_memcpy_from_physical(value, (phys_addr_t)address, width / 8, false) 1084 != B_OK) { 1085 return AE_ERROR; 1086 } 1087 return AE_OK; 1088 #else 1089 return AE_ERROR; 1090 #endif 1091 } 1092 1093 1094 /****************************************************************************** 1095 * 1096 * FUNCTION: AcpiOsWriteMemory 1097 * 1098 * PARAMETERS: address Physical Memory Address to write 1099 * value Value to write 1100 * width Number of bits 1101 * 1102 * RETURN: None 1103 * 1104 * DESCRIPTION: Write data to a physical memory address 1105 * 1106 *****************************************************************************/ 1107 ACPI_STATUS 1108 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 value, UINT32 width) 1109 { 1110 #ifdef _KERNEL_MODE 1111 if (vm_memcpy_to_physical((phys_addr_t)address, &value, width / 8, false) 1112 != B_OK) { 1113 return AE_ERROR; 1114 } 1115 return AE_OK; 1116 #else 1117 return AE_ERROR; 1118 #endif 1119 } 1120 1121 1122 /****************************************************************************** 1123 * 1124 * FUNCTION: AcpiOsReadable 1125 * 1126 * PARAMETERS: pointer - Area to be verified 1127 * length - Size of area 1128 * 1129 * RETURN: TRUE if readable for entire length 1130 * 1131 * DESCRIPTION: Verify that a pointer is valid for reading 1132 * 1133 *****************************************************************************/ 1134 BOOLEAN 1135 AcpiOsReadable(void *pointer, ACPI_SIZE length) 1136 { 1137 #ifdef _KERNEL_MODE 1138 return true; 1139 #else 1140 area_id id; 1141 area_info info; 1142 1143 DEBUG_FUNCTION_F("addr: %p; length: %lu", pointer, (size_t)length); 1144 1145 id = area_for(pointer); 1146 if (id == B_ERROR) return false; 1147 if (get_area_info(id, &info) != B_OK) return false; 1148 return (info.protection & B_READ_AREA) != 0 && 1149 ((char *)pointer) + length <= info.address + info.ram_size; 1150 #endif 1151 } 1152 1153 1154 /****************************************************************************** 1155 * 1156 * FUNCTION: AcpiOsWritable 1157 * 1158 * PARAMETERS: pointer - Area to be verified 1159 * length - Size of area 1160 * 1161 * RETURN: TRUE if writable for entire length 1162 * 1163 * DESCRIPTION: Verify that a pointer is valid for writing 1164 * 1165 *****************************************************************************/ 1166 BOOLEAN 1167 AcpiOsWritable(void *pointer, ACPI_SIZE length) 1168 { 1169 #ifdef _KERNEL_MODE 1170 return true; 1171 #else 1172 area_id id; 1173 area_info info; 1174 1175 DEBUG_FUNCTION_F("addr: %p; length: %lu", pointer, (size_t)length); 1176 1177 id = area_for(pointer); 1178 if (id == B_ERROR) return false; 1179 if (get_area_info(id, &info) != B_OK) return false; 1180 return (info.protection & B_READ_AREA) != 0 && 1181 (info.protection & B_WRITE_AREA) != 0 && 1182 ((char *)pointer) + length <= info.address + info.ram_size; 1183 #endif 1184 } 1185 1186 1187 /****************************************************************************** 1188 * 1189 * FUNCTION: AcpiOsGetThreadId 1190 * 1191 * PARAMETERS: None 1192 * 1193 * RETURN: Id of the running thread 1194 * 1195 * DESCRIPTION: Get the Id of the current (running) thread 1196 * 1197 * NOTE: The environment header should contain this line: 1198 * #define ACPI_THREAD_ID pthread_t 1199 * 1200 *****************************************************************************/ 1201 ACPI_THREAD_ID 1202 AcpiOsGetThreadId() 1203 { 1204 thread_id thread = find_thread(NULL); 1205 // TODO: We arn't allowed threads with id 0, handle this case. 1206 // ACPI treats a 0 return as an error, 1207 // but we are thread 0 in early boot 1208 return thread; 1209 } 1210 1211 1212 /****************************************************************************** 1213 * 1214 * FUNCTION: AcpiOsSignal 1215 * 1216 * PARAMETERS: function ACPI CA signal function code 1217 * info Pointer to function-dependent structure 1218 * 1219 * RETURN: Status 1220 * 1221 * DESCRIPTION: Miscellaneous functions. Example implementation only. 1222 * 1223 *****************************************************************************/ 1224 ACPI_STATUS 1225 AcpiOsSignal(UINT32 function, void *info) 1226 { 1227 DEBUG_FUNCTION(); 1228 1229 switch (function) { 1230 case ACPI_SIGNAL_FATAL: 1231 #ifdef _KERNEL_MODE 1232 panic("%s", info == NULL ? "AcpiOsSignal: fatal" : (const char*)info); 1233 break; 1234 #endif 1235 case ACPI_SIGNAL_BREAKPOINT: 1236 if (info != NULL) 1237 AcpiOsPrintf("AcpiOsBreakpoint: %s ****\n", (const char*)info); 1238 else 1239 AcpiOsPrintf("At AcpiOsBreakpoint ****\n"); 1240 break; 1241 } 1242 1243 return AE_OK; 1244 } 1245 1246 1247 /* 1248 * Adapted from FreeBSD since the documentation of its intended impl 1249 * is lacking. 1250 * Section 5.2.10.1: global lock acquire/release functions */ 1251 1252 /* 1253 * Adapted from FreeBSD since the documentation of its intended impl 1254 * is lacking. 1255 * Acquire the global lock. If busy, set the pending bit. The caller 1256 * will wait for notification from the BIOS that the lock is available 1257 * and then attempt to acquire it again. 1258 */ 1259 int 1260 AcpiOsAcquireGlobalLock(volatile uint32_t *lock) 1261 { 1262 uint32_t newValue; 1263 uint32_t oldValue; 1264 1265 do { 1266 oldValue = *lock; 1267 newValue = ((oldValue & ~ACPI_GLOCK_PENDING) | ACPI_GLOCK_OWNED); 1268 if ((oldValue & ACPI_GLOCK_OWNED) != 0) 1269 newValue |= ACPI_GLOCK_PENDING; 1270 } while (atomic_test_and_set((int32*)lock, newValue, oldValue) != (int32)oldValue); 1271 1272 return (newValue & ACPI_GLOCK_PENDING) == 0; 1273 } 1274 1275 1276 /* 1277 * Adapted from FreeBSD since the documentation of its intended impl 1278 * is lacking. 1279 * Release the global lock, returning whether there is a waiter pending. 1280 * If the BIOS set the pending bit, OSPM must notify the BIOS when it 1281 * releases the lock. 1282 */ 1283 int 1284 AcpiOsReleaseGlobalLock(volatile uint32_t *lock) 1285 { 1286 uint32 newValue; 1287 uint32 oldValue; 1288 1289 do { 1290 oldValue = *lock; 1291 newValue = oldValue & ~(ACPI_GLOCK_PENDING | ACPI_GLOCK_OWNED); 1292 } while (atomic_test_and_set((int32*)lock, newValue, oldValue) != (int32)oldValue); 1293 1294 return (oldValue & ACPI_GLOCK_PENDING) != 0; 1295 } 1296 1297 1298 ACPI_STATUS 1299 AcpiOsCreateMutex(ACPI_MUTEX* outHandle) 1300 { 1301 *outHandle = (ACPI_MUTEX) malloc(sizeof(mutex)); 1302 DEBUG_FUNCTION_F("result: %p", *outHandle); 1303 if (*outHandle == NULL) 1304 return AE_NO_MEMORY; 1305 1306 mutex_init(*outHandle, "acpi mutex"); 1307 return AE_OK; 1308 } 1309 1310 1311 void 1312 AcpiOsDeleteMutex(ACPI_MUTEX handle) 1313 { 1314 DEBUG_FUNCTION_F("mutex: %ld", (addr_t)handle); 1315 mutex_destroy(handle); 1316 free((void*)handle); 1317 } 1318 1319 1320 ACPI_STATUS 1321 AcpiOsAcquireMutex(ACPI_MUTEX handle, UINT16 timeout) 1322 { 1323 ACPI_STATUS result = AE_OK; 1324 DEBUG_FUNCTION_VF("mutex: %p; timeout: %u", handle, timeout); 1325 1326 if (timeout == ACPI_WAIT_FOREVER) { 1327 result = (mutex_lock(handle) == B_OK) ? AE_OK : AE_BAD_PARAMETER; 1328 } else if (timeout == ACPI_DO_NOT_WAIT) { 1329 result = (mutex_trylock(handle) == B_OK) ? AE_OK : AE_TIME; 1330 } else { 1331 switch (mutex_lock_with_timeout(handle, B_RELATIVE_TIMEOUT, 1332 (bigtime_t)timeout * 1000)) { 1333 case B_OK: 1334 result = AE_OK; 1335 break; 1336 case B_INTERRUPTED: 1337 case B_TIMED_OUT: 1338 case B_WOULD_BLOCK: 1339 result = AE_TIME; 1340 break; 1341 case B_BAD_VALUE: 1342 default: 1343 result = AE_BAD_PARAMETER; 1344 break; 1345 } 1346 } 1347 DEBUG_FUNCTION_VF("mutex: %p; timeout: %u result: %lu", 1348 handle, timeout, (uint32)result); 1349 return result; 1350 } 1351 1352 1353 void 1354 AcpiOsReleaseMutex(ACPI_MUTEX handle) 1355 { 1356 DEBUG_FUNCTION_F("mutex: %p", handle); 1357 mutex_unlock(handle); 1358 } 1359 1360 1361 /****************************************************************************** 1362 * 1363 * FUNCTION: AcpiOsWaitEventsComplete 1364 * 1365 * PARAMETERS: None 1366 * 1367 * RETURN: None 1368 * 1369 * DESCRIPTION: Wait for all asynchronous events to complete. This 1370 * implementation does nothing. 1371 * 1372 *****************************************************************************/ 1373 void 1374 AcpiOsWaitEventsComplete() 1375 { 1376 //TODO: FreeBSD See description. 1377 return; 1378 } 1379 1380 1381 /****************************************************************************** 1382 * 1383 * FUNCTION: AcpiOsEnterSleep 1384 * 1385 * PARAMETERS: SleepState - Which sleep state to enter 1386 * RegaValue - Register A value 1387 * RegbValue - Register B value 1388 * 1389 * RETURN: Status 1390 * 1391 * DESCRIPTION: A hook before writing sleep registers to enter the sleep 1392 * state. Return AE_CTRL_TERMINATE to skip further sleep register 1393 * writes. 1394 * 1395 *****************************************************************************/ 1396 1397 ACPI_STATUS 1398 AcpiOsEnterSleep ( 1399 UINT8 SleepState, 1400 UINT32 RegaValue, 1401 UINT32 RegbValue) 1402 { 1403 return (AE_OK); 1404 } 1405