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