evregion.c revision 249663
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 237117521Snjl if (RegionObj2->Extra.RegionContext) 238117521Snjl { 239117521Snjl /* The handler for this region was already installed */ 240117521Snjl 241167802Sjkim ACPI_FREE (RegionContext); 242117521Snjl } 243117521Snjl else 244117521Snjl { 245117521Snjl /* 246117521Snjl * Save the returned context for use in all accesses to 247117521Snjl * this particular region 248117521Snjl */ 249117521Snjl RegionObj2->Extra.RegionContext = RegionContext; 250117521Snjl } 251117521Snjl } 25267754Smsmith } 25367754Smsmith 254117521Snjl /* We have everything we need, we can invoke the address space handler */ 25567754Smsmith 256117521Snjl Handler = HandlerDesc->AddressSpace.Handler; 257117521Snjl 25882367Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 259117521Snjl "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", 260123315Snjl &RegionObj->Region.Handler->AddressSpace, Handler, 261193267Sjkim ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset), 262117521Snjl AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 26367754Smsmith 264228110Sjkim 265228110Sjkim /* 266228110Sjkim * Special handling for GenericSerialBus and GeneralPurposeIo: 267228110Sjkim * There are three extra parameters that must be passed to the 268228110Sjkim * handler via the context: 269228110Sjkim * 1) Connection buffer, a resource template from Connection() op. 270228110Sjkim * 2) Length of the above buffer. 271228110Sjkim * 3) Actual access length from the AccessAs() op. 272228110Sjkim */ 273228110Sjkim if (((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) || 274228110Sjkim (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) && 275228110Sjkim Context && 276228110Sjkim FieldObj) 277228110Sjkim { 278228110Sjkim /* Get the Connection (ResourceTemplate) buffer */ 279228110Sjkim 280228110Sjkim Context->Connection = FieldObj->Field.ResourceBuffer; 281228110Sjkim Context->Length = FieldObj->Field.ResourceLength; 282228110Sjkim Context->AccessLength = FieldObj->Field.AccessLength; 283228110Sjkim } 284228110Sjkim 285167802Sjkim if (!(HandlerDesc->AddressSpace.HandlerFlags & 286167802Sjkim ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) 28767754Smsmith { 28867754Smsmith /* 289117521Snjl * For handlers other than the default (supplied) handlers, we must 290117521Snjl * exit the interpreter because the handler *might* block -- we don't 291117521Snjl * know what it will do, so we can't hold the lock on the intepreter. 29267754Smsmith */ 293193267Sjkim AcpiExExitInterpreter(); 29467754Smsmith } 29567754Smsmith 296117521Snjl /* Call the handler */ 297117521Snjl 298193267Sjkim Status = Handler (Function, 299193267Sjkim (RegionObj->Region.Address + RegionOffset), BitWidth, Value, 300228110Sjkim Context, RegionObj2->Extra.RegionContext); 30167754Smsmith 30267754Smsmith if (ACPI_FAILURE (Status)) 30367754Smsmith { 304167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]", 305167802Sjkim AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 30667754Smsmith } 30767754Smsmith 308167802Sjkim if (!(HandlerDesc->AddressSpace.HandlerFlags & 309167802Sjkim ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) 31067754Smsmith { 31183174Smsmith /* 31283174Smsmith * We just returned from a non-default handler, we must re-enter the 31383174Smsmith * interpreter 31483174Smsmith */ 315193267Sjkim AcpiExEnterInterpreter (); 31667754Smsmith } 31767754Smsmith 31867754Smsmith return_ACPI_STATUS (Status); 31967754Smsmith} 32067754Smsmith 321123315Snjl 32277424Smsmith/******************************************************************************* 32367754Smsmith * 32499679Siwasaki * FUNCTION: AcpiEvDetachRegion 32567754Smsmith * 326138287Smarks * PARAMETERS: RegionObj - Region Object 327138287Smarks * AcpiNsIsLocked - Namespace Region Already Locked? 32867754Smsmith * 32967754Smsmith * RETURN: None 33067754Smsmith * 33167754Smsmith * DESCRIPTION: Break the association between the handler and the region 33267754Smsmith * this is a two way association. 33367754Smsmith * 33467754Smsmith ******************************************************************************/ 33567754Smsmith 33667754Smsmithvoid 33799679SiwasakiAcpiEvDetachRegion( 33870243Smsmith ACPI_OPERAND_OBJECT *RegionObj, 33970243Smsmith BOOLEAN AcpiNsIsLocked) 34067754Smsmith{ 34167754Smsmith ACPI_OPERAND_OBJECT *HandlerObj; 34267754Smsmith ACPI_OPERAND_OBJECT *ObjDesc; 34367754Smsmith ACPI_OPERAND_OBJECT **LastObjPtr; 34477424Smsmith ACPI_ADR_SPACE_SETUP RegionSetup; 345123315Snjl void **RegionContext; 34687031Smsmith ACPI_OPERAND_OBJECT *RegionObj2; 34767754Smsmith ACPI_STATUS Status; 34867754Smsmith 34967754Smsmith 350167802Sjkim ACPI_FUNCTION_TRACE (EvDetachRegion); 35167754Smsmith 35283174Smsmith 35387031Smsmith RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 35487031Smsmith if (!RegionObj2) 35587031Smsmith { 35699679Siwasaki return_VOID; 35787031Smsmith } 358123315Snjl RegionContext = &RegionObj2->Extra.RegionContext; 35967754Smsmith 360117521Snjl /* Get the address handler from the region object */ 361117521Snjl 362123315Snjl HandlerObj = RegionObj->Region.Handler; 36367754Smsmith if (!HandlerObj) 36467754Smsmith { 365117521Snjl /* This region has no handler, all done */ 366117521Snjl 36767754Smsmith return_VOID; 36867754Smsmith } 36967754Smsmith 370117521Snjl /* Find this region in the handler's list */ 37167754Smsmith 372117521Snjl ObjDesc = HandlerObj->AddressSpace.RegionList; 373117521Snjl LastObjPtr = &HandlerObj->AddressSpace.RegionList; 37467754Smsmith 37567754Smsmith while (ObjDesc) 37667754Smsmith { 377117521Snjl /* Is this the correct Region? */ 378117521Snjl 37967754Smsmith if (ObjDesc == RegionObj) 38067754Smsmith { 38182367Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 38282367Smsmith "Removing Region %p from address handler %p\n", 38367754Smsmith RegionObj, HandlerObj)); 384117521Snjl 385117521Snjl /* This is it, remove it from the handler's list */ 386117521Snjl 38767754Smsmith *LastObjPtr = ObjDesc->Region.Next; 388193267Sjkim ObjDesc->Region.Next = NULL; /* Must clear field */ 38967754Smsmith 39070243Smsmith if (AcpiNsIsLocked) 39170243Smsmith { 39291116Smsmith Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 39391116Smsmith if (ACPI_FAILURE (Status)) 39491116Smsmith { 39591116Smsmith return_VOID; 39691116Smsmith } 39770243Smsmith } 39870243Smsmith 399117521Snjl /* Now stop region accesses by executing the _REG method */ 400117521Snjl 401220663Sjkim Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT); 40299679Siwasaki if (ACPI_FAILURE (Status)) 40399679Siwasaki { 404167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]", 40599679Siwasaki AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 40699679Siwasaki } 40767754Smsmith 40870243Smsmith if (AcpiNsIsLocked) 40970243Smsmith { 41091116Smsmith Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 41191116Smsmith if (ACPI_FAILURE (Status)) 41291116Smsmith { 41391116Smsmith return_VOID; 41491116Smsmith } 41570243Smsmith } 41670243Smsmith 417167802Sjkim /* 418193267Sjkim * If the region has been activated, call the setup handler with 419193267Sjkim * the deactivate notification 420167802Sjkim */ 421167802Sjkim if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) 422167802Sjkim { 423167802Sjkim RegionSetup = HandlerObj->AddressSpace.Setup; 424167802Sjkim Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE, 425167802Sjkim HandlerObj->AddressSpace.Context, RegionContext); 426117521Snjl 427167802Sjkim /* Init routine may fail, Just ignore errors */ 42867754Smsmith 429167802Sjkim if (ACPI_FAILURE (Status)) 430167802Sjkim { 431167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 432167802Sjkim "from region handler - deactivate, [%s]", 433167802Sjkim AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 434167802Sjkim } 435117521Snjl 436167802Sjkim RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE); 43767754Smsmith } 43867754Smsmith 43967754Smsmith /* 440117521Snjl * Remove handler reference in the region 44167754Smsmith * 442167802Sjkim * NOTE: this doesn't mean that the region goes away, the region 443167802Sjkim * is just inaccessible as indicated to the _REG method 44467754Smsmith * 445167802Sjkim * If the region is on the handler's list, this must be the 446167802Sjkim * region's handler 44767754Smsmith */ 448123315Snjl RegionObj->Region.Handler = NULL; 449117521Snjl AcpiUtRemoveReference (HandlerObj); 45067754Smsmith 45167754Smsmith return_VOID; 452117521Snjl } 45367754Smsmith 454117521Snjl /* Walk the linked list of handlers */ 45567754Smsmith 45667754Smsmith LastObjPtr = &ObjDesc->Region.Next; 45767754Smsmith ObjDesc = ObjDesc->Region.Next; 45867754Smsmith } 45967754Smsmith 460117521Snjl /* If we get here, the region was not in the handler's region list */ 461117521Snjl 46282367Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 46382367Smsmith "Cannot remove region %p from address handler %p\n", 46467754Smsmith RegionObj, HandlerObj)); 46567754Smsmith 46667754Smsmith return_VOID; 46767754Smsmith} 46867754Smsmith 46967754Smsmith 47077424Smsmith/******************************************************************************* 47167754Smsmith * 47299679Siwasaki * FUNCTION: AcpiEvAttachRegion 47367754Smsmith * 474138287Smarks * PARAMETERS: HandlerObj - Handler Object 475138287Smarks * RegionObj - Region Object 476138287Smarks * AcpiNsIsLocked - Namespace Region Already Locked? 47767754Smsmith * 47867754Smsmith * RETURN: None 47967754Smsmith * 48067754Smsmith * DESCRIPTION: Create the association between the handler and the region 48167754Smsmith * this is a two way association. 48267754Smsmith * 48367754Smsmith ******************************************************************************/ 48467754Smsmith 48567754SmsmithACPI_STATUS 48699679SiwasakiAcpiEvAttachRegion ( 48767754Smsmith ACPI_OPERAND_OBJECT *HandlerObj, 48867754Smsmith ACPI_OPERAND_OBJECT *RegionObj, 48967754Smsmith BOOLEAN AcpiNsIsLocked) 49067754Smsmith{ 49167754Smsmith 492167802Sjkim ACPI_FUNCTION_TRACE (EvAttachRegion); 49367754Smsmith 49467754Smsmith 49583174Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 496123315Snjl "Adding Region [%4.4s] %p to address handler %p [%s]\n", 497123315Snjl AcpiUtGetNodeName (RegionObj->Region.Node), 498126372Snjl RegionObj, HandlerObj, 499123315Snjl AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 50067754Smsmith 501117521Snjl /* Link this region to the front of the handler's list */ 50267754Smsmith 503117521Snjl RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList; 504117521Snjl HandlerObj->AddressSpace.RegionList = RegionObj; 50567754Smsmith 506117521Snjl /* Install the region's handler */ 507117521Snjl 508123315Snjl if (RegionObj->Region.Handler) 509117521Snjl { 510117521Snjl return_ACPI_STATUS (AE_ALREADY_EXISTS); 511117521Snjl } 512117521Snjl 513123315Snjl RegionObj->Region.Handler = HandlerObj; 514117521Snjl AcpiUtAddReference (HandlerObj); 515117521Snjl 516123315Snjl return_ACPI_STATUS (AE_OK); 51767754Smsmith} 51867754Smsmith 51967754Smsmith 52077424Smsmith/******************************************************************************* 52167754Smsmith * 522245582Sjkim * FUNCTION: AcpiEvExecuteRegMethod 52367754Smsmith * 524245582Sjkim * PARAMETERS: RegionObj - Region object 525245582Sjkim * Function - Passed to _REG: On (1) or Off (0) 52667754Smsmith * 527245582Sjkim * RETURN: Status 52867754Smsmith * 529245582Sjkim * DESCRIPTION: Execute _REG method for a region 53067754Smsmith * 53177424Smsmith ******************************************************************************/ 53267754Smsmith 533245582SjkimACPI_STATUS 534245582SjkimAcpiEvExecuteRegMethod ( 535245582Sjkim ACPI_OPERAND_OBJECT *RegionObj, 536245582Sjkim UINT32 Function) 53767754Smsmith{ 538245582Sjkim ACPI_EVALUATE_INFO *Info; 539245582Sjkim ACPI_OPERAND_OBJECT *Args[3]; 540245582Sjkim ACPI_OPERAND_OBJECT *RegionObj2; 54167754Smsmith ACPI_STATUS Status; 54267754Smsmith 54367754Smsmith 544245582Sjkim ACPI_FUNCTION_TRACE (EvExecuteRegMethod); 54577424Smsmith 54677424Smsmith 547245582Sjkim RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 548245582Sjkim if (!RegionObj2) 54967754Smsmith { 550245582Sjkim return_ACPI_STATUS (AE_NOT_EXIST); 55167754Smsmith } 55267754Smsmith 553245582Sjkim if (RegionObj2->Extra.Method_REG == NULL) 55467754Smsmith { 555245582Sjkim return_ACPI_STATUS (AE_OK); 55667754Smsmith } 55767754Smsmith 558245582Sjkim /* Allocate and initialize the evaluation information block */ 55967754Smsmith 560245582Sjkim Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 561245582Sjkim if (!Info) 56267754Smsmith { 563245582Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 56467754Smsmith } 56567754Smsmith 566245582Sjkim Info->PrefixNode = RegionObj2->Extra.Method_REG; 567249663Sjkim Info->RelativePathname = NULL; 568245582Sjkim Info->Parameters = Args; 569245582Sjkim Info->Flags = ACPI_IGNORE_RETURN_VALUE; 570117521Snjl 57167754Smsmith /* 572245582Sjkim * The _REG method has two arguments: 57367754Smsmith * 574245582Sjkim * Arg0 - Integer: 575245582Sjkim * Operation region space ID Same value as RegionObj->Region.SpaceId 576245582Sjkim * 577245582Sjkim * Arg1 - Integer: 578245582Sjkim * connection status 1 for connecting the handler, 0 for disconnecting 579245582Sjkim * the handler (Passed as a parameter) 58067754Smsmith */ 581245582Sjkim Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId); 582245582Sjkim if (!Args[0]) 583129684Snjl { 584245582Sjkim Status = AE_NO_MEMORY; 585245582Sjkim goto Cleanup1; 586129684Snjl } 587129684Snjl 588245582Sjkim Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function); 589245582Sjkim if (!Args[1]) 590129684Snjl { 591129684Snjl Status = AE_NO_MEMORY; 592245582Sjkim goto Cleanup2; 593129684Snjl } 594129684Snjl 595245582Sjkim Args[2] = NULL; /* Terminate list */ 596129684Snjl 597245582Sjkim /* Execute the method, no return value */ 598129684Snjl 599245582Sjkim ACPI_DEBUG_EXEC ( 600245582Sjkim AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL)); 601129684Snjl 602245582Sjkim Status = AcpiNsEvaluate (Info); 603245582Sjkim AcpiUtRemoveReference (Args[1]); 604129684Snjl 605245582SjkimCleanup2: 606245582Sjkim AcpiUtRemoveReference (Args[0]); 607129684Snjl 608245582SjkimCleanup1: 609245582Sjkim ACPI_FREE (Info); 610129684Snjl return_ACPI_STATUS (Status); 611129684Snjl} 612129684Snjl 613129684Snjl 614129684Snjl/******************************************************************************* 615129684Snjl * 616129684Snjl * FUNCTION: AcpiEvExecuteRegMethods 617129684Snjl * 618129684Snjl * PARAMETERS: Node - Namespace node for the device 619129684Snjl * SpaceId - The address space ID 620129684Snjl * 621129684Snjl * RETURN: Status 622129684Snjl * 623138287Smarks * DESCRIPTION: Run all _REG methods for the input Space ID; 624129684Snjl * Note: assumes namespace is locked, or system init time. 625129684Snjl * 626129684Snjl ******************************************************************************/ 627129684Snjl 628129684SnjlACPI_STATUS 629129684SnjlAcpiEvExecuteRegMethods ( 630129684Snjl ACPI_NAMESPACE_NODE *Node, 631129684Snjl ACPI_ADR_SPACE_TYPE SpaceId) 632129684Snjl{ 633129684Snjl ACPI_STATUS Status; 634129684Snjl 635129684Snjl 636167802Sjkim ACPI_FUNCTION_TRACE (EvExecuteRegMethods); 637129684Snjl 638129684Snjl 639129684Snjl /* 640193267Sjkim * Run all _REG methods for all Operation Regions for this space ID. This 641193267Sjkim * is a separate walk in order to handle any interdependencies between 642193267Sjkim * regions and _REG methods. (i.e. handlers must be installed for all 643193267Sjkim * regions of this Space ID before we can run any _REG methods) 644129684Snjl */ 645129684Snjl Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, 646199337Sjkim ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, 647167802Sjkim &SpaceId, NULL); 648129684Snjl 649220663Sjkim /* Special case for EC: handle "orphan" _REG methods with no region */ 650220663Sjkim 651220663Sjkim if (SpaceId == ACPI_ADR_SPACE_EC) 652220663Sjkim { 653249663Sjkim AcpiEvOrphanEcRegMethod (Node); 654220663Sjkim } 655220663Sjkim 656129684Snjl return_ACPI_STATUS (Status); 657129684Snjl} 658129684Snjl 659129684Snjl 660129684Snjl/******************************************************************************* 661129684Snjl * 662123315Snjl * FUNCTION: AcpiEvRegRun 663123315Snjl * 664123315Snjl * PARAMETERS: WalkNamespace callback 665123315Snjl * 666123315Snjl * DESCRIPTION: Run _REG method for region objects of the requested spaceID 667123315Snjl * 668123315Snjl ******************************************************************************/ 66967754Smsmith 670151937Sjkimstatic ACPI_STATUS 671123315SnjlAcpiEvRegRun ( 672123315Snjl ACPI_HANDLE ObjHandle, 673123315Snjl UINT32 Level, 674123315Snjl void *Context, 675123315Snjl void **ReturnValue) 676123315Snjl{ 677123315Snjl ACPI_OPERAND_OBJECT *ObjDesc; 678123315Snjl ACPI_NAMESPACE_NODE *Node; 679129684Snjl ACPI_ADR_SPACE_TYPE SpaceId; 680123315Snjl ACPI_STATUS Status; 681123315Snjl 682123315Snjl 683129684Snjl SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context); 684123315Snjl 685123315Snjl /* Convert and validate the device handle */ 686123315Snjl 687200553Sjkim Node = AcpiNsValidateHandle (ObjHandle); 688123315Snjl if (!Node) 689123315Snjl { 690123315Snjl return (AE_BAD_PARAMETER); 691123315Snjl } 692123315Snjl 693123315Snjl /* 694193267Sjkim * We only care about regions.and objects that are allowed to have address 695193267Sjkim * space handlers 696123315Snjl */ 697123315Snjl if ((Node->Type != ACPI_TYPE_REGION) && 698123315Snjl (Node != AcpiGbl_RootNode)) 699123315Snjl { 700123315Snjl return (AE_OK); 701123315Snjl } 702123315Snjl 703123315Snjl /* Check for an existing internal object */ 704123315Snjl 705123315Snjl ObjDesc = AcpiNsGetAttachedObject (Node); 706123315Snjl if (!ObjDesc) 707123315Snjl { 708123315Snjl /* No object, just exit */ 709123315Snjl 710123315Snjl return (AE_OK); 711123315Snjl } 712123315Snjl 713123315Snjl /* Object is a Region */ 714123315Snjl 715129684Snjl if (ObjDesc->Region.SpaceId != SpaceId) 716123315Snjl { 717193267Sjkim /* This region is for a different address space, just ignore it */ 718193267Sjkim 719123315Snjl return (AE_OK); 720123315Snjl } 721123315Snjl 722220663Sjkim Status = AcpiEvExecuteRegMethod (ObjDesc, ACPI_REG_CONNECT); 723123315Snjl return (Status); 724123315Snjl} 725123315Snjl 726220663Sjkim 727220663Sjkim/******************************************************************************* 728220663Sjkim * 729220663Sjkim * FUNCTION: AcpiEvOrphanEcRegMethod 730220663Sjkim * 731249663Sjkim * PARAMETERS: EcDeviceNode - Namespace node for an EC device 732220663Sjkim * 733220663Sjkim * RETURN: None 734220663Sjkim * 735220663Sjkim * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC 736220663Sjkim * device. This is a _REG method that has no corresponding region 737220663Sjkim * within the EC device scope. The orphan _REG method appears to 738220663Sjkim * have been enabled by the description of the ECDT in the ACPI 739220663Sjkim * specification: "The availability of the region space can be 740220663Sjkim * detected by providing a _REG method object underneath the 741220663Sjkim * Embedded Controller device." 742220663Sjkim * 743249663Sjkim * To quickly access the EC device, we use the EcDeviceNode used 744249663Sjkim * during EC handler installation. Otherwise, we would need to 745249663Sjkim * perform a time consuming namespace walk, executing _HID 746249663Sjkim * methods to find the EC device. 747220663Sjkim * 748249663Sjkim * MUTEX: Assumes the namespace is locked 749249663Sjkim * 750220663Sjkim ******************************************************************************/ 751220663Sjkim 752220663Sjkimstatic void 753220663SjkimAcpiEvOrphanEcRegMethod ( 754249663Sjkim ACPI_NAMESPACE_NODE *EcDeviceNode) 755220663Sjkim{ 756249663Sjkim ACPI_HANDLE RegMethod; 757249663Sjkim ACPI_NAMESPACE_NODE *NextNode; 758220663Sjkim ACPI_STATUS Status; 759220663Sjkim ACPI_OBJECT_LIST Args; 760220663Sjkim ACPI_OBJECT Objects[2]; 761220663Sjkim 762220663Sjkim 763220663Sjkim ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod); 764220663Sjkim 765220663Sjkim 766249663Sjkim if (!EcDeviceNode) 767220663Sjkim { 768220663Sjkim return_VOID; 769220663Sjkim } 770220663Sjkim 771220663Sjkim /* Namespace is currently locked, must release */ 772220663Sjkim 773220663Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 774220663Sjkim 775220663Sjkim /* Get a handle to a _REG method immediately under the EC device */ 776220663Sjkim 777249663Sjkim Status = AcpiGetHandle (EcDeviceNode, METHOD_NAME__REG, &RegMethod); 778220663Sjkim if (ACPI_FAILURE (Status)) 779220663Sjkim { 780249663Sjkim goto Exit; /* There is no _REG method present */ 781220663Sjkim } 782220663Sjkim 783220663Sjkim /* 784220663Sjkim * Execute the _REG method only if there is no Operation Region in 785220663Sjkim * this scope with the Embedded Controller space ID. Otherwise, it 786220663Sjkim * will already have been executed. Note, this allows for Regions 787220663Sjkim * with other space IDs to be present; but the code below will then 788249663Sjkim * execute the _REG method with the EmbeddedControl SpaceID argument. 789220663Sjkim */ 790220663Sjkim NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL); 791220663Sjkim while (NextNode) 792220663Sjkim { 793220663Sjkim if ((NextNode->Type == ACPI_TYPE_REGION) && 794220663Sjkim (NextNode->Object) && 795220663Sjkim (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC)) 796220663Sjkim { 797249663Sjkim goto Exit; /* Do not execute the _REG */ 798220663Sjkim } 799249663Sjkim 800220663Sjkim NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode); 801220663Sjkim } 802220663Sjkim 803249663Sjkim /* Evaluate the _REG(EmbeddedControl,Connect) method */ 804220663Sjkim 805220663Sjkim Args.Count = 2; 806220663Sjkim Args.Pointer = Objects; 807220663Sjkim Objects[0].Type = ACPI_TYPE_INTEGER; 808220663Sjkim Objects[0].Integer.Value = ACPI_ADR_SPACE_EC; 809220663Sjkim Objects[1].Type = ACPI_TYPE_INTEGER; 810220663Sjkim Objects[1].Integer.Value = ACPI_REG_CONNECT; 811220663Sjkim 812220663Sjkim Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL); 813220663Sjkim 814220663SjkimExit: 815220663Sjkim /* We ignore all errors from above, don't care */ 816220663Sjkim 817220663Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 818220663Sjkim return_VOID; 819220663Sjkim} 820