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