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