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 144 ACPI_MODULE_NAME("Haiku ACPI Module") 145 146 #define _COMPONENT ACPI_OS_SERVICES 147 148 // verbosity level 0 = off, 1 = normal, 2 = all 149 #define DEBUG_OSHAIKU 0 150 151 #if DEBUG_OSHAIKU <= 0 152 // No debugging, do nothing 153 # define DEBUG_FUNCTION() 154 # define DEBUG_FUNCTION_F(x, y...) 155 # define DEBUG_FUNCTION_V() 156 # define DEBUG_FUNCTION_VF(x, y...) 157 #else 158 # define DEBUG_FUNCTION() \ 159 dprintf("acpi[%ld]: %s\n", find_thread(NULL), __PRETTY_FUNCTION__); 160 # define DEBUG_FUNCTION_F(x, y...) \ 161 dprintf("acpi[%ld]: %s(" x ")\n", find_thread(NULL), __PRETTY_FUNCTION__, y); 162 # if DEBUG_OSHAIKU == 1 163 // No verbose debugging, do nothing 164 # define DEBUG_FUNCTION_V() 165 # define DEBUG_FUNCTION_VF(x, y...) 166 # else 167 // Full debugging 168 # define DEBUG_FUNCTION_V() \ 169 dprintf("acpi[%ld]: %s\n", find_thread(NULL), __PRETTY_FUNCTION__); 170 # define DEBUG_FUNCTION_VF(x, y...) \ 171 dprintf("acpi[%ld]: %s(" x ")\n", find_thread(NULL), __PRETTY_FUNCTION__, y); 172 # endif 173 #endif 174 175 176 #ifdef _KERNEL_MODE 177 extern pci_module_info *gPCIManager; 178 extern dpc_module_info *gDPC; 179 extern void *gDPCHandle; 180 #endif 181 182 extern FILE *AcpiGbl_DebugFile; 183 FILE *AcpiGbl_OutputFile; 184 185 static ACPI_PHYSICAL_ADDRESS sACPIRoot = 0; 186 static void *sInterruptHandlerData[32]; 187 188 189 /****************************************************************************** 190 * 191 * FUNCTION: AcpiOsInitialize, AcpiOsTerminate 192 * 193 * PARAMETERS: None 194 * 195 * RETURN: Status 196 * 197 * DESCRIPTION: Init and terminate. Nothing to do. 198 * 199 *****************************************************************************/ 200 ACPI_STATUS 201 AcpiOsInitialize() 202 { 203 #ifndef _KERNEL_MODE 204 AcpiGbl_OutputFile = stdout; 205 #else 206 AcpiGbl_OutputFile = NULL; 207 #endif 208 DEBUG_FUNCTION(); 209 return AE_OK; 210 } 211 212 213 ACPI_STATUS 214 AcpiOsTerminate() 215 { 216 DEBUG_FUNCTION(); 217 return AE_OK; 218 } 219 220 221 /****************************************************************************** 222 * 223 * FUNCTION: AcpiOsGetRootPointer 224 * 225 * PARAMETERS: None 226 * 227 * RETURN: RSDP physical address 228 * 229 * DESCRIPTION: Gets the root pointer (RSDP) 230 * 231 *****************************************************************************/ 232 ACPI_PHYSICAL_ADDRESS 233 AcpiOsGetRootPointer() 234 { 235 #ifdef _KERNEL_MODE 236 ACPI_PHYSICAL_ADDRESS address; 237 ACPI_STATUS status = AE_OK; 238 DEBUG_FUNCTION(); 239 if (sACPIRoot == 0) { 240 sACPIRoot = (ACPI_PHYSICAL_ADDRESS)get_boot_item("ACPI_ROOT_POINTER", NULL); 241 if (sACPIRoot == 0) { 242 status = AcpiFindRootPointer(&address); 243 if (status == AE_OK) 244 sACPIRoot = address; 245 } 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 static char outputBuffer[1024]; 414 vsnprintf(outputBuffer, 1024, fmt, args); 415 dprintf("%s", outputBuffer); 416 #endif 417 } 418 419 420 /****************************************************************************** 421 * 422 * FUNCTION: AcpiOsGetLine 423 * 424 * PARAMETERS: fmt Standard printf format 425 * args Argument list 426 * 427 * RETURN: Actual bytes read 428 * 429 * DESCRIPTION: Formatted input with argument list pointer 430 * 431 *****************************************************************************/ 432 UINT32 433 AcpiOsGetLine(char *buffer) 434 { 435 uint32 i = 0; 436 437 #ifndef _KERNEL_MODE 438 uint8 temp; 439 440 for (i = 0; ; i++) { 441 scanf("%1c", &temp); 442 if (!temp || temp == '\n') 443 break; 444 445 buffer[i] = temp; 446 } 447 #endif 448 449 buffer[i] = 0; 450 DEBUG_FUNCTION_F("buffer: \"%s\"; result: %lu", buffer, i); 451 return i; 452 } 453 454 455 /****************************************************************************** 456 * 457 * FUNCTION: AcpiOsMapMemory 458 * 459 * PARAMETERS: where Physical address of memory to be mapped 460 * length How much memory to map 461 * 462 * RETURN: Pointer to mapped memory. Null on error. 463 * 464 * DESCRIPTION: Map physical memory into caller's address space 465 * 466 *****************************************************************************/ 467 void * 468 AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS where, ACPI_SIZE length) 469 { 470 #ifdef _KERNEL_MODE 471 void *there; 472 area_id area = map_physical_memory("acpi_physical_mem_area", where, length, 473 B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, &there); 474 475 DEBUG_FUNCTION_F("addr: 0x%08lx; length: %lu; mapped: %p; area: %ld", 476 (addr_t)where, (size_t)length, there, area); 477 if (area < 0) { 478 dprintf("ACPI: cannot map memory at 0x%08x, length %d\n", where, length); 479 return NULL; 480 } 481 return there; 482 #else 483 return NULL; 484 #endif 485 486 // return ACPI_TO_POINTER((ACPI_SIZE) where); 487 } 488 489 490 /****************************************************************************** 491 * 492 * FUNCTION: AcpiOsUnmapMemory 493 * 494 * PARAMETERS: where Logical address of memory to be unmapped 495 * length How much memory to unmap 496 * 497 * RETURN: None. 498 * 499 * DESCRIPTION: Delete a previously created mapping. Where and Length must 500 * correspond to a previous mapping exactly. 501 * 502 *****************************************************************************/ 503 void 504 AcpiOsUnmapMemory(void *where, ACPI_SIZE length) 505 { 506 DEBUG_FUNCTION_F("mapped: %p; length: %lu", where, (size_t)length); 507 delete_area(area_for(where)); 508 } 509 510 511 /****************************************************************************** 512 * 513 * FUNCTION: AcpiOsAllocate 514 * 515 * PARAMETERS: size Amount to allocate, in bytes 516 * 517 * RETURN: Pointer to the new allocation. Null on error. 518 * 519 * DESCRIPTION: Allocate memory. Algorithm is dependent on the OS. 520 * 521 *****************************************************************************/ 522 void * 523 AcpiOsAllocate(ACPI_SIZE size) 524 { 525 void *mem = (void *) malloc(size); 526 DEBUG_FUNCTION_VF("result: %p", mem); 527 return mem; 528 } 529 530 531 /****************************************************************************** 532 * 533 * FUNCTION: AcpiOsFree 534 * 535 * PARAMETERS: mem Pointer to previously allocated memory 536 * 537 * RETURN: None. 538 * 539 * DESCRIPTION: Free memory allocated via AcpiOsAllocate 540 * 541 *****************************************************************************/ 542 void 543 AcpiOsFree(void *mem) 544 { 545 DEBUG_FUNCTION_VF("mem: %p", mem); 546 free(mem); 547 } 548 549 550 /****************************************************************************** 551 * 552 * FUNCTION: AcpiOsCreateSemaphore 553 * 554 * PARAMETERS: initialUnits - Units to be assigned to the new semaphore 555 * outHandle - Where a handle will be returned 556 * 557 * RETURN: Status 558 * 559 * DESCRIPTION: Create an OS semaphore 560 * 561 *****************************************************************************/ 562 ACPI_STATUS 563 AcpiOsCreateSemaphore(UINT32 maxUnits, UINT32 initialUnits, 564 ACPI_SEMAPHORE *outHandle) 565 { 566 if (!outHandle) 567 return AE_BAD_PARAMETER; 568 569 *outHandle = create_sem(initialUnits, "acpi_sem"); 570 DEBUG_FUNCTION_F("max: %lu; count: %lu; result: %ld", 571 maxUnits, initialUnits, *outHandle); 572 573 if (*outHandle >= B_OK) 574 return AE_OK; 575 576 return *outHandle == B_BAD_VALUE ? AE_BAD_PARAMETER : AE_NO_MEMORY; 577 } 578 579 580 /****************************************************************************** 581 * 582 * FUNCTION: AcpiOsDeleteSemaphore 583 * 584 * PARAMETERS: handle - Handle returned by AcpiOsCreateSemaphore 585 * 586 * RETURN: Status 587 * 588 * DESCRIPTION: Delete an OS semaphore 589 * 590 *****************************************************************************/ 591 ACPI_STATUS 592 AcpiOsDeleteSemaphore(ACPI_SEMAPHORE handle) 593 { 594 DEBUG_FUNCTION_F("sem: %ld", handle); 595 return delete_sem(handle) == B_OK ? AE_OK : AE_BAD_PARAMETER; 596 } 597 598 599 /****************************************************************************** 600 * 601 * FUNCTION: AcpiOsWaitSemaphore 602 * 603 * PARAMETERS: handle - Handle returned by AcpiOsCreateSemaphore 604 * units - How many units to wait for 605 * timeout - How long to wait 606 * 607 * RETURN: Status 608 * 609 * DESCRIPTION: Wait for units 610 * 611 *****************************************************************************/ 612 ACPI_STATUS 613 AcpiOsWaitSemaphore(ACPI_SEMAPHORE handle, UINT32 units, UINT16 timeout) 614 { 615 ACPI_STATUS result = AE_OK; 616 DEBUG_FUNCTION_VF("sem: %ld; count: %lu; timeout: %u", 617 handle, units, timeout); 618 619 if (timeout == ACPI_WAIT_FOREVER) { 620 result = acquire_sem_etc(handle, units, 0, 0) 621 == B_OK ? AE_OK : AE_BAD_PARAMETER; 622 } else { 623 switch (acquire_sem_etc(handle, units, B_RELATIVE_TIMEOUT, 624 (bigtime_t)timeout * 1000)) { 625 case B_OK: 626 result = AE_OK; 627 break; 628 case B_INTERRUPTED: 629 case B_TIMED_OUT: 630 case B_WOULD_BLOCK: 631 result = AE_TIME; 632 break; 633 case B_BAD_VALUE: 634 default: 635 result = AE_BAD_PARAMETER; 636 break; 637 } 638 } 639 DEBUG_FUNCTION_VF("sem: %ld; count: %lu; timeout: %u result: %lu", 640 handle, units, timeout, (uint32)result); 641 return result; 642 } 643 644 645 /****************************************************************************** 646 * 647 * FUNCTION: AcpiOsSignalSemaphore 648 * 649 * PARAMETERS: handle - Handle returned by AcpiOsCreateSemaphore 650 * units - Number of units to send 651 * 652 * RETURN: Status 653 * 654 * DESCRIPTION: Send units 655 * 656 *****************************************************************************/ 657 ACPI_STATUS 658 AcpiOsSignalSemaphore(ACPI_SEMAPHORE handle, UINT32 units) 659 { 660 status_t result; 661 DEBUG_FUNCTION_VF("sem: %ld; count: %lu", handle, units); 662 // We can be called from interrupt handler, so don't reschedule 663 result = release_sem_etc(handle, units, B_DO_NOT_RESCHEDULE); 664 return result == B_OK ? AE_OK : AE_BAD_PARAMETER; 665 } 666 667 668 /****************************************************************************** 669 * 670 * FUNCTION: Spinlock interfaces 671 * 672 * DESCRIPTION: Map these interfaces to semaphore interfaces 673 * 674 *****************************************************************************/ 675 ACPI_STATUS 676 AcpiOsCreateLock(ACPI_SPINLOCK *outHandle) 677 { 678 *outHandle = (ACPI_SPINLOCK) malloc(sizeof(spinlock)); 679 DEBUG_FUNCTION_F("result: %p", *outHandle); 680 if (*outHandle == NULL) 681 return AE_NO_MEMORY; 682 683 B_INITIALIZE_SPINLOCK(*outHandle); 684 return AE_OK; 685 } 686 687 688 void 689 AcpiOsDeleteLock(ACPI_SPINLOCK handle) 690 { 691 DEBUG_FUNCTION(); 692 free((void*)handle); 693 } 694 695 696 ACPI_CPU_FLAGS 697 AcpiOsAcquireLock(ACPI_SPINLOCK handle) 698 { 699 cpu_status cpu; 700 DEBUG_FUNCTION_F("spinlock: %p", handle); 701 cpu = disable_interrupts(); 702 acquire_spinlock(handle); 703 return cpu; 704 } 705 706 707 void 708 AcpiOsReleaseLock(ACPI_SPINLOCK handle, ACPI_CPU_FLAGS flags) 709 { 710 release_spinlock(handle); 711 restore_interrupts(flags); 712 DEBUG_FUNCTION_F("spinlock: %p", handle); 713 } 714 715 716 /****************************************************************************** 717 * 718 * FUNCTION: AcpiOsInstallInterruptHandler 719 * 720 * PARAMETERS: interruptNumber Level handler should respond to. 721 * Isr Address of the ACPI interrupt handler 722 * ExceptPtr Where status is returned 723 * 724 * RETURN: Handle to the newly installed handler. 725 * 726 * DESCRIPTION: Install an interrupt handler. Used to install the ACPI 727 * OS-independent handler. 728 * 729 *****************************************************************************/ 730 UINT32 731 AcpiOsInstallInterruptHandler(UINT32 interruptNumber, 732 ACPI_OSD_HANDLER serviceRoutine, void *context) 733 { 734 status_t result; 735 DEBUG_FUNCTION_F("vector: %lu; handler: %p context %p", 736 interruptNumber, serviceRoutine, context); 737 738 #ifdef _KERNEL_MODE 739 // It so happens that the Haiku and ACPI-CA interrupt handler routines 740 // return the same values with the same meanings 741 sInterruptHandlerData[interruptNumber] = context; 742 result = install_io_interrupt_handler(interruptNumber, 743 (interrupt_handler)serviceRoutine, context, 0); 744 745 DEBUG_FUNCTION_F("vector: %lu; handler: %p context %p returned %d", 746 interruptNumber, serviceRoutine, context, result); 747 748 return result == B_OK ? AE_OK : AE_BAD_PARAMETER; 749 #else 750 return AE_BAD_PARAMETER; 751 #endif 752 } 753 754 755 /****************************************************************************** 756 * 757 * FUNCTION: AcpiOsRemoveInterruptHandler 758 * 759 * PARAMETERS: Handle Returned when handler was installed 760 * 761 * RETURN: Status 762 * 763 * DESCRIPTION: Uninstalls an interrupt handler. 764 * 765 *****************************************************************************/ 766 ACPI_STATUS 767 AcpiOsRemoveInterruptHandler(UINT32 interruptNumber, 768 ACPI_OSD_HANDLER serviceRoutine) 769 { 770 DEBUG_FUNCTION_F("vector: %lu; handler: %p", interruptNumber, 771 serviceRoutine); 772 #ifdef _KERNEL_MODE 773 remove_io_interrupt_handler(interruptNumber, 774 (interrupt_handler) serviceRoutine, 775 sInterruptHandlerData[interruptNumber]); 776 return AE_OK; 777 #else 778 return AE_ERROR; 779 #endif 780 } 781 782 783 /****************************************************************************** 784 * 785 * FUNCTION: AcpiOsExecute 786 * 787 * PARAMETERS: type - Type of execution 788 * function - Address of the function to execute 789 * context - Passed as a parameter to the function 790 * 791 * RETURN: Status. 792 * 793 * DESCRIPTION: Execute a new thread 794 * 795 *****************************************************************************/ 796 ACPI_STATUS 797 AcpiOsExecute(ACPI_EXECUTE_TYPE type, ACPI_OSD_EXEC_CALLBACK function, 798 void *context) 799 { 800 DEBUG_FUNCTION(); 801 /* TODO: Prioritize urgent? 802 switch (type) { 803 case OSL_GLOBAL_LOCK_HANDLER: 804 case OSL_NOTIFY_HANDLER: 805 case OSL_GPE_HANDLER: 806 case OSL_DEBUGGER_THREAD: 807 case OSL_EC_POLL_HANDLER: 808 case OSL_EC_BURST_HANDLER: 809 break; 810 } 811 */ 812 813 if (gDPC->queue_dpc(gDPCHandle, function, context) != B_OK) { 814 DEBUG_FUNCTION_F("Serious failure in AcpiOsExecute! function: %p", 815 function); 816 return AE_BAD_PARAMETER; 817 } 818 return AE_OK; 819 } 820 821 822 /****************************************************************************** 823 * 824 * FUNCTION: AcpiOsStall 825 * 826 * PARAMETERS: microseconds To sleep 827 * 828 * RETURN: Blocks until sleep is completed. 829 * 830 * DESCRIPTION: Sleep at microsecond granularity 831 * 832 *****************************************************************************/ 833 void 834 AcpiOsStall(UINT32 microseconds) 835 { 836 DEBUG_FUNCTION_F("microseconds: %lu", microseconds); 837 if (microseconds) 838 spin(microseconds); 839 } 840 841 842 /****************************************************************************** 843 * 844 * FUNCTION: AcpiOsSleep 845 * 846 * PARAMETERS: milliseconds To sleep 847 * 848 * RETURN: Blocks until sleep is completed. 849 * 850 * DESCRIPTION: Sleep at millisecond granularity 851 * 852 *****************************************************************************/ 853 void 854 AcpiOsSleep(ACPI_INTEGER milliseconds) 855 { 856 DEBUG_FUNCTION_F("milliseconds: %lu", milliseconds); 857 if (gKernelStartup) 858 spin(milliseconds * 1000); 859 else 860 snooze(milliseconds * 1000); 861 } 862 863 864 /****************************************************************************** 865 * 866 * FUNCTION: AcpiOsGetTimer 867 * 868 * PARAMETERS: None 869 * 870 * RETURN: Current time in 100 nanosecond units 871 * 872 * DESCRIPTION: Get the current system time 873 * 874 *****************************************************************************/ 875 UINT64 876 AcpiOsGetTimer() 877 { 878 DEBUG_FUNCTION(); 879 return system_time() * 10; 880 } 881 882 883 /****************************************************************************** 884 * 885 * FUNCTION: AcpiOsReadPciConfiguration 886 * 887 * PARAMETERS: pciId Seg/Bus/Dev 888 * reg Device Register 889 * value Buffer where value is placed 890 * width Number of bits 891 * 892 * RETURN: Status 893 * 894 * DESCRIPTION: Read data from PCI configuration space 895 * 896 *****************************************************************************/ 897 ACPI_STATUS 898 AcpiOsReadPciConfiguration(ACPI_PCI_ID *pciId, UINT32 reg, UINT64 *value, 899 UINT32 width) 900 { 901 #ifdef _KERNEL_MODE 902 DEBUG_FUNCTION(); 903 904 switch (width) { 905 case 8: 906 case 16: 907 case 32: 908 *value = gPCIManager->read_pci_config( 909 pciId->Bus, pciId->Device, pciId->Function, reg, width / 8); 910 break; 911 default: 912 return AE_ERROR; 913 } 914 return AE_OK; 915 #else 916 return AE_ERROR; 917 #endif 918 } 919 920 921 /****************************************************************************** 922 * 923 * FUNCTION: AcpiOsWritePciConfiguration 924 * 925 * PARAMETERS: pciId Seg/Bus/Dev 926 * reg Device Register 927 * value Value to be written 928 * width Number of bits 929 * 930 * RETURN: Status. 931 * 932 * DESCRIPTION: Write data to PCI configuration space 933 * 934 *****************************************************************************/ 935 ACPI_STATUS 936 AcpiOsWritePciConfiguration(ACPI_PCI_ID *pciId, UINT32 reg, 937 ACPI_INTEGER value, UINT32 width) 938 { 939 #ifdef _KERNEL_MODE 940 DEBUG_FUNCTION(); 941 gPCIManager->write_pci_config( 942 pciId->Bus, pciId->Device, pciId->Function, reg, width / 8, value); 943 return AE_OK; 944 #else 945 return AE_ERROR; 946 #endif 947 } 948 949 950 /****************************************************************************** 951 * 952 * FUNCTION: AcpiOsReadPort 953 * 954 * PARAMETERS: address Address of I/O port/register to read 955 * Value Where value is placed 956 * width Number of bits 957 * 958 * RETURN: Value read from port 959 * 960 * DESCRIPTION: Read data from an I/O port or register 961 * 962 *****************************************************************************/ 963 ACPI_STATUS 964 AcpiOsReadPort(ACPI_IO_ADDRESS address, UINT32 *value, UINT32 width) 965 { 966 #ifdef _KERNEL_MODE 967 DEBUG_FUNCTION_F("addr: 0x%08lx; width: %lu", (addr_t)address, width); 968 switch (width) { 969 case 8: 970 *value = gPCIManager->read_io_8(address); 971 break; 972 973 case 16: 974 *value = gPCIManager->read_io_16(address); 975 break; 976 977 case 32: 978 *value = gPCIManager->read_io_32(address); 979 break; 980 981 default: 982 return AE_ERROR; 983 } 984 985 return AE_OK; 986 #else 987 return AE_ERROR; 988 #endif 989 } 990 991 992 /****************************************************************************** 993 * 994 * FUNCTION: AcpiOsWritePort 995 * 996 * PARAMETERS: address Address of I/O port/register to write 997 * value Value to write 998 * width Number of bits 999 * 1000 * RETURN: None 1001 * 1002 * DESCRIPTION: Write data to an I/O port or register 1003 * 1004 *****************************************************************************/ 1005 ACPI_STATUS 1006 AcpiOsWritePort(ACPI_IO_ADDRESS address, UINT32 value, UINT32 width) 1007 { 1008 #ifdef _KERNEL_MODE 1009 DEBUG_FUNCTION_F("addr: 0x%08lx; value: %lu; width: %lu", 1010 (addr_t)address, value, width); 1011 switch (width) { 1012 case 8: 1013 gPCIManager->write_io_8(address, value); 1014 break; 1015 1016 case 16: 1017 gPCIManager->write_io_16(address,value); 1018 break; 1019 1020 case 32: 1021 gPCIManager->write_io_32(address,value); 1022 break; 1023 1024 default: 1025 return AE_ERROR; 1026 } 1027 1028 return AE_OK; 1029 #else 1030 return AE_ERROR; 1031 #endif 1032 } 1033 1034 1035 /****************************************************************************** 1036 * 1037 * FUNCTION: AcpiOsReadMemory 1038 * 1039 * PARAMETERS: address Physical Memory Address to read 1040 * value Where value is placed 1041 * width Number of bits 1042 * 1043 * RETURN: Value read from physical memory address 1044 * 1045 * DESCRIPTION: Read data from a physical memory address 1046 * 1047 *****************************************************************************/ 1048 ACPI_STATUS 1049 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 *value, UINT32 width) 1050 { 1051 #ifdef _KERNEL_MODE 1052 if (vm_memcpy_from_physical(value, (addr_t)address, width / 8, false) 1053 != B_OK) { 1054 return AE_ERROR; 1055 } 1056 return AE_OK; 1057 #else 1058 return AE_ERROR; 1059 #endif 1060 } 1061 1062 1063 /****************************************************************************** 1064 * 1065 * FUNCTION: AcpiOsWriteMemory 1066 * 1067 * PARAMETERS: address Physical Memory Address to write 1068 * value Value to write 1069 * width Number of bits 1070 * 1071 * RETURN: None 1072 * 1073 * DESCRIPTION: Write data to a physical memory address 1074 * 1075 *****************************************************************************/ 1076 ACPI_STATUS 1077 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 value, UINT32 width) 1078 { 1079 #ifdef _KERNEL_MODE 1080 if (vm_memcpy_to_physical((addr_t)address, &value, width / 8, false) 1081 != B_OK) { 1082 return AE_ERROR; 1083 } 1084 return AE_OK; 1085 #else 1086 return AE_ERROR; 1087 #endif 1088 } 1089 1090 1091 /****************************************************************************** 1092 * 1093 * FUNCTION: AcpiOsReadable 1094 * 1095 * PARAMETERS: pointer - Area to be verified 1096 * length - Size of area 1097 * 1098 * RETURN: TRUE if readable for entire length 1099 * 1100 * DESCRIPTION: Verify that a pointer is valid for reading 1101 * 1102 *****************************************************************************/ 1103 BOOLEAN 1104 AcpiOsReadable(void *pointer, ACPI_SIZE length) 1105 { 1106 #ifdef _KERNEL_MODE 1107 return true; 1108 #else 1109 area_id id; 1110 area_info info; 1111 1112 DEBUG_FUNCTION_F("addr: %p; length: %lu", pointer, (size_t)length); 1113 1114 id = area_for(pointer); 1115 if (id == B_ERROR) return false; 1116 if (get_area_info(id, &info) != B_OK) return false; 1117 return (info.protection & B_READ_AREA) != 0 && 1118 pointer + length <= info.address + info.ram_size; 1119 #endif 1120 } 1121 1122 1123 /****************************************************************************** 1124 * 1125 * FUNCTION: AcpiOsWritable 1126 * 1127 * PARAMETERS: pointer - Area to be verified 1128 * length - Size of area 1129 * 1130 * RETURN: TRUE if writable for entire length 1131 * 1132 * DESCRIPTION: Verify that a pointer is valid for writing 1133 * 1134 *****************************************************************************/ 1135 BOOLEAN 1136 AcpiOsWritable(void *pointer, ACPI_SIZE length) 1137 { 1138 #ifdef _KERNEL_MODE 1139 return true; 1140 #else 1141 area_id id; 1142 area_info info; 1143 1144 DEBUG_FUNCTION_F("addr: %p; length: %lu", pointer, (size_t)length); 1145 1146 id = area_for(pointer); 1147 if (id == B_ERROR) return false; 1148 if (get_area_info(id, &info) != B_OK) return false; 1149 return (info.protection & B_READ_AREA) != 0 && 1150 (info.protection & B_WRITE_AREA) != 0 && 1151 pointer + length <= info.address + info.ram_size; 1152 #endif 1153 } 1154 1155 1156 /****************************************************************************** 1157 * 1158 * FUNCTION: AcpiOsGetThreadId 1159 * 1160 * PARAMETERS: None 1161 * 1162 * RETURN: Id of the running thread 1163 * 1164 * DESCRIPTION: Get the Id of the current (running) thread 1165 * 1166 * NOTE: The environment header should contain this line: 1167 * #define ACPI_THREAD_ID pthread_t 1168 * 1169 *****************************************************************************/ 1170 ACPI_THREAD_ID 1171 AcpiOsGetThreadId() 1172 { 1173 thread_id thread = find_thread(NULL); 1174 // TODO: We arn't allowed threads with id 0, handle this case. 1175 // ACPI treats a 0 return as an error, 1176 // but we are thread 0 in early boot 1177 return thread; 1178 } 1179 1180 1181 /****************************************************************************** 1182 * 1183 * FUNCTION: AcpiOsSignal 1184 * 1185 * PARAMETERS: function ACPI CA signal function code 1186 * info Pointer to function-dependent structure 1187 * 1188 * RETURN: Status 1189 * 1190 * DESCRIPTION: Miscellaneous functions. Example implementation only. 1191 * 1192 *****************************************************************************/ 1193 ACPI_STATUS 1194 AcpiOsSignal(UINT32 function, void *info) 1195 { 1196 DEBUG_FUNCTION(); 1197 1198 switch (function) { 1199 case ACPI_SIGNAL_FATAL: 1200 #ifdef _KERNEL_MODE 1201 panic(info == NULL ? "AcpiOsSignal: fatal" : (const char*)info); 1202 break; 1203 #endif 1204 case ACPI_SIGNAL_BREAKPOINT: 1205 if (info != NULL) 1206 AcpiOsPrintf("AcpiOsBreakpoint: %s ****\n", info); 1207 else 1208 AcpiOsPrintf("At AcpiOsBreakpoint ****\n"); 1209 break; 1210 } 1211 1212 return AE_OK; 1213 } 1214 1215 1216 /* 1217 * Adapted from FreeBSD since the documentation of its intended impl 1218 * is lacking. 1219 * Section 5.2.10.1: global lock acquire/release functions */ 1220 #define GL_ACQUIRED (-1) 1221 #define GL_BUSY 0 1222 #define GL_BIT_PENDING 0x01 1223 #define GL_BIT_OWNED 0x02 1224 #define GL_BIT_MASK (GL_BIT_PENDING | GL_BIT_OWNED) 1225 1226 1227 /* 1228 * Adapted from FreeBSD since the documentation of its intended impl 1229 * is lacking. 1230 * Acquire the global lock. If busy, set the pending bit. The caller 1231 * will wait for notification from the BIOS that the lock is available 1232 * and then attempt to acquire it again. 1233 */ 1234 int 1235 AcpiOsAcquireGlobalLock(uint32 *lock) 1236 { 1237 uint32 newValue; 1238 uint32 oldValue; 1239 1240 do { 1241 oldValue = *lock; 1242 newValue = ((oldValue & ~GL_BIT_MASK) | GL_BIT_OWNED) | 1243 ((oldValue >> 1) & GL_BIT_PENDING); 1244 atomic_test_and_set((int32*)lock, newValue, oldValue); 1245 } while (*lock == oldValue); 1246 return ((newValue < GL_BIT_MASK) ? GL_ACQUIRED : GL_BUSY); 1247 } 1248 1249 1250 /* 1251 * Adapted from FreeBSD since the documentation of its intended impl 1252 * is lacking. 1253 * Release the global lock, returning whether there is a waiter pending. 1254 * If the BIOS set the pending bit, OSPM must notify the BIOS when it 1255 * releases the lock. 1256 */ 1257 int 1258 AcpiOsReleaseGlobalLock(uint32 *lock) 1259 { 1260 uint32 newValue; 1261 uint32 oldValue; 1262 1263 do { 1264 oldValue = *lock; 1265 newValue = oldValue & ~GL_BIT_MASK; 1266 atomic_test_and_set((int32*)lock, newValue, oldValue); 1267 } while (*lock == oldValue); 1268 return (oldValue & GL_BIT_PENDING); 1269 } 1270 1271 1272 ACPI_STATUS 1273 AcpiOsCreateMutex(ACPI_MUTEX* outHandle) 1274 { 1275 *outHandle = (ACPI_MUTEX) malloc(sizeof(mutex)); 1276 DEBUG_FUNCTION_F("result: %p", *outHandle); 1277 if (*outHandle == NULL) 1278 return AE_NO_MEMORY; 1279 1280 mutex_init(*outHandle, "acpi mutex"); 1281 return AE_OK; 1282 } 1283 1284 1285 void 1286 AcpiOsDeleteMutex(ACPI_MUTEX handle) 1287 { 1288 DEBUG_FUNCTION_F("mutex: %ld", handle); 1289 mutex_destroy(handle); 1290 free((void*)handle); 1291 } 1292 1293 1294 ACPI_STATUS 1295 AcpiOsAcquireMutex(ACPI_MUTEX handle, UINT16 timeout) 1296 { 1297 ACPI_STATUS result = AE_OK; 1298 DEBUG_FUNCTION_VF("mutex: %ld; timeout: %u", handle, timeout); 1299 1300 if (timeout == ACPI_WAIT_FOREVER) 1301 result = mutex_lock(handle) == B_OK ? AE_OK : AE_BAD_PARAMETER; 1302 else { 1303 switch (mutex_lock_with_timeout(handle, B_RELATIVE_TIMEOUT, 1304 (bigtime_t)timeout * 1000)) { 1305 case B_OK: 1306 result = AE_OK; 1307 break; 1308 case B_INTERRUPTED: 1309 case B_TIMED_OUT: 1310 case B_WOULD_BLOCK: 1311 result = AE_TIME; 1312 break; 1313 case B_BAD_VALUE: 1314 default: 1315 result = AE_BAD_PARAMETER; 1316 break; 1317 } 1318 } 1319 DEBUG_FUNCTION_VF("mutex: %ld; timeout: %u result: %lu", 1320 handle, timeout, (uint32)result); 1321 return result; 1322 } 1323 1324 1325 void 1326 AcpiOsReleaseMutex(ACPI_MUTEX handle) 1327 { 1328 DEBUG_FUNCTION_F("mutex: %p", handle); 1329 mutex_unlock(handle); 1330 } 1331 1332 1333 /****************************************************************************** 1334 * 1335 * FUNCTION: AcpiOsWaitEventsComplete 1336 * 1337 * PARAMETERS: None 1338 * 1339 * RETURN: None 1340 * 1341 * DESCRIPTION: Wait for all asynchronous events to complete. This 1342 * implementation does nothing. 1343 * 1344 *****************************************************************************/ 1345 void 1346 AcpiOsWaitEventsComplete() 1347 { 1348 //TODO: FreeBSD See description. 1349 return; 1350 } 1351