1 /****************************************************************************** 2 * 3 * Module Name: evrgnini- ACPI AddressSpace (OpRegion) init 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 #define __EVRGNINI_C__ 45 46 #include <contrib/dev/acpica/include/acpi.h> 47 #include <contrib/dev/acpica/include/accommon.h> 48 #include <contrib/dev/acpica/include/acevents.h> 49 #include <contrib/dev/acpica/include/acnamesp.h> 50 51 #define _COMPONENT ACPI_EVENTS 52 ACPI_MODULE_NAME ("evrgnini") 53 54 /* Local prototypes */ 55 56 static BOOLEAN 57 AcpiEvIsPciRootBridge ( 58 ACPI_NAMESPACE_NODE *Node); 59 60 61 /******************************************************************************* 62 * 63 * FUNCTION: AcpiEvSystemMemoryRegionSetup 64 * 65 * PARAMETERS: Handle - Region we are interested in 66 * Function - Start or stop 67 * HandlerContext - Address space handler context 68 * RegionContext - Region specific context 69 * 70 * RETURN: Status 71 * 72 * DESCRIPTION: Setup a SystemMemory operation region 73 * 74 ******************************************************************************/ 75 76 ACPI_STATUS 77 AcpiEvSystemMemoryRegionSetup ( 78 ACPI_HANDLE Handle, 79 UINT32 Function, 80 void *HandlerContext, 81 void **RegionContext) 82 { 83 ACPI_OPERAND_OBJECT *RegionDesc = (ACPI_OPERAND_OBJECT *) Handle; 84 ACPI_MEM_SPACE_CONTEXT *LocalRegionContext; 85 86 87 ACPI_FUNCTION_TRACE (EvSystemMemoryRegionSetup); 88 89 90 if (Function == ACPI_REGION_DEACTIVATE) 91 { 92 if (*RegionContext) 93 { 94 LocalRegionContext = (ACPI_MEM_SPACE_CONTEXT *) *RegionContext; 95 96 /* Delete a cached mapping if present */ 97 98 if (LocalRegionContext->MappedLength) 99 { 100 AcpiOsUnmapMemory (LocalRegionContext->MappedLogicalAddress, 101 LocalRegionContext->MappedLength); 102 } 103 ACPI_FREE (LocalRegionContext); 104 *RegionContext = NULL; 105 } 106 return_ACPI_STATUS (AE_OK); 107 } 108 109 /* Create a new context */ 110 111 LocalRegionContext = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_MEM_SPACE_CONTEXT)); 112 if (!(LocalRegionContext)) 113 { 114 return_ACPI_STATUS (AE_NO_MEMORY); 115 } 116 117 /* Save the region length and address for use in the handler */ 118 119 LocalRegionContext->Length = RegionDesc->Region.Length; 120 LocalRegionContext->Address = RegionDesc->Region.Address; 121 122 *RegionContext = LocalRegionContext; 123 return_ACPI_STATUS (AE_OK); 124 } 125 126 127 /******************************************************************************* 128 * 129 * FUNCTION: AcpiEvIoSpaceRegionSetup 130 * 131 * PARAMETERS: Handle - Region we are interested in 132 * Function - Start or stop 133 * HandlerContext - Address space handler context 134 * RegionContext - Region specific context 135 * 136 * RETURN: Status 137 * 138 * DESCRIPTION: Setup a IO operation region 139 * 140 ******************************************************************************/ 141 142 ACPI_STATUS 143 AcpiEvIoSpaceRegionSetup ( 144 ACPI_HANDLE Handle, 145 UINT32 Function, 146 void *HandlerContext, 147 void **RegionContext) 148 { 149 ACPI_FUNCTION_TRACE (EvIoSpaceRegionSetup); 150 151 152 if (Function == ACPI_REGION_DEACTIVATE) 153 { 154 *RegionContext = NULL; 155 } 156 else 157 { 158 *RegionContext = HandlerContext; 159 } 160 161 return_ACPI_STATUS (AE_OK); 162 } 163 164 165 /******************************************************************************* 166 * 167 * FUNCTION: AcpiEvPciConfigRegionSetup 168 * 169 * PARAMETERS: Handle - Region we are interested in 170 * Function - Start or stop 171 * HandlerContext - Address space handler context 172 * RegionContext - Region specific context 173 * 174 * RETURN: Status 175 * 176 * DESCRIPTION: Setup a PCI_Config operation region 177 * 178 * MUTEX: Assumes namespace is not locked 179 * 180 ******************************************************************************/ 181 182 ACPI_STATUS 183 AcpiEvPciConfigRegionSetup ( 184 ACPI_HANDLE Handle, 185 UINT32 Function, 186 void *HandlerContext, 187 void **RegionContext) 188 { 189 ACPI_STATUS Status = AE_OK; 190 UINT64 PciValue; 191 ACPI_PCI_ID *PciId = *RegionContext; 192 ACPI_OPERAND_OBJECT *HandlerObj; 193 ACPI_NAMESPACE_NODE *ParentNode; 194 ACPI_NAMESPACE_NODE *PciRootNode; 195 ACPI_NAMESPACE_NODE *PciDeviceNode; 196 ACPI_OPERAND_OBJECT *RegionObj = (ACPI_OPERAND_OBJECT *) Handle; 197 198 199 ACPI_FUNCTION_TRACE (EvPciConfigRegionSetup); 200 201 202 HandlerObj = RegionObj->Region.Handler; 203 if (!HandlerObj) 204 { 205 /* 206 * No installed handler. This shouldn't happen because the dispatch 207 * routine checks before we get here, but we check again just in case. 208 */ 209 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 210 "Attempting to init a region %p, with no handler\n", RegionObj)); 211 return_ACPI_STATUS (AE_NOT_EXIST); 212 } 213 214 *RegionContext = NULL; 215 if (Function == ACPI_REGION_DEACTIVATE) 216 { 217 if (PciId) 218 { 219 ACPI_FREE (PciId); 220 } 221 return_ACPI_STATUS (Status); 222 } 223 224 ParentNode = RegionObj->Region.Node->Parent; 225 226 /* 227 * Get the _SEG and _BBN values from the device upon which the handler 228 * is installed. 229 * 230 * We need to get the _SEG and _BBN objects relative to the PCI BUS device. 231 * This is the device the handler has been registered to handle. 232 */ 233 234 /* 235 * If the AddressSpace.Node is still pointing to the root, we need 236 * to scan upward for a PCI Root bridge and re-associate the OpRegion 237 * handlers with that device. 238 */ 239 if (HandlerObj->AddressSpace.Node == AcpiGbl_RootNode) 240 { 241 /* Start search from the parent object */ 242 243 PciRootNode = ParentNode; 244 while (PciRootNode != AcpiGbl_RootNode) 245 { 246 /* Get the _HID/_CID in order to detect a RootBridge */ 247 248 if (AcpiEvIsPciRootBridge (PciRootNode)) 249 { 250 /* Install a handler for this PCI root bridge */ 251 252 Status = AcpiInstallAddressSpaceHandler ( 253 (ACPI_HANDLE) PciRootNode, 254 ACPI_ADR_SPACE_PCI_CONFIG, 255 ACPI_DEFAULT_HANDLER, NULL, NULL); 256 if (ACPI_FAILURE (Status)) 257 { 258 if (Status == AE_SAME_HANDLER) 259 { 260 /* 261 * It is OK if the handler is already installed on the 262 * root bridge. Still need to return a context object 263 * for the new PCI_Config operation region, however. 264 */ 265 Status = AE_OK; 266 } 267 else 268 { 269 ACPI_EXCEPTION ((AE_INFO, Status, 270 "Could not install PciConfig handler " 271 "for Root Bridge %4.4s", 272 AcpiUtGetNodeName (PciRootNode))); 273 } 274 } 275 break; 276 } 277 278 PciRootNode = PciRootNode->Parent; 279 } 280 281 /* PCI root bridge not found, use namespace root node */ 282 } 283 else 284 { 285 PciRootNode = HandlerObj->AddressSpace.Node; 286 } 287 288 /* 289 * If this region is now initialized, we are done. 290 * (InstallAddressSpaceHandler could have initialized it) 291 */ 292 if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) 293 { 294 return_ACPI_STATUS (AE_OK); 295 } 296 297 /* Region is still not initialized. Create a new context */ 298 299 PciId = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PCI_ID)); 300 if (!PciId) 301 { 302 return_ACPI_STATUS (AE_NO_MEMORY); 303 } 304 305 /* 306 * For PCI_Config space access, we need the segment, bus, device and 307 * function numbers. Acquire them here. 308 * 309 * Find the parent device object. (This allows the operation region to be 310 * within a subscope under the device, such as a control method.) 311 */ 312 PciDeviceNode = RegionObj->Region.Node; 313 while (PciDeviceNode && (PciDeviceNode->Type != ACPI_TYPE_DEVICE)) 314 { 315 PciDeviceNode = PciDeviceNode->Parent; 316 } 317 318 if (!PciDeviceNode) 319 { 320 ACPI_FREE (PciId); 321 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 322 } 323 324 /* 325 * Get the PCI device and function numbers from the _ADR object 326 * contained in the parent's scope. 327 */ 328 Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, 329 PciDeviceNode, &PciValue); 330 331 /* 332 * The default is zero, and since the allocation above zeroed the data, 333 * just do nothing on failure. 334 */ 335 if (ACPI_SUCCESS (Status)) 336 { 337 PciId->Device = ACPI_HIWORD (ACPI_LODWORD (PciValue)); 338 PciId->Function = ACPI_LOWORD (ACPI_LODWORD (PciValue)); 339 } 340 341 /* The PCI segment number comes from the _SEG method */ 342 343 Status = AcpiUtEvaluateNumericObject (METHOD_NAME__SEG, 344 PciRootNode, &PciValue); 345 if (ACPI_SUCCESS (Status)) 346 { 347 PciId->Segment = ACPI_LOWORD (PciValue); 348 } 349 350 /* The PCI bus number comes from the _BBN method */ 351 352 Status = AcpiUtEvaluateNumericObject (METHOD_NAME__BBN, 353 PciRootNode, &PciValue); 354 if (ACPI_SUCCESS (Status)) 355 { 356 PciId->Bus = ACPI_LOWORD (PciValue); 357 } 358 359 /* Complete/update the PCI ID for this device */ 360 361 Status = AcpiHwDerivePciId (PciId, PciRootNode, RegionObj->Region.Node); 362 if (ACPI_FAILURE (Status)) 363 { 364 ACPI_FREE (PciId); 365 return_ACPI_STATUS (Status); 366 } 367 368 *RegionContext = PciId; 369 return_ACPI_STATUS (AE_OK); 370 } 371 372 373 /******************************************************************************* 374 * 375 * FUNCTION: AcpiEvIsPciRootBridge 376 * 377 * PARAMETERS: Node - Device node being examined 378 * 379 * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge 380 * 381 * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by 382 * examining the _HID and _CID for the device. 383 * 384 ******************************************************************************/ 385 386 static BOOLEAN 387 AcpiEvIsPciRootBridge ( 388 ACPI_NAMESPACE_NODE *Node) 389 { 390 ACPI_STATUS Status; 391 ACPI_PNP_DEVICE_ID *Hid; 392 ACPI_PNP_DEVICE_ID_LIST *Cid; 393 UINT32 i; 394 BOOLEAN Match; 395 396 397 /* Get the _HID and check for a PCI Root Bridge */ 398 399 Status = AcpiUtExecute_HID (Node, &Hid); 400 if (ACPI_FAILURE (Status)) 401 { 402 return (FALSE); 403 } 404 405 Match = AcpiUtIsPciRootBridge (Hid->String); 406 ACPI_FREE (Hid); 407 408 if (Match) 409 { 410 return (TRUE); 411 } 412 413 /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */ 414 415 Status = AcpiUtExecute_CID (Node, &Cid); 416 if (ACPI_FAILURE (Status)) 417 { 418 return (FALSE); 419 } 420 421 /* Check all _CIDs in the returned list */ 422 423 for (i = 0; i < Cid->Count; i++) 424 { 425 if (AcpiUtIsPciRootBridge (Cid->Ids[i].String)) 426 { 427 ACPI_FREE (Cid); 428 return (TRUE); 429 } 430 } 431 432 ACPI_FREE (Cid); 433 return (FALSE); 434 } 435 436 437 /******************************************************************************* 438 * 439 * FUNCTION: AcpiEvPciBarRegionSetup 440 * 441 * PARAMETERS: Handle - Region we are interested in 442 * Function - Start or stop 443 * HandlerContext - Address space handler context 444 * RegionContext - Region specific context 445 * 446 * RETURN: Status 447 * 448 * DESCRIPTION: Setup a PciBAR operation region 449 * 450 * MUTEX: Assumes namespace is not locked 451 * 452 ******************************************************************************/ 453 454 ACPI_STATUS 455 AcpiEvPciBarRegionSetup ( 456 ACPI_HANDLE Handle, 457 UINT32 Function, 458 void *HandlerContext, 459 void **RegionContext) 460 { 461 ACPI_FUNCTION_TRACE (EvPciBarRegionSetup); 462 463 464 return_ACPI_STATUS (AE_OK); 465 } 466 467 468 /******************************************************************************* 469 * 470 * FUNCTION: AcpiEvCmosRegionSetup 471 * 472 * PARAMETERS: Handle - Region we are interested in 473 * Function - Start or stop 474 * HandlerContext - Address space handler context 475 * RegionContext - Region specific context 476 * 477 * RETURN: Status 478 * 479 * DESCRIPTION: Setup a CMOS operation region 480 * 481 * MUTEX: Assumes namespace is not locked 482 * 483 ******************************************************************************/ 484 485 ACPI_STATUS 486 AcpiEvCmosRegionSetup ( 487 ACPI_HANDLE Handle, 488 UINT32 Function, 489 void *HandlerContext, 490 void **RegionContext) 491 { 492 ACPI_FUNCTION_TRACE (EvCmosRegionSetup); 493 494 495 return_ACPI_STATUS (AE_OK); 496 } 497 498 499 /******************************************************************************* 500 * 501 * FUNCTION: AcpiEvDefaultRegionSetup 502 * 503 * PARAMETERS: Handle - Region we are interested in 504 * Function - Start or stop 505 * HandlerContext - Address space handler context 506 * RegionContext - Region specific context 507 * 508 * RETURN: Status 509 * 510 * DESCRIPTION: Default region initialization 511 * 512 ******************************************************************************/ 513 514 ACPI_STATUS 515 AcpiEvDefaultRegionSetup ( 516 ACPI_HANDLE Handle, 517 UINT32 Function, 518 void *HandlerContext, 519 void **RegionContext) 520 { 521 ACPI_FUNCTION_TRACE (EvDefaultRegionSetup); 522 523 524 if (Function == ACPI_REGION_DEACTIVATE) 525 { 526 *RegionContext = NULL; 527 } 528 else 529 { 530 *RegionContext = HandlerContext; 531 } 532 533 return_ACPI_STATUS (AE_OK); 534 } 535 536 537 /******************************************************************************* 538 * 539 * FUNCTION: AcpiEvInitializeRegion 540 * 541 * PARAMETERS: RegionObj - Region we are initializing 542 * AcpiNsLocked - Is namespace locked? 543 * 544 * RETURN: Status 545 * 546 * DESCRIPTION: Initializes the region, finds any _REG methods and saves them 547 * for execution at a later time 548 * 549 * Get the appropriate address space handler for a newly 550 * created region. 551 * 552 * This also performs address space specific initialization. For 553 * example, PCI regions must have an _ADR object that contains 554 * a PCI address in the scope of the definition. This address is 555 * required to perform an access to PCI config space. 556 * 557 * MUTEX: Interpreter should be unlocked, because we may run the _REG 558 * method for this region. 559 * 560 ******************************************************************************/ 561 562 ACPI_STATUS 563 AcpiEvInitializeRegion ( 564 ACPI_OPERAND_OBJECT *RegionObj, 565 BOOLEAN AcpiNsLocked) 566 { 567 ACPI_OPERAND_OBJECT *HandlerObj; 568 ACPI_OPERAND_OBJECT *ObjDesc; 569 ACPI_ADR_SPACE_TYPE SpaceId; 570 ACPI_NAMESPACE_NODE *Node; 571 ACPI_STATUS Status; 572 ACPI_NAMESPACE_NODE *MethodNode; 573 ACPI_NAME *RegNamePtr = (ACPI_NAME *) METHOD_NAME__REG; 574 ACPI_OPERAND_OBJECT *RegionObj2; 575 576 577 ACPI_FUNCTION_TRACE_U32 (EvInitializeRegion, AcpiNsLocked); 578 579 580 if (!RegionObj) 581 { 582 return_ACPI_STATUS (AE_BAD_PARAMETER); 583 } 584 585 if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED) 586 { 587 return_ACPI_STATUS (AE_OK); 588 } 589 590 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 591 if (!RegionObj2) 592 { 593 return_ACPI_STATUS (AE_NOT_EXIST); 594 } 595 596 Node = RegionObj->Region.Node->Parent; 597 SpaceId = RegionObj->Region.SpaceId; 598 599 /* Setup defaults */ 600 601 RegionObj->Region.Handler = NULL; 602 RegionObj2->Extra.Method_REG = NULL; 603 RegionObj->Common.Flags &= ~(AOPOBJ_SETUP_COMPLETE); 604 RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED; 605 606 /* Find any "_REG" method associated with this region definition */ 607 608 Status = AcpiNsSearchOneScope ( 609 *RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode); 610 if (ACPI_SUCCESS (Status)) 611 { 612 /* 613 * The _REG method is optional and there can be only one per region 614 * definition. This will be executed when the handler is attached 615 * or removed 616 */ 617 RegionObj2->Extra.Method_REG = MethodNode; 618 } 619 620 /* 621 * The following loop depends upon the root Node having no parent 622 * ie: AcpiGbl_RootNode->ParentEntry being set to NULL 623 */ 624 while (Node) 625 { 626 /* Check to see if a handler exists */ 627 628 HandlerObj = NULL; 629 ObjDesc = AcpiNsGetAttachedObject (Node); 630 if (ObjDesc) 631 { 632 /* Can only be a handler if the object exists */ 633 634 switch (Node->Type) 635 { 636 case ACPI_TYPE_DEVICE: 637 638 HandlerObj = ObjDesc->Device.Handler; 639 break; 640 641 case ACPI_TYPE_PROCESSOR: 642 643 HandlerObj = ObjDesc->Processor.Handler; 644 break; 645 646 case ACPI_TYPE_THERMAL: 647 648 HandlerObj = ObjDesc->ThermalZone.Handler; 649 break; 650 651 case ACPI_TYPE_METHOD: 652 /* 653 * If we are executing module level code, the original 654 * Node's object was replaced by this Method object and we 655 * saved the handler in the method object. 656 * 657 * See AcpiNsExecModuleCode 658 */ 659 if (ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) 660 { 661 HandlerObj = ObjDesc->Method.Dispatch.Handler; 662 } 663 break; 664 665 default: 666 667 /* Ignore other objects */ 668 669 break; 670 } 671 672 while (HandlerObj) 673 { 674 /* Is this handler of the correct type? */ 675 676 if (HandlerObj->AddressSpace.SpaceId == SpaceId) 677 { 678 /* Found correct handler */ 679 680 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 681 "Found handler %p for region %p in obj %p\n", 682 HandlerObj, RegionObj, ObjDesc)); 683 684 Status = AcpiEvAttachRegion (HandlerObj, RegionObj, 685 AcpiNsLocked); 686 687 /* 688 * Tell all users that this region is usable by 689 * running the _REG method 690 */ 691 if (AcpiNsLocked) 692 { 693 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 694 if (ACPI_FAILURE (Status)) 695 { 696 return_ACPI_STATUS (Status); 697 } 698 } 699 700 Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT); 701 702 if (AcpiNsLocked) 703 { 704 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 705 if (ACPI_FAILURE (Status)) 706 { 707 return_ACPI_STATUS (Status); 708 } 709 } 710 711 return_ACPI_STATUS (AE_OK); 712 } 713 714 /* Try next handler in the list */ 715 716 HandlerObj = HandlerObj->AddressSpace.Next; 717 } 718 } 719 720 /* This node does not have the handler we need; Pop up one level */ 721 722 Node = Node->Parent; 723 } 724 725 /* If we get here, there is no handler for this region */ 726 727 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 728 "No handler for RegionType %s(%X) (RegionObj %p)\n", 729 AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj)); 730 731 return_ACPI_STATUS (AE_NOT_EXIST); 732 } 733