evregion.c revision 278970
167754Smsmith/****************************************************************************** 267754Smsmith * 3245582Sjkim * Module Name: evregion - Operation Region support 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 7217365Sjkim/* 8278970Sjkim * Copyright (C) 2000 - 2015, 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 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 46193341Sjkim#include <contrib/dev/acpica/include/acevents.h> 47193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 48193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 4967754Smsmith 5077424Smsmith#define _COMPONENT ACPI_EVENTS 5191116Smsmith ACPI_MODULE_NAME ("evregion") 5267754Smsmith 5367754Smsmith 54245582Sjkimextern UINT8 AcpiGbl_DefaultAddressSpaces[]; 55245582Sjkim 56151937Sjkim/* Local prototypes */ 57117521Snjl 58220663Sjkimstatic void 59220663SjkimAcpiEvOrphanEcRegMethod ( 60249663Sjkim ACPI_NAMESPACE_NODE *EcDeviceNode); 61220663Sjkim 62151937Sjkimstatic ACPI_STATUS 63151937SjkimAcpiEvRegRun ( 64151937Sjkim ACPI_HANDLE ObjHandle, 65151937Sjkim UINT32 Level, 66151937Sjkim void *Context, 67151937Sjkim void **ReturnValue); 68151937Sjkim 69151937Sjkim 7077424Smsmith/******************************************************************************* 7167754Smsmith * 72129684Snjl * FUNCTION: AcpiEvInitializeOpRegions 73129684Snjl * 74129684Snjl * PARAMETERS: None 75129684Snjl * 76129684Snjl * RETURN: Status 77129684Snjl * 78129684Snjl * DESCRIPTION: Execute _REG methods for all Operation Regions that have 79129684Snjl * an installed default region handler. 80129684Snjl * 81129684Snjl ******************************************************************************/ 82129684Snjl 83129684SnjlACPI_STATUS 84129684SnjlAcpiEvInitializeOpRegions ( 85129684Snjl void) 86129684Snjl{ 87129684Snjl ACPI_STATUS Status; 88193267Sjkim UINT32 i; 89129684Snjl 90129684Snjl 91167802Sjkim ACPI_FUNCTION_TRACE (EvInitializeOpRegions); 92129684Snjl 93129684Snjl 94129684Snjl Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 95129684Snjl if (ACPI_FAILURE (Status)) 96129684Snjl { 97129684Snjl return_ACPI_STATUS (Status); 98129684Snjl } 99129684Snjl 100193267Sjkim /* Run the _REG methods for OpRegions in each default address space */ 101193267Sjkim 102129684Snjl for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) 103129684Snjl { 104193267Sjkim /* 105198237Sjkim * Make sure the installed handler is the DEFAULT handler. If not the 106198237Sjkim * default, the _REG methods will have already been run (when the 107198237Sjkim * handler was installed) 108129684Snjl */ 109198237Sjkim if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode, 110198237Sjkim AcpiGbl_DefaultAddressSpaces[i])) 111198237Sjkim { 112198237Sjkim Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode, 113198237Sjkim AcpiGbl_DefaultAddressSpaces[i]); 114198237Sjkim } 115129684Snjl } 116129684Snjl 117218590Sjkim AcpiGbl_RegMethodsExecuted = TRUE; 118218590Sjkim 119129684Snjl (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 120129684Snjl return_ACPI_STATUS (Status); 121129684Snjl} 122129684Snjl 123129684Snjl 124129684Snjl/******************************************************************************* 125129684Snjl * 12667754Smsmith * FUNCTION: AcpiEvAddressSpaceDispatch 12767754Smsmith * 128123315Snjl * PARAMETERS: RegionObj - Internal region object 129228110Sjkim * FieldObj - Corresponding field. Can be NULL. 13067754Smsmith * Function - Read or Write operation 131193267Sjkim * RegionOffset - Where in the region to read or write 13287031Smsmith * BitWidth - Field width in bits (8, 16, 32, or 64) 133167802Sjkim * Value - Pointer to in or out value, must be 134202771Sjkim * a full 64-bit integer 13567754Smsmith * 13667754Smsmith * RETURN: Status 13767754Smsmith * 13867754Smsmith * DESCRIPTION: Dispatch an address space or operation region access to 13967754Smsmith * a previously installed handler. 14067754Smsmith * 14177424Smsmith ******************************************************************************/ 14267754Smsmith 14367754SmsmithACPI_STATUS 14467754SmsmithAcpiEvAddressSpaceDispatch ( 14567754Smsmith ACPI_OPERAND_OBJECT *RegionObj, 146228110Sjkim ACPI_OPERAND_OBJECT *FieldObj, 14767754Smsmith UINT32 Function, 148193267Sjkim UINT32 RegionOffset, 14967754Smsmith UINT32 BitWidth, 150202771Sjkim UINT64 *Value) 15167754Smsmith{ 15267754Smsmith ACPI_STATUS Status; 15377424Smsmith ACPI_ADR_SPACE_HANDLER Handler; 15477424Smsmith ACPI_ADR_SPACE_SETUP RegionSetup; 15567754Smsmith ACPI_OPERAND_OBJECT *HandlerDesc; 15687031Smsmith ACPI_OPERAND_OBJECT *RegionObj2; 15767754Smsmith void *RegionContext = NULL; 158228110Sjkim ACPI_CONNECTION_INFO *Context; 159272444Sjkim ACPI_PHYSICAL_ADDRESS Address; 16067754Smsmith 16167754Smsmith 162167802Sjkim ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch); 16367754Smsmith 16467754Smsmith 16587031Smsmith RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 16687031Smsmith if (!RegionObj2) 16787031Smsmith { 16887031Smsmith return_ACPI_STATUS (AE_NOT_EXIST); 16987031Smsmith } 17087031Smsmith 171117521Snjl /* Ensure that there is a handler associated with this region */ 172117521Snjl 173123315Snjl HandlerDesc = RegionObj->Region.Handler; 17467754Smsmith if (!HandlerDesc) 17567754Smsmith { 176167802Sjkim ACPI_ERROR ((AE_INFO, 177167802Sjkim "No handler for Region [%4.4s] (%p) [%s]", 178123315Snjl AcpiUtGetNodeName (RegionObj->Region.Node), 17977424Smsmith RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 18077424Smsmith 18187031Smsmith return_ACPI_STATUS (AE_NOT_EXIST); 18267754Smsmith } 18367754Smsmith 184228110Sjkim Context = HandlerDesc->AddressSpace.Context; 185228110Sjkim 18667754Smsmith /* 187193267Sjkim * It may be the case that the region has never been initialized. 18877424Smsmith * Some types of regions require special init code 18967754Smsmith */ 19087031Smsmith if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) 19167754Smsmith { 192193267Sjkim /* This region has not been initialized yet, do it */ 193193267Sjkim 194117521Snjl RegionSetup = HandlerDesc->AddressSpace.Setup; 19567754Smsmith if (!RegionSetup) 19667754Smsmith { 197117521Snjl /* No initialization routine, exit with error */ 198117521Snjl 199167802Sjkim ACPI_ERROR ((AE_INFO, 200167802Sjkim "No init routine for region(%p) [%s]", 20177424Smsmith RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 202117521Snjl return_ACPI_STATUS (AE_NOT_EXIST); 20367754Smsmith } 20467754Smsmith 20567754Smsmith /* 206193267Sjkim * We must exit the interpreter because the region setup will 207193267Sjkim * potentially execute control methods (for example, the _REG method 208193267Sjkim * for this region) 20967754Smsmith */ 210193267Sjkim AcpiExExitInterpreter (); 21167754Smsmith 21267754Smsmith Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE, 213228110Sjkim Context, &RegionContext); 21467754Smsmith 21567754Smsmith /* Re-enter the interpreter */ 21667754Smsmith 217193267Sjkim AcpiExEnterInterpreter (); 21867754Smsmith 219117521Snjl /* Check for failure of the Region Setup */ 220117521Snjl 22167754Smsmith if (ACPI_FAILURE (Status)) 22267754Smsmith { 223167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 224167802Sjkim "During region initialization: [%s]", 22577424Smsmith AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 22687031Smsmith return_ACPI_STATUS (Status); 22767754Smsmith } 22867754Smsmith 229193267Sjkim /* Region initialization may have been completed by RegionSetup */ 230193267Sjkim 231117521Snjl if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) 232117521Snjl { 233117521Snjl RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE; 234117521Snjl 235254745Sjkim /* 236254745Sjkim * Save the returned context for use in all accesses to 237254745Sjkim * the handler for this particular region 238254745Sjkim */ 239254745Sjkim if (!(RegionObj2->Extra.RegionContext)) 240117521Snjl { 241117521Snjl RegionObj2->Extra.RegionContext = RegionContext; 242117521Snjl } 243117521Snjl } 24467754Smsmith } 24567754Smsmith 246117521Snjl /* We have everything we need, we can invoke the address space handler */ 24767754Smsmith 248117521Snjl Handler = HandlerDesc->AddressSpace.Handler; 249272444Sjkim Address = (RegionObj->Region.Address + RegionOffset); 250117521Snjl 251228110Sjkim /* 252228110Sjkim * Special handling for GenericSerialBus and GeneralPurposeIo: 253228110Sjkim * There are three extra parameters that must be passed to the 254228110Sjkim * handler via the context: 255272444Sjkim * 1) Connection buffer, a resource template from Connection() op 256272444Sjkim * 2) Length of the above buffer 257272444Sjkim * 3) Actual access length from the AccessAs() op 258272444Sjkim * 259272444Sjkim * In addition, for GeneralPurposeIo, the Address and BitWidth fields 260272444Sjkim * are defined as follows: 261272444Sjkim * 1) Address is the pin number index of the field (bit offset from 262272444Sjkim * the previous Connection) 263272444Sjkim * 2) BitWidth is the actual bit length of the field (number of pins) 264228110Sjkim */ 265272444Sjkim if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) && 266228110Sjkim Context && 267228110Sjkim FieldObj) 268228110Sjkim { 269228110Sjkim /* Get the Connection (ResourceTemplate) buffer */ 270228110Sjkim 271228110Sjkim Context->Connection = FieldObj->Field.ResourceBuffer; 272228110Sjkim Context->Length = FieldObj->Field.ResourceLength; 273228110Sjkim Context->AccessLength = FieldObj->Field.AccessLength; 274228110Sjkim } 275272444Sjkim if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) && 276272444Sjkim Context && 277272444Sjkim FieldObj) 278272444Sjkim { 279272444Sjkim /* Get the Connection (ResourceTemplate) buffer */ 280228110Sjkim 281272444Sjkim Context->Connection = FieldObj->Field.ResourceBuffer; 282272444Sjkim Context->Length = FieldObj->Field.ResourceLength; 283272444Sjkim Context->AccessLength = FieldObj->Field.AccessLength; 284272444Sjkim Address = FieldObj->Field.PinNumberIndex; 285272444Sjkim BitWidth = FieldObj->Field.BitLength; 286272444Sjkim } 287272444Sjkim 288272444Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 289272444Sjkim "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", 290272444Sjkim &RegionObj->Region.Handler->AddressSpace, Handler, 291272444Sjkim ACPI_FORMAT_NATIVE_UINT (Address), 292272444Sjkim AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 293272444Sjkim 294167802Sjkim if (!(HandlerDesc->AddressSpace.HandlerFlags & 295167802Sjkim ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) 29667754Smsmith { 29767754Smsmith /* 298117521Snjl * For handlers other than the default (supplied) handlers, we must 299117521Snjl * exit the interpreter because the handler *might* block -- we don't 300117521Snjl * know what it will do, so we can't hold the lock on the intepreter. 30167754Smsmith */ 302193267Sjkim AcpiExExitInterpreter(); 30367754Smsmith } 30467754Smsmith 305117521Snjl /* Call the handler */ 306117521Snjl 307272444Sjkim Status = Handler (Function, Address, BitWidth, Value, Context, 308272444Sjkim RegionObj2->Extra.RegionContext); 30967754Smsmith 31067754Smsmith if (ACPI_FAILURE (Status)) 31167754Smsmith { 312167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]", 313167802Sjkim AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 31467754Smsmith } 31567754Smsmith 316167802Sjkim if (!(HandlerDesc->AddressSpace.HandlerFlags & 317167802Sjkim ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) 31867754Smsmith { 31983174Smsmith /* 32083174Smsmith * We just returned from a non-default handler, we must re-enter the 32183174Smsmith * interpreter 32283174Smsmith */ 323193267Sjkim AcpiExEnterInterpreter (); 32467754Smsmith } 32567754Smsmith 32667754Smsmith return_ACPI_STATUS (Status); 32767754Smsmith} 32867754Smsmith 329123315Snjl 33077424Smsmith/******************************************************************************* 33167754Smsmith * 33299679Siwasaki * FUNCTION: AcpiEvDetachRegion 33367754Smsmith * 334138287Smarks * PARAMETERS: RegionObj - Region Object 335138287Smarks * AcpiNsIsLocked - Namespace Region Already Locked? 33667754Smsmith * 33767754Smsmith * RETURN: None 33867754Smsmith * 33967754Smsmith * DESCRIPTION: Break the association between the handler and the region 34067754Smsmith * this is a two way association. 34167754Smsmith * 34267754Smsmith ******************************************************************************/ 34367754Smsmith 34467754Smsmithvoid 34599679SiwasakiAcpiEvDetachRegion( 34670243Smsmith ACPI_OPERAND_OBJECT *RegionObj, 34770243Smsmith BOOLEAN AcpiNsIsLocked) 34867754Smsmith{ 34967754Smsmith ACPI_OPERAND_OBJECT *HandlerObj; 35067754Smsmith ACPI_OPERAND_OBJECT *ObjDesc; 351272444Sjkim ACPI_OPERAND_OBJECT *StartDesc; 35267754Smsmith ACPI_OPERAND_OBJECT **LastObjPtr; 35377424Smsmith ACPI_ADR_SPACE_SETUP RegionSetup; 354123315Snjl void **RegionContext; 35587031Smsmith ACPI_OPERAND_OBJECT *RegionObj2; 35667754Smsmith ACPI_STATUS Status; 35767754Smsmith 35867754Smsmith 359167802Sjkim ACPI_FUNCTION_TRACE (EvDetachRegion); 36067754Smsmith 36183174Smsmith 36287031Smsmith RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 36387031Smsmith if (!RegionObj2) 36487031Smsmith { 36599679Siwasaki return_VOID; 36687031Smsmith } 367123315Snjl RegionContext = &RegionObj2->Extra.RegionContext; 36867754Smsmith 369117521Snjl /* Get the address handler from the region object */ 370117521Snjl 371123315Snjl HandlerObj = RegionObj->Region.Handler; 37267754Smsmith if (!HandlerObj) 37367754Smsmith { 374117521Snjl /* This region has no handler, all done */ 375117521Snjl 37667754Smsmith return_VOID; 37767754Smsmith } 37867754Smsmith 379117521Snjl /* Find this region in the handler's list */ 38067754Smsmith 381117521Snjl ObjDesc = HandlerObj->AddressSpace.RegionList; 382272444Sjkim StartDesc = ObjDesc; 383117521Snjl LastObjPtr = &HandlerObj->AddressSpace.RegionList; 38467754Smsmith 38567754Smsmith while (ObjDesc) 38667754Smsmith { 387117521Snjl /* Is this the correct Region? */ 388117521Snjl 38967754Smsmith if (ObjDesc == RegionObj) 39067754Smsmith { 39182367Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 39282367Smsmith "Removing Region %p from address handler %p\n", 39367754Smsmith RegionObj, HandlerObj)); 394117521Snjl 395117521Snjl /* This is it, remove it from the handler's list */ 396117521Snjl 39767754Smsmith *LastObjPtr = ObjDesc->Region.Next; 398193267Sjkim ObjDesc->Region.Next = NULL; /* Must clear field */ 39967754Smsmith 40070243Smsmith if (AcpiNsIsLocked) 40170243Smsmith { 40291116Smsmith Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 40391116Smsmith if (ACPI_FAILURE (Status)) 40491116Smsmith { 40591116Smsmith return_VOID; 40691116Smsmith } 40770243Smsmith } 40870243Smsmith 409117521Snjl /* Now stop region accesses by executing the _REG method */ 410117521Snjl 411220663Sjkim Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT); 41299679Siwasaki if (ACPI_FAILURE (Status)) 41399679Siwasaki { 414167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]", 41599679Siwasaki AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 41699679Siwasaki } 41767754Smsmith 41870243Smsmith if (AcpiNsIsLocked) 41970243Smsmith { 42091116Smsmith Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 42191116Smsmith if (ACPI_FAILURE (Status)) 42291116Smsmith { 42391116Smsmith return_VOID; 42491116Smsmith } 42570243Smsmith } 42670243Smsmith 427167802Sjkim /* 428193267Sjkim * If the region has been activated, call the setup handler with 429193267Sjkim * the deactivate notification 430167802Sjkim */ 431167802Sjkim if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) 432167802Sjkim { 433167802Sjkim RegionSetup = HandlerObj->AddressSpace.Setup; 434167802Sjkim Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE, 435167802Sjkim HandlerObj->AddressSpace.Context, RegionContext); 436117521Snjl 437254745Sjkim /* 438254745Sjkim * RegionContext should have been released by the deactivate 439254745Sjkim * operation. We don't need access to it anymore here. 440254745Sjkim */ 441254745Sjkim if (RegionContext) 442254745Sjkim { 443254745Sjkim *RegionContext = NULL; 444254745Sjkim } 445254745Sjkim 446167802Sjkim /* Init routine may fail, Just ignore errors */ 44767754Smsmith 448167802Sjkim if (ACPI_FAILURE (Status)) 449167802Sjkim { 450167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 451167802Sjkim "from region handler - deactivate, [%s]", 452167802Sjkim AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 453167802Sjkim } 454117521Snjl 455167802Sjkim RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE); 45667754Smsmith } 45767754Smsmith 45867754Smsmith /* 459117521Snjl * Remove handler reference in the region 46067754Smsmith * 461167802Sjkim * NOTE: this doesn't mean that the region goes away, the region 462167802Sjkim * is just inaccessible as indicated to the _REG method 46367754Smsmith * 464167802Sjkim * If the region is on the handler's list, this must be the 465167802Sjkim * region's handler 46667754Smsmith */ 467123315Snjl RegionObj->Region.Handler = NULL; 468117521Snjl AcpiUtRemoveReference (HandlerObj); 46967754Smsmith 47067754Smsmith return_VOID; 471117521Snjl } 47267754Smsmith 473117521Snjl /* Walk the linked list of handlers */ 47467754Smsmith 47567754Smsmith LastObjPtr = &ObjDesc->Region.Next; 47667754Smsmith ObjDesc = ObjDesc->Region.Next; 477272444Sjkim 478272444Sjkim /* Prevent infinite loop if list is corrupted */ 479272444Sjkim 480272444Sjkim if (ObjDesc == StartDesc) 481272444Sjkim { 482272444Sjkim ACPI_ERROR ((AE_INFO, 483272444Sjkim "Circular handler list in region object %p", 484272444Sjkim RegionObj)); 485272444Sjkim return_VOID; 486272444Sjkim } 48767754Smsmith } 48867754Smsmith 489117521Snjl /* If we get here, the region was not in the handler's region list */ 490117521Snjl 49182367Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 49282367Smsmith "Cannot remove region %p from address handler %p\n", 49367754Smsmith RegionObj, HandlerObj)); 49467754Smsmith 49567754Smsmith return_VOID; 49667754Smsmith} 49767754Smsmith 49867754Smsmith 49977424Smsmith/******************************************************************************* 50067754Smsmith * 50199679Siwasaki * FUNCTION: AcpiEvAttachRegion 50267754Smsmith * 503138287Smarks * PARAMETERS: HandlerObj - Handler Object 504138287Smarks * RegionObj - Region Object 505138287Smarks * AcpiNsIsLocked - Namespace Region Already Locked? 50667754Smsmith * 50767754Smsmith * RETURN: None 50867754Smsmith * 50967754Smsmith * DESCRIPTION: Create the association between the handler and the region 51067754Smsmith * this is a two way association. 51167754Smsmith * 51267754Smsmith ******************************************************************************/ 51367754Smsmith 51467754SmsmithACPI_STATUS 51599679SiwasakiAcpiEvAttachRegion ( 51667754Smsmith ACPI_OPERAND_OBJECT *HandlerObj, 51767754Smsmith ACPI_OPERAND_OBJECT *RegionObj, 51867754Smsmith BOOLEAN AcpiNsIsLocked) 51967754Smsmith{ 52067754Smsmith 521167802Sjkim ACPI_FUNCTION_TRACE (EvAttachRegion); 52267754Smsmith 52367754Smsmith 52483174Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 525123315Snjl "Adding Region [%4.4s] %p to address handler %p [%s]\n", 526123315Snjl AcpiUtGetNodeName (RegionObj->Region.Node), 527126372Snjl RegionObj, HandlerObj, 528123315Snjl AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 52967754Smsmith 530117521Snjl /* Link this region to the front of the handler's list */ 53167754Smsmith 532117521Snjl RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList; 533117521Snjl HandlerObj->AddressSpace.RegionList = RegionObj; 53467754Smsmith 535117521Snjl /* Install the region's handler */ 536117521Snjl 537123315Snjl if (RegionObj->Region.Handler) 538117521Snjl { 539117521Snjl return_ACPI_STATUS (AE_ALREADY_EXISTS); 540117521Snjl } 541117521Snjl 542123315Snjl RegionObj->Region.Handler = HandlerObj; 543117521Snjl AcpiUtAddReference (HandlerObj); 544117521Snjl 545123315Snjl return_ACPI_STATUS (AE_OK); 54667754Smsmith} 54767754Smsmith 54867754Smsmith 54977424Smsmith/******************************************************************************* 55067754Smsmith * 551245582Sjkim * FUNCTION: AcpiEvExecuteRegMethod 55267754Smsmith * 553245582Sjkim * PARAMETERS: RegionObj - Region object 554245582Sjkim * Function - Passed to _REG: On (1) or Off (0) 55567754Smsmith * 556245582Sjkim * RETURN: Status 55767754Smsmith * 558245582Sjkim * DESCRIPTION: Execute _REG method for a region 55967754Smsmith * 56077424Smsmith ******************************************************************************/ 56167754Smsmith 562245582SjkimACPI_STATUS 563245582SjkimAcpiEvExecuteRegMethod ( 564245582Sjkim ACPI_OPERAND_OBJECT *RegionObj, 565245582Sjkim UINT32 Function) 56667754Smsmith{ 567245582Sjkim ACPI_EVALUATE_INFO *Info; 568245582Sjkim ACPI_OPERAND_OBJECT *Args[3]; 569245582Sjkim ACPI_OPERAND_OBJECT *RegionObj2; 57067754Smsmith ACPI_STATUS Status; 57167754Smsmith 57267754Smsmith 573245582Sjkim ACPI_FUNCTION_TRACE (EvExecuteRegMethod); 57477424Smsmith 57577424Smsmith 576245582Sjkim RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 577245582Sjkim if (!RegionObj2) 57867754Smsmith { 579245582Sjkim return_ACPI_STATUS (AE_NOT_EXIST); 58067754Smsmith } 58167754Smsmith 582245582Sjkim if (RegionObj2->Extra.Method_REG == NULL) 58367754Smsmith { 584245582Sjkim return_ACPI_STATUS (AE_OK); 58567754Smsmith } 58667754Smsmith 587245582Sjkim /* Allocate and initialize the evaluation information block */ 58867754Smsmith 589245582Sjkim Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 590245582Sjkim if (!Info) 59167754Smsmith { 592245582Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 59367754Smsmith } 59467754Smsmith 595245582Sjkim Info->PrefixNode = RegionObj2->Extra.Method_REG; 596249663Sjkim Info->RelativePathname = NULL; 597245582Sjkim Info->Parameters = Args; 598245582Sjkim Info->Flags = ACPI_IGNORE_RETURN_VALUE; 599117521Snjl 60067754Smsmith /* 601245582Sjkim * The _REG method has two arguments: 60267754Smsmith * 603245582Sjkim * Arg0 - Integer: 604245582Sjkim * Operation region space ID Same value as RegionObj->Region.SpaceId 605245582Sjkim * 606245582Sjkim * Arg1 - Integer: 607245582Sjkim * connection status 1 for connecting the handler, 0 for disconnecting 608245582Sjkim * the handler (Passed as a parameter) 60967754Smsmith */ 610245582Sjkim Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId); 611245582Sjkim if (!Args[0]) 612129684Snjl { 613245582Sjkim Status = AE_NO_MEMORY; 614245582Sjkim goto Cleanup1; 615129684Snjl } 616129684Snjl 617245582Sjkim Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function); 618245582Sjkim if (!Args[1]) 619129684Snjl { 620129684Snjl Status = AE_NO_MEMORY; 621245582Sjkim goto Cleanup2; 622129684Snjl } 623129684Snjl 624245582Sjkim Args[2] = NULL; /* Terminate list */ 625129684Snjl 626245582Sjkim /* Execute the method, no return value */ 627129684Snjl 628245582Sjkim ACPI_DEBUG_EXEC ( 629245582Sjkim AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL)); 630129684Snjl 631245582Sjkim Status = AcpiNsEvaluate (Info); 632245582Sjkim AcpiUtRemoveReference (Args[1]); 633129684Snjl 634245582SjkimCleanup2: 635245582Sjkim AcpiUtRemoveReference (Args[0]); 636129684Snjl 637245582SjkimCleanup1: 638245582Sjkim ACPI_FREE (Info); 639129684Snjl return_ACPI_STATUS (Status); 640129684Snjl} 641129684Snjl 642129684Snjl 643129684Snjl/******************************************************************************* 644129684Snjl * 645129684Snjl * FUNCTION: AcpiEvExecuteRegMethods 646129684Snjl * 647129684Snjl * PARAMETERS: Node - Namespace node for the device 648129684Snjl * SpaceId - The address space ID 649129684Snjl * 650129684Snjl * RETURN: Status 651129684Snjl * 652138287Smarks * DESCRIPTION: Run all _REG methods for the input Space ID; 653129684Snjl * Note: assumes namespace is locked, or system init time. 654129684Snjl * 655129684Snjl ******************************************************************************/ 656129684Snjl 657129684SnjlACPI_STATUS 658129684SnjlAcpiEvExecuteRegMethods ( 659129684Snjl ACPI_NAMESPACE_NODE *Node, 660129684Snjl ACPI_ADR_SPACE_TYPE SpaceId) 661129684Snjl{ 662129684Snjl ACPI_STATUS Status; 663129684Snjl 664129684Snjl 665167802Sjkim ACPI_FUNCTION_TRACE (EvExecuteRegMethods); 666129684Snjl 667129684Snjl 668129684Snjl /* 669193267Sjkim * Run all _REG methods for all Operation Regions for this space ID. This 670193267Sjkim * is a separate walk in order to handle any interdependencies between 671193267Sjkim * regions and _REG methods. (i.e. handlers must be installed for all 672193267Sjkim * regions of this Space ID before we can run any _REG methods) 673129684Snjl */ 674129684Snjl Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, 675199337Sjkim ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, 676167802Sjkim &SpaceId, NULL); 677129684Snjl 678220663Sjkim /* Special case for EC: handle "orphan" _REG methods with no region */ 679220663Sjkim 680220663Sjkim if (SpaceId == ACPI_ADR_SPACE_EC) 681220663Sjkim { 682249663Sjkim AcpiEvOrphanEcRegMethod (Node); 683220663Sjkim } 684220663Sjkim 685129684Snjl return_ACPI_STATUS (Status); 686129684Snjl} 687129684Snjl 688129684Snjl 689129684Snjl/******************************************************************************* 690129684Snjl * 691123315Snjl * FUNCTION: AcpiEvRegRun 692123315Snjl * 693123315Snjl * PARAMETERS: WalkNamespace callback 694123315Snjl * 695123315Snjl * DESCRIPTION: Run _REG method for region objects of the requested spaceID 696123315Snjl * 697123315Snjl ******************************************************************************/ 69867754Smsmith 699151937Sjkimstatic ACPI_STATUS 700123315SnjlAcpiEvRegRun ( 701123315Snjl ACPI_HANDLE ObjHandle, 702123315Snjl UINT32 Level, 703123315Snjl void *Context, 704123315Snjl void **ReturnValue) 705123315Snjl{ 706123315Snjl ACPI_OPERAND_OBJECT *ObjDesc; 707123315Snjl ACPI_NAMESPACE_NODE *Node; 708129684Snjl ACPI_ADR_SPACE_TYPE SpaceId; 709123315Snjl ACPI_STATUS Status; 710123315Snjl 711123315Snjl 712129684Snjl SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context); 713123315Snjl 714123315Snjl /* Convert and validate the device handle */ 715123315Snjl 716200553Sjkim Node = AcpiNsValidateHandle (ObjHandle); 717123315Snjl if (!Node) 718123315Snjl { 719123315Snjl return (AE_BAD_PARAMETER); 720123315Snjl } 721123315Snjl 722123315Snjl /* 723193267Sjkim * We only care about regions.and objects that are allowed to have address 724193267Sjkim * space handlers 725123315Snjl */ 726123315Snjl if ((Node->Type != ACPI_TYPE_REGION) && 727123315Snjl (Node != AcpiGbl_RootNode)) 728123315Snjl { 729123315Snjl return (AE_OK); 730123315Snjl } 731123315Snjl 732123315Snjl /* Check for an existing internal object */ 733123315Snjl 734123315Snjl ObjDesc = AcpiNsGetAttachedObject (Node); 735123315Snjl if (!ObjDesc) 736123315Snjl { 737123315Snjl /* No object, just exit */ 738123315Snjl 739123315Snjl return (AE_OK); 740123315Snjl } 741123315Snjl 742123315Snjl /* Object is a Region */ 743123315Snjl 744129684Snjl if (ObjDesc->Region.SpaceId != SpaceId) 745123315Snjl { 746193267Sjkim /* This region is for a different address space, just ignore it */ 747193267Sjkim 748123315Snjl return (AE_OK); 749123315Snjl } 750123315Snjl 751220663Sjkim Status = AcpiEvExecuteRegMethod (ObjDesc, ACPI_REG_CONNECT); 752123315Snjl return (Status); 753123315Snjl} 754123315Snjl 755220663Sjkim 756220663Sjkim/******************************************************************************* 757220663Sjkim * 758220663Sjkim * FUNCTION: AcpiEvOrphanEcRegMethod 759220663Sjkim * 760249663Sjkim * PARAMETERS: EcDeviceNode - Namespace node for an EC device 761220663Sjkim * 762220663Sjkim * RETURN: None 763220663Sjkim * 764220663Sjkim * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC 765220663Sjkim * device. This is a _REG method that has no corresponding region 766220663Sjkim * within the EC device scope. The orphan _REG method appears to 767220663Sjkim * have been enabled by the description of the ECDT in the ACPI 768220663Sjkim * specification: "The availability of the region space can be 769220663Sjkim * detected by providing a _REG method object underneath the 770220663Sjkim * Embedded Controller device." 771220663Sjkim * 772249663Sjkim * To quickly access the EC device, we use the EcDeviceNode used 773249663Sjkim * during EC handler installation. Otherwise, we would need to 774249663Sjkim * perform a time consuming namespace walk, executing _HID 775249663Sjkim * methods to find the EC device. 776220663Sjkim * 777249663Sjkim * MUTEX: Assumes the namespace is locked 778249663Sjkim * 779220663Sjkim ******************************************************************************/ 780220663Sjkim 781220663Sjkimstatic void 782220663SjkimAcpiEvOrphanEcRegMethod ( 783249663Sjkim ACPI_NAMESPACE_NODE *EcDeviceNode) 784220663Sjkim{ 785249663Sjkim ACPI_HANDLE RegMethod; 786249663Sjkim ACPI_NAMESPACE_NODE *NextNode; 787220663Sjkim ACPI_STATUS Status; 788220663Sjkim ACPI_OBJECT_LIST Args; 789220663Sjkim ACPI_OBJECT Objects[2]; 790220663Sjkim 791220663Sjkim 792220663Sjkim ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod); 793220663Sjkim 794220663Sjkim 795249663Sjkim if (!EcDeviceNode) 796220663Sjkim { 797220663Sjkim return_VOID; 798220663Sjkim } 799220663Sjkim 800220663Sjkim /* Namespace is currently locked, must release */ 801220663Sjkim 802220663Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 803220663Sjkim 804220663Sjkim /* Get a handle to a _REG method immediately under the EC device */ 805220663Sjkim 806249663Sjkim Status = AcpiGetHandle (EcDeviceNode, METHOD_NAME__REG, &RegMethod); 807220663Sjkim if (ACPI_FAILURE (Status)) 808220663Sjkim { 809249663Sjkim goto Exit; /* There is no _REG method present */ 810220663Sjkim } 811220663Sjkim 812220663Sjkim /* 813220663Sjkim * Execute the _REG method only if there is no Operation Region in 814220663Sjkim * this scope with the Embedded Controller space ID. Otherwise, it 815220663Sjkim * will already have been executed. Note, this allows for Regions 816220663Sjkim * with other space IDs to be present; but the code below will then 817249663Sjkim * execute the _REG method with the EmbeddedControl SpaceID argument. 818220663Sjkim */ 819220663Sjkim NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL); 820220663Sjkim while (NextNode) 821220663Sjkim { 822220663Sjkim if ((NextNode->Type == ACPI_TYPE_REGION) && 823220663Sjkim (NextNode->Object) && 824220663Sjkim (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC)) 825220663Sjkim { 826249663Sjkim goto Exit; /* Do not execute the _REG */ 827220663Sjkim } 828249663Sjkim 829220663Sjkim NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode); 830220663Sjkim } 831220663Sjkim 832249663Sjkim /* Evaluate the _REG(EmbeddedControl,Connect) method */ 833220663Sjkim 834220663Sjkim Args.Count = 2; 835220663Sjkim Args.Pointer = Objects; 836220663Sjkim Objects[0].Type = ACPI_TYPE_INTEGER; 837220663Sjkim Objects[0].Integer.Value = ACPI_ADR_SPACE_EC; 838220663Sjkim Objects[1].Type = ACPI_TYPE_INTEGER; 839220663Sjkim Objects[1].Integer.Value = ACPI_REG_CONNECT; 840220663Sjkim 841220663Sjkim Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL); 842220663Sjkim 843220663SjkimExit: 844220663Sjkim /* We ignore all errors from above, don't care */ 845220663Sjkim 846220663Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 847220663Sjkim return_VOID; 848220663Sjkim} 849