167754Smsmith/****************************************************************************** 267754Smsmith * 3245582Sjkim * Module Name: evregion - Operation Region support 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 7217365Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp. 970243Smsmith * All rights reserved. 1067754Smsmith * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 2567754Smsmith * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 2967754Smsmith * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 4367754Smsmith 4467754Smsmith 4567754Smsmith#define __EVREGION_C__ 4667754Smsmith 47193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 48193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 49193341Sjkim#include <contrib/dev/acpica/include/acevents.h> 50193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 51193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 5267754Smsmith 5377424Smsmith#define _COMPONENT ACPI_EVENTS 5491116Smsmith ACPI_MODULE_NAME ("evregion") 5567754Smsmith 5667754Smsmith 57245582Sjkimextern UINT8 AcpiGbl_DefaultAddressSpaces[]; 58245582Sjkim 59151937Sjkim/* Local prototypes */ 60117521Snjl 61220663Sjkimstatic void 62220663SjkimAcpiEvOrphanEcRegMethod ( 63249663Sjkim ACPI_NAMESPACE_NODE *EcDeviceNode); 64220663Sjkim 65151937Sjkimstatic ACPI_STATUS 66151937SjkimAcpiEvRegRun ( 67151937Sjkim ACPI_HANDLE ObjHandle, 68151937Sjkim UINT32 Level, 69151937Sjkim void *Context, 70151937Sjkim void **ReturnValue); 71151937Sjkim 72151937Sjkim 7377424Smsmith/******************************************************************************* 7467754Smsmith * 75129684Snjl * FUNCTION: AcpiEvInitializeOpRegions 76129684Snjl * 77129684Snjl * PARAMETERS: None 78129684Snjl * 79129684Snjl * RETURN: Status 80129684Snjl * 81129684Snjl * DESCRIPTION: Execute _REG methods for all Operation Regions that have 82129684Snjl * an installed default region handler. 83129684Snjl * 84129684Snjl ******************************************************************************/ 85129684Snjl 86129684SnjlACPI_STATUS 87129684SnjlAcpiEvInitializeOpRegions ( 88129684Snjl void) 89129684Snjl{ 90129684Snjl ACPI_STATUS Status; 91193267Sjkim UINT32 i; 92129684Snjl 93129684Snjl 94167802Sjkim ACPI_FUNCTION_TRACE (EvInitializeOpRegions); 95129684Snjl 96129684Snjl 97129684Snjl Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 98129684Snjl if (ACPI_FAILURE (Status)) 99129684Snjl { 100129684Snjl return_ACPI_STATUS (Status); 101129684Snjl } 102129684Snjl 103193267Sjkim /* Run the _REG methods for OpRegions in each default address space */ 104193267Sjkim 105129684Snjl for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) 106129684Snjl { 107193267Sjkim /* 108198237Sjkim * Make sure the installed handler is the DEFAULT handler. If not the 109198237Sjkim * default, the _REG methods will have already been run (when the 110198237Sjkim * handler was installed) 111129684Snjl */ 112198237Sjkim if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode, 113198237Sjkim AcpiGbl_DefaultAddressSpaces[i])) 114198237Sjkim { 115198237Sjkim Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode, 116198237Sjkim AcpiGbl_DefaultAddressSpaces[i]); 117198237Sjkim } 118129684Snjl } 119129684Snjl 120218590Sjkim AcpiGbl_RegMethodsExecuted = TRUE; 121218590Sjkim 122129684Snjl (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 123129684Snjl return_ACPI_STATUS (Status); 124129684Snjl} 125129684Snjl 126129684Snjl 127129684Snjl/******************************************************************************* 128129684Snjl * 12967754Smsmith * FUNCTION: AcpiEvAddressSpaceDispatch 13067754Smsmith * 131123315Snjl * PARAMETERS: RegionObj - Internal region object 132228110Sjkim * FieldObj - Corresponding field. Can be NULL. 13367754Smsmith * Function - Read or Write operation 134193267Sjkim * RegionOffset - Where in the region to read or write 13587031Smsmith * BitWidth - Field width in bits (8, 16, 32, or 64) 136167802Sjkim * Value - Pointer to in or out value, must be 137202771Sjkim * a full 64-bit integer 13867754Smsmith * 13967754Smsmith * RETURN: Status 14067754Smsmith * 14167754Smsmith * DESCRIPTION: Dispatch an address space or operation region access to 14267754Smsmith * a previously installed handler. 14367754Smsmith * 14477424Smsmith ******************************************************************************/ 14567754Smsmith 14667754SmsmithACPI_STATUS 14767754SmsmithAcpiEvAddressSpaceDispatch ( 14867754Smsmith ACPI_OPERAND_OBJECT *RegionObj, 149228110Sjkim ACPI_OPERAND_OBJECT *FieldObj, 15067754Smsmith UINT32 Function, 151193267Sjkim UINT32 RegionOffset, 15267754Smsmith UINT32 BitWidth, 153202771Sjkim UINT64 *Value) 15467754Smsmith{ 15567754Smsmith ACPI_STATUS Status; 15677424Smsmith ACPI_ADR_SPACE_HANDLER Handler; 15777424Smsmith ACPI_ADR_SPACE_SETUP RegionSetup; 15867754Smsmith ACPI_OPERAND_OBJECT *HandlerDesc; 15987031Smsmith ACPI_OPERAND_OBJECT *RegionObj2; 16067754Smsmith void *RegionContext = NULL; 161228110Sjkim ACPI_CONNECTION_INFO *Context; 16267754Smsmith 16367754Smsmith 164167802Sjkim ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch); 16567754Smsmith 16667754Smsmith 16787031Smsmith RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 16887031Smsmith if (!RegionObj2) 16987031Smsmith { 17087031Smsmith return_ACPI_STATUS (AE_NOT_EXIST); 17187031Smsmith } 17287031Smsmith 173117521Snjl /* Ensure that there is a handler associated with this region */ 174117521Snjl 175123315Snjl HandlerDesc = RegionObj->Region.Handler; 17667754Smsmith if (!HandlerDesc) 17767754Smsmith { 178167802Sjkim ACPI_ERROR ((AE_INFO, 179167802Sjkim "No handler for Region [%4.4s] (%p) [%s]", 180123315Snjl AcpiUtGetNodeName (RegionObj->Region.Node), 18177424Smsmith RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 18277424Smsmith 18387031Smsmith return_ACPI_STATUS (AE_NOT_EXIST); 18467754Smsmith } 18567754Smsmith 186228110Sjkim Context = HandlerDesc->AddressSpace.Context; 187228110Sjkim 18867754Smsmith /* 189193267Sjkim * It may be the case that the region has never been initialized. 19077424Smsmith * Some types of regions require special init code 19167754Smsmith */ 19287031Smsmith if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) 19367754Smsmith { 194193267Sjkim /* This region has not been initialized yet, do it */ 195193267Sjkim 196117521Snjl RegionSetup = HandlerDesc->AddressSpace.Setup; 19767754Smsmith if (!RegionSetup) 19867754Smsmith { 199117521Snjl /* No initialization routine, exit with error */ 200117521Snjl 201167802Sjkim ACPI_ERROR ((AE_INFO, 202167802Sjkim "No init routine for region(%p) [%s]", 20377424Smsmith RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 204117521Snjl return_ACPI_STATUS (AE_NOT_EXIST); 20567754Smsmith } 20667754Smsmith 20767754Smsmith /* 208193267Sjkim * We must exit the interpreter because the region setup will 209193267Sjkim * potentially execute control methods (for example, the _REG method 210193267Sjkim * for this region) 21167754Smsmith */ 212193267Sjkim AcpiExExitInterpreter (); 21367754Smsmith 21467754Smsmith Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE, 215228110Sjkim Context, &RegionContext); 21667754Smsmith 21767754Smsmith /* Re-enter the interpreter */ 21867754Smsmith 219193267Sjkim AcpiExEnterInterpreter (); 22067754Smsmith 221117521Snjl /* Check for failure of the Region Setup */ 222117521Snjl 22367754Smsmith if (ACPI_FAILURE (Status)) 22467754Smsmith { 225167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 226167802Sjkim "During region initialization: [%s]", 22777424Smsmith AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 22887031Smsmith return_ACPI_STATUS (Status); 22967754Smsmith } 23067754Smsmith 231193267Sjkim /* Region initialization may have been completed by RegionSetup */ 232193267Sjkim 233117521Snjl if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) 234117521Snjl { 235117521Snjl RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE; 236117521Snjl 237254745Sjkim /* 238254745Sjkim * Save the returned context for use in all accesses to 239254745Sjkim * the handler for this particular region 240254745Sjkim */ 241254745Sjkim if (!(RegionObj2->Extra.RegionContext)) 242117521Snjl { 243117521Snjl RegionObj2->Extra.RegionContext = RegionContext; 244117521Snjl } 245117521Snjl } 24667754Smsmith } 24767754Smsmith 248117521Snjl /* We have everything we need, we can invoke the address space handler */ 24967754Smsmith 250117521Snjl Handler = HandlerDesc->AddressSpace.Handler; 251117521Snjl 25282367Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 253117521Snjl "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", 254123315Snjl &RegionObj->Region.Handler->AddressSpace, Handler, 255193267Sjkim ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset), 256117521Snjl AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 25767754Smsmith 258228110Sjkim /* 259228110Sjkim * Special handling for GenericSerialBus and GeneralPurposeIo: 260228110Sjkim * There are three extra parameters that must be passed to the 261228110Sjkim * handler via the context: 262228110Sjkim * 1) Connection buffer, a resource template from Connection() op. 263228110Sjkim * 2) Length of the above buffer. 264228110Sjkim * 3) Actual access length from the AccessAs() op. 265228110Sjkim */ 266228110Sjkim if (((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) || 267228110Sjkim (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) && 268228110Sjkim Context && 269228110Sjkim FieldObj) 270228110Sjkim { 271228110Sjkim /* Get the Connection (ResourceTemplate) buffer */ 272228110Sjkim 273228110Sjkim Context->Connection = FieldObj->Field.ResourceBuffer; 274228110Sjkim Context->Length = FieldObj->Field.ResourceLength; 275228110Sjkim Context->AccessLength = FieldObj->Field.AccessLength; 276228110Sjkim } 277228110Sjkim 278167802Sjkim if (!(HandlerDesc->AddressSpace.HandlerFlags & 279167802Sjkim ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) 28067754Smsmith { 28167754Smsmith /* 282117521Snjl * For handlers other than the default (supplied) handlers, we must 283117521Snjl * exit the interpreter because the handler *might* block -- we don't 284117521Snjl * know what it will do, so we can't hold the lock on the intepreter. 28567754Smsmith */ 286193267Sjkim AcpiExExitInterpreter(); 28767754Smsmith } 28867754Smsmith 289117521Snjl /* Call the handler */ 290117521Snjl 291193267Sjkim Status = Handler (Function, 292193267Sjkim (RegionObj->Region.Address + RegionOffset), BitWidth, Value, 293228110Sjkim Context, RegionObj2->Extra.RegionContext); 29467754Smsmith 29567754Smsmith if (ACPI_FAILURE (Status)) 29667754Smsmith { 297167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]", 298167802Sjkim AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 29967754Smsmith } 30067754Smsmith 301167802Sjkim if (!(HandlerDesc->AddressSpace.HandlerFlags & 302167802Sjkim ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) 30367754Smsmith { 30483174Smsmith /* 30583174Smsmith * We just returned from a non-default handler, we must re-enter the 30683174Smsmith * interpreter 30783174Smsmith */ 308193267Sjkim AcpiExEnterInterpreter (); 30967754Smsmith } 31067754Smsmith 31167754Smsmith return_ACPI_STATUS (Status); 31267754Smsmith} 31367754Smsmith 314123315Snjl 31577424Smsmith/******************************************************************************* 31667754Smsmith * 31799679Siwasaki * FUNCTION: AcpiEvDetachRegion 31867754Smsmith * 319138287Smarks * PARAMETERS: RegionObj - Region Object 320138287Smarks * AcpiNsIsLocked - Namespace Region Already Locked? 32167754Smsmith * 32267754Smsmith * RETURN: None 32367754Smsmith * 32467754Smsmith * DESCRIPTION: Break the association between the handler and the region 32567754Smsmith * this is a two way association. 32667754Smsmith * 32767754Smsmith ******************************************************************************/ 32867754Smsmith 32967754Smsmithvoid 33099679SiwasakiAcpiEvDetachRegion( 33170243Smsmith ACPI_OPERAND_OBJECT *RegionObj, 33270243Smsmith BOOLEAN AcpiNsIsLocked) 33367754Smsmith{ 33467754Smsmith ACPI_OPERAND_OBJECT *HandlerObj; 33567754Smsmith ACPI_OPERAND_OBJECT *ObjDesc; 33667754Smsmith ACPI_OPERAND_OBJECT **LastObjPtr; 33777424Smsmith ACPI_ADR_SPACE_SETUP RegionSetup; 338123315Snjl void **RegionContext; 33987031Smsmith ACPI_OPERAND_OBJECT *RegionObj2; 34067754Smsmith ACPI_STATUS Status; 34167754Smsmith 34267754Smsmith 343167802Sjkim ACPI_FUNCTION_TRACE (EvDetachRegion); 34467754Smsmith 34583174Smsmith 34687031Smsmith RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 34787031Smsmith if (!RegionObj2) 34887031Smsmith { 34999679Siwasaki return_VOID; 35087031Smsmith } 351123315Snjl RegionContext = &RegionObj2->Extra.RegionContext; 35267754Smsmith 353117521Snjl /* Get the address handler from the region object */ 354117521Snjl 355123315Snjl HandlerObj = RegionObj->Region.Handler; 35667754Smsmith if (!HandlerObj) 35767754Smsmith { 358117521Snjl /* This region has no handler, all done */ 359117521Snjl 36067754Smsmith return_VOID; 36167754Smsmith } 36267754Smsmith 363117521Snjl /* Find this region in the handler's list */ 36467754Smsmith 365117521Snjl ObjDesc = HandlerObj->AddressSpace.RegionList; 366117521Snjl LastObjPtr = &HandlerObj->AddressSpace.RegionList; 36767754Smsmith 36867754Smsmith while (ObjDesc) 36967754Smsmith { 370117521Snjl /* Is this the correct Region? */ 371117521Snjl 37267754Smsmith if (ObjDesc == RegionObj) 37367754Smsmith { 37482367Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 37582367Smsmith "Removing Region %p from address handler %p\n", 37667754Smsmith RegionObj, HandlerObj)); 377117521Snjl 378117521Snjl /* This is it, remove it from the handler's list */ 379117521Snjl 38067754Smsmith *LastObjPtr = ObjDesc->Region.Next; 381193267Sjkim ObjDesc->Region.Next = NULL; /* Must clear field */ 38267754Smsmith 38370243Smsmith if (AcpiNsIsLocked) 38470243Smsmith { 38591116Smsmith Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 38691116Smsmith if (ACPI_FAILURE (Status)) 38791116Smsmith { 38891116Smsmith return_VOID; 38991116Smsmith } 39070243Smsmith } 39170243Smsmith 392117521Snjl /* Now stop region accesses by executing the _REG method */ 393117521Snjl 394220663Sjkim Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT); 39599679Siwasaki if (ACPI_FAILURE (Status)) 39699679Siwasaki { 397167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]", 39899679Siwasaki AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 39999679Siwasaki } 40067754Smsmith 40170243Smsmith if (AcpiNsIsLocked) 40270243Smsmith { 40391116Smsmith Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 40491116Smsmith if (ACPI_FAILURE (Status)) 40591116Smsmith { 40691116Smsmith return_VOID; 40791116Smsmith } 40870243Smsmith } 40970243Smsmith 410167802Sjkim /* 411193267Sjkim * If the region has been activated, call the setup handler with 412193267Sjkim * the deactivate notification 413167802Sjkim */ 414167802Sjkim if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) 415167802Sjkim { 416167802Sjkim RegionSetup = HandlerObj->AddressSpace.Setup; 417167802Sjkim Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE, 418167802Sjkim HandlerObj->AddressSpace.Context, RegionContext); 419117521Snjl 420254745Sjkim /* 421254745Sjkim * RegionContext should have been released by the deactivate 422254745Sjkim * operation. We don't need access to it anymore here. 423254745Sjkim */ 424254745Sjkim if (RegionContext) 425254745Sjkim { 426254745Sjkim *RegionContext = NULL; 427254745Sjkim } 428254745Sjkim 429167802Sjkim /* Init routine may fail, Just ignore errors */ 43067754Smsmith 431167802Sjkim if (ACPI_FAILURE (Status)) 432167802Sjkim { 433167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 434167802Sjkim "from region handler - deactivate, [%s]", 435167802Sjkim AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 436167802Sjkim } 437117521Snjl 438167802Sjkim RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE); 43967754Smsmith } 44067754Smsmith 44167754Smsmith /* 442117521Snjl * Remove handler reference in the region 44367754Smsmith * 444167802Sjkim * NOTE: this doesn't mean that the region goes away, the region 445167802Sjkim * is just inaccessible as indicated to the _REG method 44667754Smsmith * 447167802Sjkim * If the region is on the handler's list, this must be the 448167802Sjkim * region's handler 44967754Smsmith */ 450123315Snjl RegionObj->Region.Handler = NULL; 451117521Snjl AcpiUtRemoveReference (HandlerObj); 45267754Smsmith 45367754Smsmith return_VOID; 454117521Snjl } 45567754Smsmith 456117521Snjl /* Walk the linked list of handlers */ 45767754Smsmith 45867754Smsmith LastObjPtr = &ObjDesc->Region.Next; 45967754Smsmith ObjDesc = ObjDesc->Region.Next; 46067754Smsmith } 46167754Smsmith 462117521Snjl /* If we get here, the region was not in the handler's region list */ 463117521Snjl 46482367Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 46582367Smsmith "Cannot remove region %p from address handler %p\n", 46667754Smsmith RegionObj, HandlerObj)); 46767754Smsmith 46867754Smsmith return_VOID; 46967754Smsmith} 47067754Smsmith 47167754Smsmith 47277424Smsmith/******************************************************************************* 47367754Smsmith * 47499679Siwasaki * FUNCTION: AcpiEvAttachRegion 47567754Smsmith * 476138287Smarks * PARAMETERS: HandlerObj - Handler Object 477138287Smarks * RegionObj - Region Object 478138287Smarks * AcpiNsIsLocked - Namespace Region Already Locked? 47967754Smsmith * 48067754Smsmith * RETURN: None 48167754Smsmith * 48267754Smsmith * DESCRIPTION: Create the association between the handler and the region 48367754Smsmith * this is a two way association. 48467754Smsmith * 48567754Smsmith ******************************************************************************/ 48667754Smsmith 48767754SmsmithACPI_STATUS 48899679SiwasakiAcpiEvAttachRegion ( 48967754Smsmith ACPI_OPERAND_OBJECT *HandlerObj, 49067754Smsmith ACPI_OPERAND_OBJECT *RegionObj, 49167754Smsmith BOOLEAN AcpiNsIsLocked) 49267754Smsmith{ 49367754Smsmith 494167802Sjkim ACPI_FUNCTION_TRACE (EvAttachRegion); 49567754Smsmith 49667754Smsmith 49783174Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 498123315Snjl "Adding Region [%4.4s] %p to address handler %p [%s]\n", 499123315Snjl AcpiUtGetNodeName (RegionObj->Region.Node), 500126372Snjl RegionObj, HandlerObj, 501123315Snjl AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 50267754Smsmith 503117521Snjl /* Link this region to the front of the handler's list */ 50467754Smsmith 505117521Snjl RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList; 506117521Snjl HandlerObj->AddressSpace.RegionList = RegionObj; 50767754Smsmith 508117521Snjl /* Install the region's handler */ 509117521Snjl 510123315Snjl if (RegionObj->Region.Handler) 511117521Snjl { 512117521Snjl return_ACPI_STATUS (AE_ALREADY_EXISTS); 513117521Snjl } 514117521Snjl 515123315Snjl RegionObj->Region.Handler = HandlerObj; 516117521Snjl AcpiUtAddReference (HandlerObj); 517117521Snjl 518123315Snjl return_ACPI_STATUS (AE_OK); 51967754Smsmith} 52067754Smsmith 52167754Smsmith 52277424Smsmith/******************************************************************************* 52367754Smsmith * 524245582Sjkim * FUNCTION: AcpiEvExecuteRegMethod 52567754Smsmith * 526245582Sjkim * PARAMETERS: RegionObj - Region object 527245582Sjkim * Function - Passed to _REG: On (1) or Off (0) 52867754Smsmith * 529245582Sjkim * RETURN: Status 53067754Smsmith * 531245582Sjkim * DESCRIPTION: Execute _REG method for a region 53267754Smsmith * 53377424Smsmith ******************************************************************************/ 53467754Smsmith 535245582SjkimACPI_STATUS 536245582SjkimAcpiEvExecuteRegMethod ( 537245582Sjkim ACPI_OPERAND_OBJECT *RegionObj, 538245582Sjkim UINT32 Function) 53967754Smsmith{ 540245582Sjkim ACPI_EVALUATE_INFO *Info; 541245582Sjkim ACPI_OPERAND_OBJECT *Args[3]; 542245582Sjkim ACPI_OPERAND_OBJECT *RegionObj2; 54367754Smsmith ACPI_STATUS Status; 54467754Smsmith 54567754Smsmith 546245582Sjkim ACPI_FUNCTION_TRACE (EvExecuteRegMethod); 54777424Smsmith 54877424Smsmith 549245582Sjkim RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 550245582Sjkim if (!RegionObj2) 55167754Smsmith { 552245582Sjkim return_ACPI_STATUS (AE_NOT_EXIST); 55367754Smsmith } 55467754Smsmith 555245582Sjkim if (RegionObj2->Extra.Method_REG == NULL) 55667754Smsmith { 557245582Sjkim return_ACPI_STATUS (AE_OK); 55867754Smsmith } 55967754Smsmith 560245582Sjkim /* Allocate and initialize the evaluation information block */ 56167754Smsmith 562245582Sjkim Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 563245582Sjkim if (!Info) 56467754Smsmith { 565245582Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 56667754Smsmith } 56767754Smsmith 568245582Sjkim Info->PrefixNode = RegionObj2->Extra.Method_REG; 569249663Sjkim Info->RelativePathname = NULL; 570245582Sjkim Info->Parameters = Args; 571245582Sjkim Info->Flags = ACPI_IGNORE_RETURN_VALUE; 572117521Snjl 57367754Smsmith /* 574245582Sjkim * The _REG method has two arguments: 57567754Smsmith * 576245582Sjkim * Arg0 - Integer: 577245582Sjkim * Operation region space ID Same value as RegionObj->Region.SpaceId 578245582Sjkim * 579245582Sjkim * Arg1 - Integer: 580245582Sjkim * connection status 1 for connecting the handler, 0 for disconnecting 581245582Sjkim * the handler (Passed as a parameter) 58267754Smsmith */ 583245582Sjkim Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId); 584245582Sjkim if (!Args[0]) 585129684Snjl { 586245582Sjkim Status = AE_NO_MEMORY; 587245582Sjkim goto Cleanup1; 588129684Snjl } 589129684Snjl 590245582Sjkim Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function); 591245582Sjkim if (!Args[1]) 592129684Snjl { 593129684Snjl Status = AE_NO_MEMORY; 594245582Sjkim goto Cleanup2; 595129684Snjl } 596129684Snjl 597245582Sjkim Args[2] = NULL; /* Terminate list */ 598129684Snjl 599245582Sjkim /* Execute the method, no return value */ 600129684Snjl 601245582Sjkim ACPI_DEBUG_EXEC ( 602245582Sjkim AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL)); 603129684Snjl 604245582Sjkim Status = AcpiNsEvaluate (Info); 605245582Sjkim AcpiUtRemoveReference (Args[1]); 606129684Snjl 607245582SjkimCleanup2: 608245582Sjkim AcpiUtRemoveReference (Args[0]); 609129684Snjl 610245582SjkimCleanup1: 611245582Sjkim ACPI_FREE (Info); 612129684Snjl return_ACPI_STATUS (Status); 613129684Snjl} 614129684Snjl 615129684Snjl 616129684Snjl/******************************************************************************* 617129684Snjl * 618129684Snjl * FUNCTION: AcpiEvExecuteRegMethods 619129684Snjl * 620129684Snjl * PARAMETERS: Node - Namespace node for the device 621129684Snjl * SpaceId - The address space ID 622129684Snjl * 623129684Snjl * RETURN: Status 624129684Snjl * 625138287Smarks * DESCRIPTION: Run all _REG methods for the input Space ID; 626129684Snjl * Note: assumes namespace is locked, or system init time. 627129684Snjl * 628129684Snjl ******************************************************************************/ 629129684Snjl 630129684SnjlACPI_STATUS 631129684SnjlAcpiEvExecuteRegMethods ( 632129684Snjl ACPI_NAMESPACE_NODE *Node, 633129684Snjl ACPI_ADR_SPACE_TYPE SpaceId) 634129684Snjl{ 635129684Snjl ACPI_STATUS Status; 636129684Snjl 637129684Snjl 638167802Sjkim ACPI_FUNCTION_TRACE (EvExecuteRegMethods); 639129684Snjl 640129684Snjl 641129684Snjl /* 642193267Sjkim * Run all _REG methods for all Operation Regions for this space ID. This 643193267Sjkim * is a separate walk in order to handle any interdependencies between 644193267Sjkim * regions and _REG methods. (i.e. handlers must be installed for all 645193267Sjkim * regions of this Space ID before we can run any _REG methods) 646129684Snjl */ 647129684Snjl Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, 648199337Sjkim ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, 649167802Sjkim &SpaceId, NULL); 650129684Snjl 651220663Sjkim /* Special case for EC: handle "orphan" _REG methods with no region */ 652220663Sjkim 653220663Sjkim if (SpaceId == ACPI_ADR_SPACE_EC) 654220663Sjkim { 655249663Sjkim AcpiEvOrphanEcRegMethod (Node); 656220663Sjkim } 657220663Sjkim 658129684Snjl return_ACPI_STATUS (Status); 659129684Snjl} 660129684Snjl 661129684Snjl 662129684Snjl/******************************************************************************* 663129684Snjl * 664123315Snjl * FUNCTION: AcpiEvRegRun 665123315Snjl * 666123315Snjl * PARAMETERS: WalkNamespace callback 667123315Snjl * 668123315Snjl * DESCRIPTION: Run _REG method for region objects of the requested spaceID 669123315Snjl * 670123315Snjl ******************************************************************************/ 67167754Smsmith 672151937Sjkimstatic ACPI_STATUS 673123315SnjlAcpiEvRegRun ( 674123315Snjl ACPI_HANDLE ObjHandle, 675123315Snjl UINT32 Level, 676123315Snjl void *Context, 677123315Snjl void **ReturnValue) 678123315Snjl{ 679123315Snjl ACPI_OPERAND_OBJECT *ObjDesc; 680123315Snjl ACPI_NAMESPACE_NODE *Node; 681129684Snjl ACPI_ADR_SPACE_TYPE SpaceId; 682123315Snjl ACPI_STATUS Status; 683123315Snjl 684123315Snjl 685129684Snjl SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context); 686123315Snjl 687123315Snjl /* Convert and validate the device handle */ 688123315Snjl 689200553Sjkim Node = AcpiNsValidateHandle (ObjHandle); 690123315Snjl if (!Node) 691123315Snjl { 692123315Snjl return (AE_BAD_PARAMETER); 693123315Snjl } 694123315Snjl 695123315Snjl /* 696193267Sjkim * We only care about regions.and objects that are allowed to have address 697193267Sjkim * space handlers 698123315Snjl */ 699123315Snjl if ((Node->Type != ACPI_TYPE_REGION) && 700123315Snjl (Node != AcpiGbl_RootNode)) 701123315Snjl { 702123315Snjl return (AE_OK); 703123315Snjl } 704123315Snjl 705123315Snjl /* Check for an existing internal object */ 706123315Snjl 707123315Snjl ObjDesc = AcpiNsGetAttachedObject (Node); 708123315Snjl if (!ObjDesc) 709123315Snjl { 710123315Snjl /* No object, just exit */ 711123315Snjl 712123315Snjl return (AE_OK); 713123315Snjl } 714123315Snjl 715123315Snjl /* Object is a Region */ 716123315Snjl 717129684Snjl if (ObjDesc->Region.SpaceId != SpaceId) 718123315Snjl { 719193267Sjkim /* This region is for a different address space, just ignore it */ 720193267Sjkim 721123315Snjl return (AE_OK); 722123315Snjl } 723123315Snjl 724220663Sjkim Status = AcpiEvExecuteRegMethod (ObjDesc, ACPI_REG_CONNECT); 725123315Snjl return (Status); 726123315Snjl} 727123315Snjl 728220663Sjkim 729220663Sjkim/******************************************************************************* 730220663Sjkim * 731220663Sjkim * FUNCTION: AcpiEvOrphanEcRegMethod 732220663Sjkim * 733249663Sjkim * PARAMETERS: EcDeviceNode - Namespace node for an EC device 734220663Sjkim * 735220663Sjkim * RETURN: None 736220663Sjkim * 737220663Sjkim * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC 738220663Sjkim * device. This is a _REG method that has no corresponding region 739220663Sjkim * within the EC device scope. The orphan _REG method appears to 740220663Sjkim * have been enabled by the description of the ECDT in the ACPI 741220663Sjkim * specification: "The availability of the region space can be 742220663Sjkim * detected by providing a _REG method object underneath the 743220663Sjkim * Embedded Controller device." 744220663Sjkim * 745249663Sjkim * To quickly access the EC device, we use the EcDeviceNode used 746249663Sjkim * during EC handler installation. Otherwise, we would need to 747249663Sjkim * perform a time consuming namespace walk, executing _HID 748249663Sjkim * methods to find the EC device. 749220663Sjkim * 750249663Sjkim * MUTEX: Assumes the namespace is locked 751249663Sjkim * 752220663Sjkim ******************************************************************************/ 753220663Sjkim 754220663Sjkimstatic void 755220663SjkimAcpiEvOrphanEcRegMethod ( 756249663Sjkim ACPI_NAMESPACE_NODE *EcDeviceNode) 757220663Sjkim{ 758249663Sjkim ACPI_HANDLE RegMethod; 759249663Sjkim ACPI_NAMESPACE_NODE *NextNode; 760220663Sjkim ACPI_STATUS Status; 761220663Sjkim ACPI_OBJECT_LIST Args; 762220663Sjkim ACPI_OBJECT Objects[2]; 763220663Sjkim 764220663Sjkim 765220663Sjkim ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod); 766220663Sjkim 767220663Sjkim 768249663Sjkim if (!EcDeviceNode) 769220663Sjkim { 770220663Sjkim return_VOID; 771220663Sjkim } 772220663Sjkim 773220663Sjkim /* Namespace is currently locked, must release */ 774220663Sjkim 775220663Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 776220663Sjkim 777220663Sjkim /* Get a handle to a _REG method immediately under the EC device */ 778220663Sjkim 779249663Sjkim Status = AcpiGetHandle (EcDeviceNode, METHOD_NAME__REG, &RegMethod); 780220663Sjkim if (ACPI_FAILURE (Status)) 781220663Sjkim { 782249663Sjkim goto Exit; /* There is no _REG method present */ 783220663Sjkim } 784220663Sjkim 785220663Sjkim /* 786220663Sjkim * Execute the _REG method only if there is no Operation Region in 787220663Sjkim * this scope with the Embedded Controller space ID. Otherwise, it 788220663Sjkim * will already have been executed. Note, this allows for Regions 789220663Sjkim * with other space IDs to be present; but the code below will then 790249663Sjkim * execute the _REG method with the EmbeddedControl SpaceID argument. 791220663Sjkim */ 792220663Sjkim NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL); 793220663Sjkim while (NextNode) 794220663Sjkim { 795220663Sjkim if ((NextNode->Type == ACPI_TYPE_REGION) && 796220663Sjkim (NextNode->Object) && 797220663Sjkim (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC)) 798220663Sjkim { 799249663Sjkim goto Exit; /* Do not execute the _REG */ 800220663Sjkim } 801249663Sjkim 802220663Sjkim NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode); 803220663Sjkim } 804220663Sjkim 805249663Sjkim /* Evaluate the _REG(EmbeddedControl,Connect) method */ 806220663Sjkim 807220663Sjkim Args.Count = 2; 808220663Sjkim Args.Pointer = Objects; 809220663Sjkim Objects[0].Type = ACPI_TYPE_INTEGER; 810220663Sjkim Objects[0].Integer.Value = ACPI_ADR_SPACE_EC; 811220663Sjkim Objects[1].Type = ACPI_TYPE_INTEGER; 812220663Sjkim Objects[1].Integer.Value = ACPI_REG_CONNECT; 813220663Sjkim 814220663Sjkim Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL); 815220663Sjkim 816220663SjkimExit: 817220663Sjkim /* We ignore all errors from above, don't care */ 818220663Sjkim 819220663Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 820220663Sjkim return_VOID; 821220663Sjkim} 822