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