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