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