1/****************************************************************************** 2 * 3 * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch 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#define __EVREGION_C__ 118 119#include <contrib/dev/acpica/include/acpi.h> 120#include <contrib/dev/acpica/include/accommon.h> 121#include <contrib/dev/acpica/include/acevents.h> 122#include <contrib/dev/acpica/include/acnamesp.h> 123#include <contrib/dev/acpica/include/acinterp.h> 124 125#define _COMPONENT ACPI_EVENTS 126 ACPI_MODULE_NAME ("evregion") 127 128 129/* Local prototypes */ 130 131static BOOLEAN 132AcpiEvHasDefaultHandler ( 133 ACPI_NAMESPACE_NODE *Node, 134 ACPI_ADR_SPACE_TYPE SpaceId); 135 136static ACPI_STATUS 137AcpiEvRegRun ( 138 ACPI_HANDLE ObjHandle, 139 UINT32 Level, 140 void *Context, 141 void **ReturnValue); 142 143static ACPI_STATUS 144AcpiEvInstallHandler ( 145 ACPI_HANDLE ObjHandle, 146 UINT32 Level, 147 void *Context, 148 void **ReturnValue); 149 150/* These are the address spaces that will get default handlers */ 151 152#define ACPI_NUM_DEFAULT_SPACES 4 153 154static UINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] = 155{ 156 ACPI_ADR_SPACE_SYSTEM_MEMORY, 157 ACPI_ADR_SPACE_SYSTEM_IO, 158 ACPI_ADR_SPACE_PCI_CONFIG, 159 ACPI_ADR_SPACE_DATA_TABLE 160}; 161 162 163/******************************************************************************* 164 * 165 * FUNCTION: AcpiEvInstallRegionHandlers 166 * 167 * PARAMETERS: None 168 * 169 * RETURN: Status 170 * 171 * DESCRIPTION: Installs the core subsystem default address space handlers. 172 * 173 ******************************************************************************/ 174 175ACPI_STATUS 176AcpiEvInstallRegionHandlers ( 177 void) 178{ 179 ACPI_STATUS Status; 180 UINT32 i; 181 182 183 ACPI_FUNCTION_TRACE (EvInstallRegionHandlers); 184 185 186 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 187 if (ACPI_FAILURE (Status)) 188 { 189 return_ACPI_STATUS (Status); 190 } 191 192 /* 193 * All address spaces (PCI Config, EC, SMBus) are scope dependent and 194 * registration must occur for a specific device. 195 * 196 * In the case of the system memory and IO address spaces there is 197 * currently no device associated with the address space. For these we 198 * use the root. 199 * 200 * We install the default PCI config space handler at the root so that 201 * this space is immediately available even though the we have not 202 * enumerated all the PCI Root Buses yet. This is to conform to the ACPI 203 * specification which states that the PCI config space must be always 204 * available -- even though we are nowhere near ready to find the PCI root 205 * buses at this point. 206 * 207 * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler 208 * has already been installed (via AcpiInstallAddressSpaceHandler). 209 * Similar for AE_SAME_HANDLER. 210 */ 211 for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) 212 { 213 Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode, 214 AcpiGbl_DefaultAddressSpaces[i], 215 ACPI_DEFAULT_HANDLER, NULL, NULL); 216 switch (Status) 217 { 218 case AE_OK: 219 case AE_SAME_HANDLER: 220 case AE_ALREADY_EXISTS: 221 222 /* These exceptions are all OK */ 223 224 Status = AE_OK; 225 break; 226 227 default: 228 229 goto UnlockAndExit; 230 } 231 } 232 233UnlockAndExit: 234 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 235 return_ACPI_STATUS (Status); 236} 237 238 239/******************************************************************************* 240 * 241 * FUNCTION: AcpiEvHasDefaultHandler 242 * 243 * PARAMETERS: Node - Namespace node for the device 244 * SpaceId - The address space ID 245 * 246 * RETURN: TRUE if default handler is installed, FALSE otherwise 247 * 248 * DESCRIPTION: Check if the default handler is installed for the requested 249 * space ID. 250 * 251 ******************************************************************************/ 252 253static BOOLEAN 254AcpiEvHasDefaultHandler ( 255 ACPI_NAMESPACE_NODE *Node, 256 ACPI_ADR_SPACE_TYPE SpaceId) 257{ 258 ACPI_OPERAND_OBJECT *ObjDesc; 259 ACPI_OPERAND_OBJECT *HandlerObj; 260 261 262 /* Must have an existing internal object */ 263 264 ObjDesc = AcpiNsGetAttachedObject (Node); 265 if (ObjDesc) 266 { 267 HandlerObj = ObjDesc->Device.Handler; 268 269 /* Walk the linked list of handlers for this object */ 270 271 while (HandlerObj) 272 { 273 if (HandlerObj->AddressSpace.SpaceId == SpaceId) 274 { 275 if (HandlerObj->AddressSpace.HandlerFlags & 276 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) 277 { 278 return (TRUE); 279 } 280 } 281 282 HandlerObj = HandlerObj->AddressSpace.Next; 283 } 284 } 285 286 return (FALSE); 287} 288 289 290/******************************************************************************* 291 * 292 * FUNCTION: AcpiEvInitializeOpRegions 293 * 294 * PARAMETERS: None 295 * 296 * RETURN: Status 297 * 298 * DESCRIPTION: Execute _REG methods for all Operation Regions that have 299 * an installed default region handler. 300 * 301 ******************************************************************************/ 302 303ACPI_STATUS 304AcpiEvInitializeOpRegions ( 305 void) 306{ 307 ACPI_STATUS Status; 308 UINT32 i; 309 310 311 ACPI_FUNCTION_TRACE (EvInitializeOpRegions); 312 313 314 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 315 if (ACPI_FAILURE (Status)) 316 { 317 return_ACPI_STATUS (Status); 318 } 319 320 /* Run the _REG methods for OpRegions in each default address space */ 321 322 for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) 323 { 324 /* 325 * Make sure the installed handler is the DEFAULT handler. If not the 326 * default, the _REG methods will have already been run (when the 327 * handler was installed) 328 */ 329 if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode, 330 AcpiGbl_DefaultAddressSpaces[i])) 331 { 332 Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode, 333 AcpiGbl_DefaultAddressSpaces[i]); 334 } 335 } 336 337 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 338 return_ACPI_STATUS (Status); 339} 340 341 342/******************************************************************************* 343 * 344 * FUNCTION: AcpiEvExecuteRegMethod 345 * 346 * PARAMETERS: RegionObj - Region object 347 * Function - Passed to _REG: On (1) or Off (0) 348 * 349 * RETURN: Status 350 * 351 * DESCRIPTION: Execute _REG method for a region 352 * 353 ******************************************************************************/ 354 355ACPI_STATUS 356AcpiEvExecuteRegMethod ( 357 ACPI_OPERAND_OBJECT *RegionObj, 358 UINT32 Function) 359{ 360 ACPI_EVALUATE_INFO *Info; 361 ACPI_OPERAND_OBJECT *Args[3]; 362 ACPI_OPERAND_OBJECT *RegionObj2; 363 ACPI_STATUS Status; 364 365 366 ACPI_FUNCTION_TRACE (EvExecuteRegMethod); 367 368 369 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 370 if (!RegionObj2) 371 { 372 return_ACPI_STATUS (AE_NOT_EXIST); 373 } 374 375 if (RegionObj2->Extra.Method_REG == NULL) 376 { 377 return_ACPI_STATUS (AE_OK); 378 } 379 380 /* Allocate and initialize the evaluation information block */ 381 382 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 383 if (!Info) 384 { 385 return_ACPI_STATUS (AE_NO_MEMORY); 386 } 387 388 Info->PrefixNode = RegionObj2->Extra.Method_REG; 389 Info->Pathname = NULL; 390 Info->Parameters = Args; 391 Info->Flags = ACPI_IGNORE_RETURN_VALUE; 392 393 /* 394 * The _REG method has two arguments: 395 * 396 * Arg0 - Integer: 397 * Operation region space ID Same value as RegionObj->Region.SpaceId 398 * 399 * Arg1 - Integer: 400 * connection status 1 for connecting the handler, 0 for disconnecting 401 * the handler (Passed as a parameter) 402 */ 403 Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId); 404 if (!Args[0]) 405 { 406 Status = AE_NO_MEMORY; 407 goto Cleanup1; 408 } 409 410 Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function); 411 if (!Args[1]) 412 { 413 Status = AE_NO_MEMORY; 414 goto Cleanup2; 415 } 416 417 Args[2] = NULL; /* Terminate list */ 418 419 /* Execute the method, no return value */ 420 421 ACPI_DEBUG_EXEC ( 422 AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL)); 423 424 Status = AcpiNsEvaluate (Info); 425 AcpiUtRemoveReference (Args[1]); 426 427Cleanup2: 428 AcpiUtRemoveReference (Args[0]); 429 430Cleanup1: 431 ACPI_FREE (Info); 432 return_ACPI_STATUS (Status); 433} 434 435 436/******************************************************************************* 437 * 438 * FUNCTION: AcpiEvAddressSpaceDispatch 439 * 440 * PARAMETERS: RegionObj - Internal region object 441 * Function - Read or Write operation 442 * RegionOffset - Where in the region to read or write 443 * BitWidth - Field width in bits (8, 16, 32, or 64) 444 * Value - Pointer to in or out value, must be 445 * full 64-bit ACPI_INTEGER 446 * 447 * RETURN: Status 448 * 449 * DESCRIPTION: Dispatch an address space or operation region access to 450 * a previously installed handler. 451 * 452 ******************************************************************************/ 453 454ACPI_STATUS 455AcpiEvAddressSpaceDispatch ( 456 ACPI_OPERAND_OBJECT *RegionObj, 457 UINT32 Function, 458 UINT32 RegionOffset, 459 UINT32 BitWidth, 460 ACPI_INTEGER *Value) 461{ 462 ACPI_STATUS Status; 463 ACPI_ADR_SPACE_HANDLER Handler; 464 ACPI_ADR_SPACE_SETUP RegionSetup; 465 ACPI_OPERAND_OBJECT *HandlerDesc; 466 ACPI_OPERAND_OBJECT *RegionObj2; 467 void *RegionContext = NULL; 468 469 470 ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch); 471 472 473 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 474 if (!RegionObj2) 475 { 476 return_ACPI_STATUS (AE_NOT_EXIST); 477 } 478 479 /* Ensure that there is a handler associated with this region */ 480 481 HandlerDesc = RegionObj->Region.Handler; 482 if (!HandlerDesc) 483 { 484 ACPI_ERROR ((AE_INFO, 485 "No handler for Region [%4.4s] (%p) [%s]", 486 AcpiUtGetNodeName (RegionObj->Region.Node), 487 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 488 489 return_ACPI_STATUS (AE_NOT_EXIST); 490 } 491 492 /* 493 * It may be the case that the region has never been initialized. 494 * Some types of regions require special init code 495 */ 496 if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) 497 { 498 /* This region has not been initialized yet, do it */ 499 500 RegionSetup = HandlerDesc->AddressSpace.Setup; 501 if (!RegionSetup) 502 { 503 /* No initialization routine, exit with error */ 504 505 ACPI_ERROR ((AE_INFO, 506 "No init routine for region(%p) [%s]", 507 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 508 return_ACPI_STATUS (AE_NOT_EXIST); 509 } 510 511 /* 512 * We must exit the interpreter because the region setup will 513 * potentially execute control methods (for example, the _REG method 514 * for this region) 515 */ 516 AcpiExExitInterpreter (); 517 518 Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE, 519 HandlerDesc->AddressSpace.Context, &RegionContext); 520 521 /* Re-enter the interpreter */ 522 523 AcpiExEnterInterpreter (); 524 525 /* Check for failure of the Region Setup */ 526 527 if (ACPI_FAILURE (Status)) 528 { 529 ACPI_EXCEPTION ((AE_INFO, Status, 530 "During region initialization: [%s]", 531 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 532 return_ACPI_STATUS (Status); 533 } 534 535 /* Region initialization may have been completed by RegionSetup */ 536 537 if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) 538 { 539 RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE; 540 541 if (RegionObj2->Extra.RegionContext) 542 { 543 /* The handler for this region was already installed */ 544 545 ACPI_FREE (RegionContext); 546 } 547 else 548 { 549 /* 550 * Save the returned context for use in all accesses to 551 * this particular region 552 */ 553 RegionObj2->Extra.RegionContext = RegionContext; 554 } 555 } 556 } 557 558 /* We have everything we need, we can invoke the address space handler */ 559 560 Handler = HandlerDesc->AddressSpace.Handler; 561 562 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 563 "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", 564 &RegionObj->Region.Handler->AddressSpace, Handler, 565 ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset), 566 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 567 568 if (!(HandlerDesc->AddressSpace.HandlerFlags & 569 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) 570 { 571 /* 572 * For handlers other than the default (supplied) handlers, we must 573 * exit the interpreter because the handler *might* block -- we don't 574 * know what it will do, so we can't hold the lock on the intepreter. 575 */ 576 AcpiExExitInterpreter(); 577 } 578 579 /* Call the handler */ 580 581 Status = Handler (Function, 582 (RegionObj->Region.Address + RegionOffset), BitWidth, Value, 583 HandlerDesc->AddressSpace.Context, RegionObj2->Extra.RegionContext); 584 585 if (ACPI_FAILURE (Status)) 586 { 587 ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]", 588 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 589 } 590 591 if (!(HandlerDesc->AddressSpace.HandlerFlags & 592 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) 593 { 594 /* 595 * We just returned from a non-default handler, we must re-enter the 596 * interpreter 597 */ 598 AcpiExEnterInterpreter (); 599 } 600 601 return_ACPI_STATUS (Status); 602} 603 604 605/******************************************************************************* 606 * 607 * FUNCTION: AcpiEvDetachRegion 608 * 609 * PARAMETERS: RegionObj - Region Object 610 * AcpiNsIsLocked - Namespace Region Already Locked? 611 * 612 * RETURN: None 613 * 614 * DESCRIPTION: Break the association between the handler and the region 615 * this is a two way association. 616 * 617 ******************************************************************************/ 618 619void 620AcpiEvDetachRegion( 621 ACPI_OPERAND_OBJECT *RegionObj, 622 BOOLEAN AcpiNsIsLocked) 623{ 624 ACPI_OPERAND_OBJECT *HandlerObj; 625 ACPI_OPERAND_OBJECT *ObjDesc; 626 ACPI_OPERAND_OBJECT **LastObjPtr; 627 ACPI_ADR_SPACE_SETUP RegionSetup; 628 void **RegionContext; 629 ACPI_OPERAND_OBJECT *RegionObj2; 630 ACPI_STATUS Status; 631 632 633 ACPI_FUNCTION_TRACE (EvDetachRegion); 634 635 636 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 637 if (!RegionObj2) 638 { 639 return_VOID; 640 } 641 RegionContext = &RegionObj2->Extra.RegionContext; 642 643 /* Get the address handler from the region object */ 644 645 HandlerObj = RegionObj->Region.Handler; 646 if (!HandlerObj) 647 { 648 /* This region has no handler, all done */ 649 650 return_VOID; 651 } 652 653 /* Find this region in the handler's list */ 654 655 ObjDesc = HandlerObj->AddressSpace.RegionList; 656 LastObjPtr = &HandlerObj->AddressSpace.RegionList; 657 658 while (ObjDesc) 659 { 660 /* Is this the correct Region? */ 661 662 if (ObjDesc == RegionObj) 663 { 664 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 665 "Removing Region %p from address handler %p\n", 666 RegionObj, HandlerObj)); 667 668 /* This is it, remove it from the handler's list */ 669 670 *LastObjPtr = ObjDesc->Region.Next; 671 ObjDesc->Region.Next = NULL; /* Must clear field */ 672 673 if (AcpiNsIsLocked) 674 { 675 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 676 if (ACPI_FAILURE (Status)) 677 { 678 return_VOID; 679 } 680 } 681 682 /* Now stop region accesses by executing the _REG method */ 683 684 Status = AcpiEvExecuteRegMethod (RegionObj, 0); 685 if (ACPI_FAILURE (Status)) 686 { 687 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]", 688 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 689 } 690 691 if (AcpiNsIsLocked) 692 { 693 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 694 if (ACPI_FAILURE (Status)) 695 { 696 return_VOID; 697 } 698 } 699 700 /* 701 * If the region has been activated, call the setup handler with 702 * the deactivate notification 703 */ 704 if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) 705 { 706 RegionSetup = HandlerObj->AddressSpace.Setup; 707 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE, 708 HandlerObj->AddressSpace.Context, RegionContext); 709 710 /* Init routine may fail, Just ignore errors */ 711 712 if (ACPI_FAILURE (Status)) 713 { 714 ACPI_EXCEPTION ((AE_INFO, Status, 715 "from region handler - deactivate, [%s]", 716 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 717 } 718 719 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE); 720 } 721 722 /* 723 * Remove handler reference in the region 724 * 725 * NOTE: this doesn't mean that the region goes away, the region 726 * is just inaccessible as indicated to the _REG method 727 * 728 * If the region is on the handler's list, this must be the 729 * region's handler 730 */ 731 RegionObj->Region.Handler = NULL; 732 AcpiUtRemoveReference (HandlerObj); 733 734 return_VOID; 735 } 736 737 /* Walk the linked list of handlers */ 738 739 LastObjPtr = &ObjDesc->Region.Next; 740 ObjDesc = ObjDesc->Region.Next; 741 } 742 743 /* If we get here, the region was not in the handler's region list */ 744 745 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 746 "Cannot remove region %p from address handler %p\n", 747 RegionObj, HandlerObj)); 748 749 return_VOID; 750} 751 752 753/******************************************************************************* 754 * 755 * FUNCTION: AcpiEvAttachRegion 756 * 757 * PARAMETERS: HandlerObj - Handler Object 758 * RegionObj - Region Object 759 * AcpiNsIsLocked - Namespace Region Already Locked? 760 * 761 * RETURN: None 762 * 763 * DESCRIPTION: Create the association between the handler and the region 764 * this is a two way association. 765 * 766 ******************************************************************************/ 767 768ACPI_STATUS 769AcpiEvAttachRegion ( 770 ACPI_OPERAND_OBJECT *HandlerObj, 771 ACPI_OPERAND_OBJECT *RegionObj, 772 BOOLEAN AcpiNsIsLocked) 773{ 774 775 ACPI_FUNCTION_TRACE (EvAttachRegion); 776 777 778 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 779 "Adding Region [%4.4s] %p to address handler %p [%s]\n", 780 AcpiUtGetNodeName (RegionObj->Region.Node), 781 RegionObj, HandlerObj, 782 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 783 784 /* Link this region to the front of the handler's list */ 785 786 RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList; 787 HandlerObj->AddressSpace.RegionList = RegionObj; 788 789 /* Install the region's handler */ 790 791 if (RegionObj->Region.Handler) 792 { 793 return_ACPI_STATUS (AE_ALREADY_EXISTS); 794 } 795 796 RegionObj->Region.Handler = HandlerObj; 797 AcpiUtAddReference (HandlerObj); 798 799 return_ACPI_STATUS (AE_OK); 800} 801 802 803/******************************************************************************* 804 * 805 * FUNCTION: AcpiEvInstallHandler 806 * 807 * PARAMETERS: WalkNamespace callback 808 * 809 * DESCRIPTION: This routine installs an address handler into objects that are 810 * of type Region or Device. 811 * 812 * If the Object is a Device, and the device has a handler of 813 * the same type then the search is terminated in that branch. 814 * 815 * This is because the existing handler is closer in proximity 816 * to any more regions than the one we are trying to install. 817 * 818 ******************************************************************************/ 819 820static ACPI_STATUS 821AcpiEvInstallHandler ( 822 ACPI_HANDLE ObjHandle, 823 UINT32 Level, 824 void *Context, 825 void **ReturnValue) 826{ 827 ACPI_OPERAND_OBJECT *HandlerObj; 828 ACPI_OPERAND_OBJECT *NextHandlerObj; 829 ACPI_OPERAND_OBJECT *ObjDesc; 830 ACPI_NAMESPACE_NODE *Node; 831 ACPI_STATUS Status; 832 833 834 ACPI_FUNCTION_NAME (EvInstallHandler); 835 836 837 HandlerObj = (ACPI_OPERAND_OBJECT *) Context; 838 839 /* Parameter validation */ 840 841 if (!HandlerObj) 842 { 843 return (AE_OK); 844 } 845 846 /* Convert and validate the device handle */ 847
|
849 if (!Node) 850 { 851 return (AE_BAD_PARAMETER); 852 } 853 854 /* 855 * We only care about regions and objects that are allowed to have 856 * address space handlers 857 */ 858 if ((Node->Type != ACPI_TYPE_DEVICE) && 859 (Node->Type != ACPI_TYPE_REGION) && 860 (Node != AcpiGbl_RootNode)) 861 { 862 return (AE_OK); 863 } 864 865 /* Check for an existing internal object */ 866 867 ObjDesc = AcpiNsGetAttachedObject (Node); 868 if (!ObjDesc) 869 { 870 /* No object, just exit */ 871 872 return (AE_OK); 873 } 874 875 /* Devices are handled different than regions */ 876 877 if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE) 878 { 879 /* Check if this Device already has a handler for this address space */ 880 881 NextHandlerObj = ObjDesc->Device.Handler; 882 while (NextHandlerObj) 883 { 884 /* Found a handler, is it for the same address space? */ 885 886 if (NextHandlerObj->AddressSpace.SpaceId == 887 HandlerObj->AddressSpace.SpaceId) 888 { 889 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 890 "Found handler for region [%s] in device %p(%p) " 891 "handler %p\n", 892 AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId), 893 ObjDesc, NextHandlerObj, HandlerObj)); 894 895 /* 896 * Since the object we found it on was a device, then it 897 * means that someone has already installed a handler for 898 * the branch of the namespace from this device on. Just 899 * bail out telling the walk routine to not traverse this 900 * branch. This preserves the scoping rule for handlers. 901 */ 902 return (AE_CTRL_DEPTH); 903 } 904 905 /* Walk the linked list of handlers attached to this device */ 906 907 NextHandlerObj = NextHandlerObj->AddressSpace.Next; 908 } 909 910 /* 911 * As long as the device didn't have a handler for this space we 912 * don't care about it. We just ignore it and proceed. 913 */ 914 return (AE_OK); 915 } 916 917 /* Object is a Region */ 918 919 if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId) 920 { 921 /* This region is for a different address space, just ignore it */ 922 923 return (AE_OK); 924 } 925 926 /* 927 * Now we have a region and it is for the handler's address space type. 928 * 929 * First disconnect region for any previous handler (if any) 930 */ 931 AcpiEvDetachRegion (ObjDesc, FALSE); 932 933 /* Connect the region to the new handler */ 934 935 Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE); 936 return (Status); 937} 938 939 940/******************************************************************************* 941 * 942 * FUNCTION: AcpiEvInstallSpaceHandler 943 * 944 * PARAMETERS: Node - Namespace node for the device 945 * SpaceId - The address space ID 946 * Handler - Address of the handler 947 * Setup - Address of the setup function 948 * Context - Value passed to the handler on each access 949 * 950 * RETURN: Status 951 * 952 * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId. 953 * Assumes namespace is locked 954 * 955 ******************************************************************************/ 956 957ACPI_STATUS 958AcpiEvInstallSpaceHandler ( 959 ACPI_NAMESPACE_NODE *Node, 960 ACPI_ADR_SPACE_TYPE SpaceId, 961 ACPI_ADR_SPACE_HANDLER Handler, 962 ACPI_ADR_SPACE_SETUP Setup, 963 void *Context) 964{ 965 ACPI_OPERAND_OBJECT *ObjDesc; 966 ACPI_OPERAND_OBJECT *HandlerObj; 967 ACPI_STATUS Status; 968 ACPI_OBJECT_TYPE Type; 969 UINT8 Flags = 0; 970 971 972 ACPI_FUNCTION_TRACE (EvInstallSpaceHandler); 973 974 975 /* 976 * This registration is valid for only the types below and the root. This 977 * is where the default handlers get placed. 978 */ 979 if ((Node->Type != ACPI_TYPE_DEVICE) && 980 (Node->Type != ACPI_TYPE_PROCESSOR) && 981 (Node->Type != ACPI_TYPE_THERMAL) && 982 (Node != AcpiGbl_RootNode)) 983 { 984 Status = AE_BAD_PARAMETER; 985 goto UnlockAndExit; 986 } 987 988 if (Handler == ACPI_DEFAULT_HANDLER) 989 { 990 Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; 991 992 switch (SpaceId) 993 { 994 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 995 Handler = AcpiExSystemMemorySpaceHandler; 996 Setup = AcpiEvSystemMemoryRegionSetup; 997 break; 998 999 case ACPI_ADR_SPACE_SYSTEM_IO: 1000 Handler = AcpiExSystemIoSpaceHandler; 1001 Setup = AcpiEvIoSpaceRegionSetup; 1002 break; 1003 1004 case ACPI_ADR_SPACE_PCI_CONFIG: 1005 Handler = AcpiExPciConfigSpaceHandler; 1006 Setup = AcpiEvPciConfigRegionSetup; 1007 break; 1008 1009 case ACPI_ADR_SPACE_CMOS: 1010 Handler = AcpiExCmosSpaceHandler; 1011 Setup = AcpiEvCmosRegionSetup; 1012 break; 1013 1014 case ACPI_ADR_SPACE_PCI_BAR_TARGET: 1015 Handler = AcpiExPciBarSpaceHandler; 1016 Setup = AcpiEvPciBarRegionSetup; 1017 break; 1018 1019 case ACPI_ADR_SPACE_DATA_TABLE: 1020 Handler = AcpiExDataTableSpaceHandler; 1021 Setup = NULL; 1022 break; 1023 1024 default: 1025 Status = AE_BAD_PARAMETER; 1026 goto UnlockAndExit; 1027 } 1028 } 1029 1030 /* If the caller hasn't specified a setup routine, use the default */ 1031 1032 if (!Setup) 1033 { 1034 Setup = AcpiEvDefaultRegionSetup; 1035 } 1036 1037 /* Check for an existing internal object */ 1038 1039 ObjDesc = AcpiNsGetAttachedObject (Node); 1040 if (ObjDesc) 1041 { 1042 /* 1043 * The attached device object already exists. Make sure the handler 1044 * is not already installed. 1045 */ 1046 HandlerObj = ObjDesc->Device.Handler; 1047 1048 /* Walk the handler list for this device */ 1049 1050 while (HandlerObj) 1051 { 1052 /* Same SpaceId indicates a handler already installed */ 1053 1054 if (HandlerObj->AddressSpace.SpaceId == SpaceId) 1055 { 1056 if (HandlerObj->AddressSpace.Handler == Handler) 1057 { 1058 /* 1059 * It is (relatively) OK to attempt to install the SAME 1060 * handler twice. This can easily happen with the 1061 * PCI_Config space. 1062 */ 1063 Status = AE_SAME_HANDLER; 1064 goto UnlockAndExit; 1065 } 1066 else 1067 { 1068 /* A handler is already installed */ 1069 1070 Status = AE_ALREADY_EXISTS; 1071 } 1072 goto UnlockAndExit; 1073 } 1074 1075 /* Walk the linked list of handlers */ 1076 1077 HandlerObj = HandlerObj->AddressSpace.Next; 1078 } 1079 } 1080 else 1081 { 1082 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 1083 "Creating object on Device %p while installing handler\n", Node)); 1084 1085 /* ObjDesc does not exist, create one */ 1086 1087 if (Node->Type == ACPI_TYPE_ANY) 1088 { 1089 Type = ACPI_TYPE_DEVICE; 1090 } 1091 else 1092 { 1093 Type = Node->Type; 1094 } 1095 1096 ObjDesc = AcpiUtCreateInternalObject (Type); 1097 if (!ObjDesc) 1098 { 1099 Status = AE_NO_MEMORY; 1100 goto UnlockAndExit; 1101 } 1102 1103 /* Init new descriptor */ 1104 1105 ObjDesc->Common.Type = (UINT8) Type; 1106 1107 /* Attach the new object to the Node */ 1108 1109 Status = AcpiNsAttachObject (Node, ObjDesc, Type); 1110 1111 /* Remove local reference to the object */ 1112 1113 AcpiUtRemoveReference (ObjDesc); 1114 1115 if (ACPI_FAILURE (Status)) 1116 { 1117 goto UnlockAndExit; 1118 } 1119 } 1120 1121 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 1122 "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", 1123 AcpiUtGetRegionName (SpaceId), SpaceId, 1124 AcpiUtGetNodeName (Node), Node, ObjDesc)); 1125 1126 /* 1127 * Install the handler 1128 * 1129 * At this point there is no existing handler. Just allocate the object 1130 * for the handler and link it into the list. 1131 */ 1132 HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER); 1133 if (!HandlerObj) 1134 { 1135 Status = AE_NO_MEMORY; 1136 goto UnlockAndExit; 1137 } 1138 1139 /* Init handler obj */ 1140 1141 HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId; 1142 HandlerObj->AddressSpace.HandlerFlags = Flags; 1143 HandlerObj->AddressSpace.RegionList = NULL; 1144 HandlerObj->AddressSpace.Node = Node; 1145 HandlerObj->AddressSpace.Handler = Handler; 1146 HandlerObj->AddressSpace.Context = Context; 1147 HandlerObj->AddressSpace.Setup = Setup; 1148 1149 /* Install at head of Device.AddressSpace list */ 1150 1151 HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler; 1152 1153 /* 1154 * The Device object is the first reference on the HandlerObj. 1155 * Each region that uses the handler adds a reference. 1156 */ 1157 ObjDesc->Device.Handler = HandlerObj; 1158 1159 /* 1160 * Walk the namespace finding all of the regions this 1161 * handler will manage. 1162 * 1163 * Start at the device and search the branch toward 1164 * the leaf nodes until either the leaf is encountered or 1165 * a device is detected that has an address handler of the 1166 * same type. 1167 * 1168 * In either case, back up and search down the remainder 1169 * of the branch 1170 */ 1171 Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, 1172 ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL, 1173 HandlerObj, NULL); 1174 1175UnlockAndExit: 1176 return_ACPI_STATUS (Status); 1177} 1178 1179 1180/******************************************************************************* 1181 * 1182 * FUNCTION: AcpiEvExecuteRegMethods 1183 * 1184 * PARAMETERS: Node - Namespace node for the device 1185 * SpaceId - The address space ID 1186 * 1187 * RETURN: Status 1188 * 1189 * DESCRIPTION: Run all _REG methods for the input Space ID; 1190 * Note: assumes namespace is locked, or system init time. 1191 * 1192 ******************************************************************************/ 1193 1194ACPI_STATUS 1195AcpiEvExecuteRegMethods ( 1196 ACPI_NAMESPACE_NODE *Node, 1197 ACPI_ADR_SPACE_TYPE SpaceId) 1198{ 1199 ACPI_STATUS Status; 1200 1201 1202 ACPI_FUNCTION_TRACE (EvExecuteRegMethods); 1203 1204 1205 /* 1206 * Run all _REG methods for all Operation Regions for this space ID. This 1207 * is a separate walk in order to handle any interdependencies between 1208 * regions and _REG methods. (i.e. handlers must be installed for all 1209 * regions of this Space ID before we can run any _REG methods) 1210 */ 1211 Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, 1212 ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, 1213 &SpaceId, NULL); 1214 1215 return_ACPI_STATUS (Status); 1216} 1217 1218 1219/******************************************************************************* 1220 * 1221 * FUNCTION: AcpiEvRegRun 1222 * 1223 * PARAMETERS: WalkNamespace callback 1224 * 1225 * DESCRIPTION: Run _REG method for region objects of the requested spaceID 1226 * 1227 ******************************************************************************/ 1228 1229static ACPI_STATUS 1230AcpiEvRegRun ( 1231 ACPI_HANDLE ObjHandle, 1232 UINT32 Level, 1233 void *Context, 1234 void **ReturnValue) 1235{ 1236 ACPI_OPERAND_OBJECT *ObjDesc; 1237 ACPI_NAMESPACE_NODE *Node; 1238 ACPI_ADR_SPACE_TYPE SpaceId; 1239 ACPI_STATUS Status; 1240 1241 1242 SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context); 1243 1244 /* Convert and validate the device handle */ 1245
|