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