nsxfeval.c revision 217365
1100966Siwasaki/******************************************************************************* 2100966Siwasaki * 3100966Siwasaki * Module Name: nsxfeval - Public interfaces to the ACPI subsystem 4100966Siwasaki * ACPI Object evaluation interfaces 5100966Siwasaki * 6100966Siwasaki ******************************************************************************/ 7100966Siwasaki 8217365Sjkim/* 9217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp. 10100966Siwasaki * All rights reserved. 11100966Siwasaki * 12217365Sjkim * Redistribution and use in source and binary forms, with or without 13217365Sjkim * modification, are permitted provided that the following conditions 14217365Sjkim * are met: 15217365Sjkim * 1. Redistributions of source code must retain the above copyright 16217365Sjkim * notice, this list of conditions, and the following disclaimer, 17217365Sjkim * without modification. 18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 20217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 21217365Sjkim * including a substantially similar Disclaimer requirement for further 22217365Sjkim * binary redistribution. 23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 24217365Sjkim * of any contributors may be used to endorse or promote products derived 25217365Sjkim * from this software without specific prior written permission. 26100966Siwasaki * 27217365Sjkim * Alternatively, this software may be distributed under the terms of the 28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 29217365Sjkim * Software Foundation. 30100966Siwasaki * 31217365Sjkim * NO WARRANTY 32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 43217365Sjkim */ 44100966Siwasaki 45100966Siwasaki 46100966Siwasaki#define __NSXFEVAL_C__ 47100966Siwasaki 48193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 49193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 50193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 51193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 52100966Siwasaki 53100966Siwasaki 54100966Siwasaki#define _COMPONENT ACPI_NAMESPACE 55100966Siwasaki ACPI_MODULE_NAME ("nsxfeval") 56100966Siwasaki 57193267Sjkim/* Local prototypes */ 58100966Siwasaki 59193267Sjkimstatic void 60193267SjkimAcpiNsResolveReferences ( 61193267Sjkim ACPI_EVALUATE_INFO *Info); 62193267Sjkim 63193267Sjkim 64100966Siwasaki/******************************************************************************* 65100966Siwasaki * 66100966Siwasaki * FUNCTION: AcpiEvaluateObjectTyped 67100966Siwasaki * 68100966Siwasaki * PARAMETERS: Handle - Object handle (optional) 69151937Sjkim * Pathname - Object pathname (optional) 70151937Sjkim * ExternalParams - List of parameters to pass to method, 71100966Siwasaki * terminated by NULL. May be NULL 72100966Siwasaki * if no parameters are being passed. 73151937Sjkim * ReturnBuffer - Where to put method's return value (if 74100966Siwasaki * any). If NULL, no value is returned. 75100966Siwasaki * ReturnType - Expected type of return object 76100966Siwasaki * 77100966Siwasaki * RETURN: Status 78100966Siwasaki * 79100966Siwasaki * DESCRIPTION: Find and evaluate the given object, passing the given 80100966Siwasaki * parameters if necessary. One of "Handle" or "Pathname" must 81100966Siwasaki * be valid (non-null) 82100966Siwasaki * 83100966Siwasaki ******************************************************************************/ 84100966Siwasaki 85100966SiwasakiACPI_STATUS 86100966SiwasakiAcpiEvaluateObjectTyped ( 87100966Siwasaki ACPI_HANDLE Handle, 88100966Siwasaki ACPI_STRING Pathname, 89100966Siwasaki ACPI_OBJECT_LIST *ExternalParams, 90100966Siwasaki ACPI_BUFFER *ReturnBuffer, 91100966Siwasaki ACPI_OBJECT_TYPE ReturnType) 92100966Siwasaki{ 93100966Siwasaki ACPI_STATUS Status; 94100966Siwasaki BOOLEAN MustFree = FALSE; 95100966Siwasaki 96100966Siwasaki 97167802Sjkim ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped); 98100966Siwasaki 99100966Siwasaki 100100966Siwasaki /* Return buffer must be valid */ 101100966Siwasaki 102100966Siwasaki if (!ReturnBuffer) 103100966Siwasaki { 104100966Siwasaki return_ACPI_STATUS (AE_BAD_PARAMETER); 105100966Siwasaki } 106100966Siwasaki 107100966Siwasaki if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER) 108100966Siwasaki { 109100966Siwasaki MustFree = TRUE; 110100966Siwasaki } 111100966Siwasaki 112100966Siwasaki /* Evaluate the object */ 113100966Siwasaki 114100966Siwasaki Status = AcpiEvaluateObject (Handle, Pathname, ExternalParams, ReturnBuffer); 115100966Siwasaki if (ACPI_FAILURE (Status)) 116100966Siwasaki { 117100966Siwasaki return_ACPI_STATUS (Status); 118100966Siwasaki } 119100966Siwasaki 120100966Siwasaki /* Type ANY means "don't care" */ 121100966Siwasaki 122100966Siwasaki if (ReturnType == ACPI_TYPE_ANY) 123100966Siwasaki { 124100966Siwasaki return_ACPI_STATUS (AE_OK); 125100966Siwasaki } 126100966Siwasaki 127100966Siwasaki if (ReturnBuffer->Length == 0) 128100966Siwasaki { 129100966Siwasaki /* Error because caller specifically asked for a return value */ 130100966Siwasaki 131167802Sjkim ACPI_ERROR ((AE_INFO, "No return value")); 132100966Siwasaki return_ACPI_STATUS (AE_NULL_OBJECT); 133100966Siwasaki } 134100966Siwasaki 135100966Siwasaki /* Examine the object type returned from EvaluateObject */ 136100966Siwasaki 137100966Siwasaki if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType) 138100966Siwasaki { 139100966Siwasaki return_ACPI_STATUS (AE_OK); 140100966Siwasaki } 141100966Siwasaki 142100966Siwasaki /* Return object type does not match requested type */ 143100966Siwasaki 144167802Sjkim ACPI_ERROR ((AE_INFO, 145167802Sjkim "Incorrect return type [%s] requested [%s]", 146100966Siwasaki AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type), 147100966Siwasaki AcpiUtGetTypeName (ReturnType))); 148100966Siwasaki 149100966Siwasaki if (MustFree) 150100966Siwasaki { 151100966Siwasaki /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ 152100966Siwasaki 153100966Siwasaki AcpiOsFree (ReturnBuffer->Pointer); 154100966Siwasaki ReturnBuffer->Pointer = NULL; 155100966Siwasaki } 156100966Siwasaki 157100966Siwasaki ReturnBuffer->Length = 0; 158100966Siwasaki return_ACPI_STATUS (AE_TYPE); 159100966Siwasaki} 160100966Siwasaki 161167802SjkimACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped) 162100966Siwasaki 163167802Sjkim 164100966Siwasaki/******************************************************************************* 165100966Siwasaki * 166100966Siwasaki * FUNCTION: AcpiEvaluateObject 167100966Siwasaki * 168100966Siwasaki * PARAMETERS: Handle - Object handle (optional) 169128212Snjl * Pathname - Object pathname (optional) 170128212Snjl * ExternalParams - List of parameters to pass to method, 171100966Siwasaki * terminated by NULL. May be NULL 172100966Siwasaki * if no parameters are being passed. 173128212Snjl * ReturnBuffer - Where to put method's return value (if 174100966Siwasaki * any). If NULL, no value is returned. 175100966Siwasaki * 176100966Siwasaki * RETURN: Status 177100966Siwasaki * 178100966Siwasaki * DESCRIPTION: Find and evaluate the given object, passing the given 179100966Siwasaki * parameters if necessary. One of "Handle" or "Pathname" must 180100966Siwasaki * be valid (non-null) 181100966Siwasaki * 182100966Siwasaki ******************************************************************************/ 183100966Siwasaki 184100966SiwasakiACPI_STATUS 185100966SiwasakiAcpiEvaluateObject ( 186100966Siwasaki ACPI_HANDLE Handle, 187100966Siwasaki ACPI_STRING Pathname, 188100966Siwasaki ACPI_OBJECT_LIST *ExternalParams, 189100966Siwasaki ACPI_BUFFER *ReturnBuffer) 190100966Siwasaki{ 191100966Siwasaki ACPI_STATUS Status; 192167802Sjkim ACPI_EVALUATE_INFO *Info; 193100966Siwasaki ACPI_SIZE BufferSpaceNeeded; 194100966Siwasaki UINT32 i; 195100966Siwasaki 196100966Siwasaki 197167802Sjkim ACPI_FUNCTION_TRACE (AcpiEvaluateObject); 198100966Siwasaki 199100966Siwasaki 200167802Sjkim /* Allocate and initialize the evaluation information block */ 201129684Snjl 202167802Sjkim Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 203167802Sjkim if (!Info) 204167802Sjkim { 205167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 206167802Sjkim } 207167802Sjkim 208167802Sjkim Info->Pathname = Pathname; 209167802Sjkim 210167802Sjkim /* Convert and validate the device handle */ 211167802Sjkim 212200553Sjkim Info->PrefixNode = AcpiNsValidateHandle (Handle); 213167802Sjkim if (!Info->PrefixNode) 214167802Sjkim { 215167802Sjkim Status = AE_BAD_PARAMETER; 216167802Sjkim goto Cleanup; 217167802Sjkim } 218167802Sjkim 219100966Siwasaki /* 220167802Sjkim * If there are parameters to be passed to a control method, the external 221167802Sjkim * objects must all be converted to internal objects 222100966Siwasaki */ 223100966Siwasaki if (ExternalParams && ExternalParams->Count) 224100966Siwasaki { 225100966Siwasaki /* 226100966Siwasaki * Allocate a new parameter block for the internal objects 227100966Siwasaki * Add 1 to count to allow for null terminated internal list 228100966Siwasaki */ 229167802Sjkim Info->Parameters = ACPI_ALLOCATE_ZEROED ( 230167802Sjkim ((ACPI_SIZE) ExternalParams->Count + 1) * sizeof (void *)); 231167802Sjkim if (!Info->Parameters) 232100966Siwasaki { 233167802Sjkim Status = AE_NO_MEMORY; 234167802Sjkim goto Cleanup; 235100966Siwasaki } 236100966Siwasaki 237167802Sjkim /* Convert each external object in the list to an internal object */ 238167802Sjkim 239100966Siwasaki for (i = 0; i < ExternalParams->Count; i++) 240100966Siwasaki { 241167802Sjkim Status = AcpiUtCopyEobjectToIobject ( 242167802Sjkim &ExternalParams->Pointer[i], &Info->Parameters[i]); 243100966Siwasaki if (ACPI_FAILURE (Status)) 244100966Siwasaki { 245167802Sjkim goto Cleanup; 246100966Siwasaki } 247100966Siwasaki } 248167802Sjkim Info->Parameters[ExternalParams->Count] = NULL; 249100966Siwasaki } 250100966Siwasaki 251100966Siwasaki /* 252100966Siwasaki * Three major cases: 253100966Siwasaki * 1) Fully qualified pathname 254100966Siwasaki * 2) No handle, not fully qualified pathname (error) 255100966Siwasaki * 3) Valid handle 256100966Siwasaki */ 257100966Siwasaki if ((Pathname) && 258100966Siwasaki (AcpiNsValidRootPrefix (Pathname[0]))) 259100966Siwasaki { 260167802Sjkim /* The path is fully qualified, just evaluate by name */ 261167802Sjkim 262167802Sjkim Info->PrefixNode = NULL; 263167802Sjkim Status = AcpiNsEvaluate (Info); 264100966Siwasaki } 265100966Siwasaki else if (!Handle) 266100966Siwasaki { 267100966Siwasaki /* 268167802Sjkim * A handle is optional iff a fully qualified pathname is specified. 269167802Sjkim * Since we've already handled fully qualified names above, this is 270167802Sjkim * an error 271100966Siwasaki */ 272100966Siwasaki if (!Pathname) 273100966Siwasaki { 274167802Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 275167802Sjkim "Both Handle and Pathname are NULL")); 276100966Siwasaki } 277100966Siwasaki else 278100966Siwasaki { 279167802Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 280167802Sjkim "Null Handle with relative pathname [%s]", Pathname)); 281100966Siwasaki } 282100966Siwasaki 283100966Siwasaki Status = AE_BAD_PARAMETER; 284100966Siwasaki } 285100966Siwasaki else 286100966Siwasaki { 287167802Sjkim /* We have a namespace a node and a possible relative path */ 288167802Sjkim 289167802Sjkim Status = AcpiNsEvaluate (Info); 290100966Siwasaki } 291100966Siwasaki 292100966Siwasaki /* 293100966Siwasaki * If we are expecting a return value, and all went well above, 294100966Siwasaki * copy the return value to an external object. 295100966Siwasaki */ 296100966Siwasaki if (ReturnBuffer) 297100966Siwasaki { 298167802Sjkim if (!Info->ReturnObject) 299100966Siwasaki { 300100966Siwasaki ReturnBuffer->Length = 0; 301100966Siwasaki } 302100966Siwasaki else 303100966Siwasaki { 304167802Sjkim if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) == 305167802Sjkim ACPI_DESC_TYPE_NAMED) 306100966Siwasaki { 307100966Siwasaki /* 308100966Siwasaki * If we received a NS Node as a return object, this means that 309100966Siwasaki * the object we are evaluating has nothing interesting to 310100966Siwasaki * return (such as a mutex, etc.) We return an error because 311100966Siwasaki * these types are essentially unsupported by this interface. 312100966Siwasaki * We don't check up front because this makes it easier to add 313100966Siwasaki * support for various types at a later date if necessary. 314100966Siwasaki */ 315100966Siwasaki Status = AE_TYPE; 316167802Sjkim Info->ReturnObject = NULL; /* No need to delete a NS Node */ 317100966Siwasaki ReturnBuffer->Length = 0; 318100966Siwasaki } 319100966Siwasaki 320100966Siwasaki if (ACPI_SUCCESS (Status)) 321100966Siwasaki { 322193267Sjkim /* Dereference Index and RefOf references */ 323193267Sjkim 324193267Sjkim AcpiNsResolveReferences (Info); 325193267Sjkim 326167802Sjkim /* Get the size of the returned object */ 327167802Sjkim 328167802Sjkim Status = AcpiUtGetObjectSize (Info->ReturnObject, 329167802Sjkim &BufferSpaceNeeded); 330100966Siwasaki if (ACPI_SUCCESS (Status)) 331100966Siwasaki { 332100966Siwasaki /* Validate/Allocate/Clear caller buffer */ 333100966Siwasaki 334151937Sjkim Status = AcpiUtInitializeBuffer (ReturnBuffer, 335167802Sjkim BufferSpaceNeeded); 336100966Siwasaki if (ACPI_FAILURE (Status)) 337100966Siwasaki { 338100966Siwasaki /* 339167802Sjkim * Caller's buffer is too small or a new one can't 340167802Sjkim * be allocated 341100966Siwasaki */ 342100966Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 343100966Siwasaki "Needed buffer size %X, %s\n", 344129684Snjl (UINT32) BufferSpaceNeeded, 345129684Snjl AcpiFormatException (Status))); 346100966Siwasaki } 347100966Siwasaki else 348100966Siwasaki { 349167802Sjkim /* We have enough space for the object, build it */ 350167802Sjkim 351167802Sjkim Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject, 352167802Sjkim ReturnBuffer); 353100966Siwasaki } 354100966Siwasaki } 355100966Siwasaki } 356100966Siwasaki } 357100966Siwasaki } 358100966Siwasaki 359167802Sjkim if (Info->ReturnObject) 360100966Siwasaki { 361129684Snjl /* 362167802Sjkim * Delete the internal return object. NOTE: Interpreter must be 363167802Sjkim * locked to avoid race condition. 364100966Siwasaki */ 365167802Sjkim AcpiExEnterInterpreter (); 366167802Sjkim 367167802Sjkim /* Remove one reference on the return object (should delete it) */ 368167802Sjkim 369167802Sjkim AcpiUtRemoveReference (Info->ReturnObject); 370167802Sjkim AcpiExExitInterpreter (); 371100966Siwasaki } 372100966Siwasaki 373167802Sjkim 374167802SjkimCleanup: 375167802Sjkim 376167802Sjkim /* Free the input parameter list (if we created one) */ 377167802Sjkim 378167802Sjkim if (Info->Parameters) 379100966Siwasaki { 380100966Siwasaki /* Free the allocated parameter block */ 381100966Siwasaki 382167802Sjkim AcpiUtDeleteInternalObjectList (Info->Parameters); 383100966Siwasaki } 384100966Siwasaki 385167802Sjkim ACPI_FREE (Info); 386100966Siwasaki return_ACPI_STATUS (Status); 387100966Siwasaki} 388100966Siwasaki 389167802SjkimACPI_EXPORT_SYMBOL (AcpiEvaluateObject) 390100966Siwasaki 391167802Sjkim 392100966Siwasaki/******************************************************************************* 393100966Siwasaki * 394193267Sjkim * FUNCTION: AcpiNsResolveReferences 395193267Sjkim * 396193267Sjkim * PARAMETERS: Info - Evaluation info block 397193267Sjkim * 398193267Sjkim * RETURN: Info->ReturnObject is replaced with the dereferenced object 399193267Sjkim * 400193267Sjkim * DESCRIPTION: Dereference certain reference objects. Called before an 401193267Sjkim * internal return object is converted to an external ACPI_OBJECT. 402193267Sjkim * 403193267Sjkim * Performs an automatic dereference of Index and RefOf reference objects. 404193267Sjkim * These reference objects are not supported by the ACPI_OBJECT, so this is a 405193267Sjkim * last resort effort to return something useful. Also, provides compatibility 406193267Sjkim * with other ACPI implementations. 407193267Sjkim * 408193267Sjkim * NOTE: does not handle references within returned package objects or nested 409193267Sjkim * references, but this support could be added later if found to be necessary. 410193267Sjkim * 411193267Sjkim ******************************************************************************/ 412193267Sjkim 413193267Sjkimstatic void 414193267SjkimAcpiNsResolveReferences ( 415193267Sjkim ACPI_EVALUATE_INFO *Info) 416193267Sjkim{ 417193267Sjkim ACPI_OPERAND_OBJECT *ObjDesc = NULL; 418193267Sjkim ACPI_NAMESPACE_NODE *Node; 419193267Sjkim 420193267Sjkim 421193267Sjkim /* We are interested in reference objects only */ 422193267Sjkim 423193267Sjkim if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) 424193267Sjkim { 425193267Sjkim return; 426193267Sjkim } 427193267Sjkim 428193267Sjkim /* 429193267Sjkim * Two types of references are supported - those created by Index and 430193267Sjkim * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted 431193267Sjkim * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle 432193267Sjkim * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to 433193267Sjkim * an ACPI_OBJECT. 434193267Sjkim */ 435193267Sjkim switch (Info->ReturnObject->Reference.Class) 436193267Sjkim { 437193267Sjkim case ACPI_REFCLASS_INDEX: 438193267Sjkim 439193267Sjkim ObjDesc = *(Info->ReturnObject->Reference.Where); 440193267Sjkim break; 441193267Sjkim 442193267Sjkim case ACPI_REFCLASS_REFOF: 443193267Sjkim 444193267Sjkim Node = Info->ReturnObject->Reference.Object; 445193267Sjkim if (Node) 446193267Sjkim { 447193267Sjkim ObjDesc = Node->Object; 448193267Sjkim } 449193267Sjkim break; 450193267Sjkim 451193267Sjkim default: 452193267Sjkim return; 453193267Sjkim } 454193267Sjkim 455193267Sjkim /* Replace the existing reference object */ 456193267Sjkim 457193267Sjkim if (ObjDesc) 458193267Sjkim { 459193267Sjkim AcpiUtAddReference (ObjDesc); 460193267Sjkim AcpiUtRemoveReference (Info->ReturnObject); 461193267Sjkim Info->ReturnObject = ObjDesc; 462193267Sjkim } 463193267Sjkim 464193267Sjkim return; 465193267Sjkim} 466193267Sjkim 467193267Sjkim 468193267Sjkim/******************************************************************************* 469193267Sjkim * 470100966Siwasaki * FUNCTION: AcpiWalkNamespace 471100966Siwasaki * 472100966Siwasaki * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for 473100966Siwasaki * StartObject - Handle in namespace where search begins 474100966Siwasaki * MaxDepth - Depth to which search is to reach 475199337Sjkim * PreOrderVisit - Called during tree pre-order visit 476199337Sjkim * when an object of "Type" is found 477199337Sjkim * PostOrderVisit - Called during tree post-order visit 478199337Sjkim * when an object of "Type" is found 479199337Sjkim * Context - Passed to user function(s) above 480100966Siwasaki * ReturnValue - Location where return value of 481100966Siwasaki * UserFunction is put if terminated early 482100966Siwasaki * 483100966Siwasaki * RETURNS Return value from the UserFunction if terminated early. 484100966Siwasaki * Otherwise, returns NULL. 485100966Siwasaki * 486100966Siwasaki * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, 487100966Siwasaki * starting (and ending) at the object specified by StartHandle. 488199337Sjkim * The callback function is called whenever an object that matches 489199337Sjkim * the type parameter is found. If the callback function returns 490100966Siwasaki * a non-zero value, the search is terminated immediately and this 491100966Siwasaki * value is returned to the caller. 492100966Siwasaki * 493100966Siwasaki * The point of this procedure is to provide a generic namespace 494100966Siwasaki * walk routine that can be called from multiple places to 495199337Sjkim * provide multiple services; the callback function(s) can be 496199337Sjkim * tailored to each task, whether it is a print function, 497199337Sjkim * a compare function, etc. 498100966Siwasaki * 499100966Siwasaki ******************************************************************************/ 500100966Siwasaki 501100966SiwasakiACPI_STATUS 502100966SiwasakiAcpiWalkNamespace ( 503100966Siwasaki ACPI_OBJECT_TYPE Type, 504100966Siwasaki ACPI_HANDLE StartObject, 505100966Siwasaki UINT32 MaxDepth, 506199337Sjkim ACPI_WALK_CALLBACK PreOrderVisit, 507199337Sjkim ACPI_WALK_CALLBACK PostOrderVisit, 508100966Siwasaki void *Context, 509100966Siwasaki void **ReturnValue) 510100966Siwasaki{ 511100966Siwasaki ACPI_STATUS Status; 512100966Siwasaki 513100966Siwasaki 514167802Sjkim ACPI_FUNCTION_TRACE (AcpiWalkNamespace); 515100966Siwasaki 516100966Siwasaki 517100966Siwasaki /* Parameter validation */ 518100966Siwasaki 519167802Sjkim if ((Type > ACPI_TYPE_LOCAL_MAX) || 520167802Sjkim (!MaxDepth) || 521199337Sjkim (!PreOrderVisit && !PostOrderVisit)) 522100966Siwasaki { 523100966Siwasaki return_ACPI_STATUS (AE_BAD_PARAMETER); 524100966Siwasaki } 525100966Siwasaki 526100966Siwasaki /* 527193267Sjkim * Need to acquire the namespace reader lock to prevent interference 528193267Sjkim * with any concurrent table unloads (which causes the deletion of 529193267Sjkim * namespace objects). We cannot allow the deletion of a namespace node 530193267Sjkim * while the user function is using it. The exception to this are the 531193267Sjkim * nodes created and deleted during control method execution -- these 532193267Sjkim * nodes are marked as temporary nodes and are ignored by the namespace 533193267Sjkim * walk. Thus, control methods can be executed while holding the 534193267Sjkim * namespace deletion lock (and the user function can execute control 535193267Sjkim * methods.) 536100966Siwasaki */ 537193267Sjkim Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock); 538193267Sjkim if (ACPI_FAILURE (Status)) 539193267Sjkim { 540193267Sjkim return (Status); 541193267Sjkim } 542193267Sjkim 543193267Sjkim /* 544193267Sjkim * Lock the namespace around the walk. The namespace will be 545193267Sjkim * unlocked/locked around each call to the user function - since the user 546193267Sjkim * function must be allowed to make ACPICA calls itself (for example, it 547193267Sjkim * will typically execute control methods during device enumeration.) 548193267Sjkim */ 549100966Siwasaki Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 550100966Siwasaki if (ACPI_FAILURE (Status)) 551100966Siwasaki { 552193267Sjkim goto UnlockAndExit; 553100966Siwasaki } 554100966Siwasaki 555151937Sjkim Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth, 556199337Sjkim ACPI_NS_WALK_UNLOCK, PreOrderVisit, 557199337Sjkim PostOrderVisit, Context, ReturnValue); 558100966Siwasaki 559100966Siwasaki (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 560193267Sjkim 561193267SjkimUnlockAndExit: 562193267Sjkim (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock); 563100966Siwasaki return_ACPI_STATUS (Status); 564100966Siwasaki} 565100966Siwasaki 566167802SjkimACPI_EXPORT_SYMBOL (AcpiWalkNamespace) 567100966Siwasaki 568167802Sjkim 569100966Siwasaki/******************************************************************************* 570100966Siwasaki * 571100966Siwasaki * FUNCTION: AcpiNsGetDeviceCallback 572100966Siwasaki * 573100966Siwasaki * PARAMETERS: Callback from AcpiGetDevice 574100966Siwasaki * 575100966Siwasaki * RETURN: Status 576100966Siwasaki * 577100966Siwasaki * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non- 578100966Siwasaki * present devices, or if they specified a HID, it filters based 579100966Siwasaki * on that. 580100966Siwasaki * 581100966Siwasaki ******************************************************************************/ 582100966Siwasaki 583100966Siwasakistatic ACPI_STATUS 584100966SiwasakiAcpiNsGetDeviceCallback ( 585100966Siwasaki ACPI_HANDLE ObjHandle, 586100966Siwasaki UINT32 NestingLevel, 587100966Siwasaki void *Context, 588100966Siwasaki void **ReturnValue) 589100966Siwasaki{ 590117521Snjl ACPI_GET_DEVICES_INFO *Info = Context; 591100966Siwasaki ACPI_STATUS Status; 592100966Siwasaki ACPI_NAMESPACE_NODE *Node; 593100966Siwasaki UINT32 Flags; 594197104Sjkim ACPI_DEVICE_ID *Hid; 595197104Sjkim ACPI_DEVICE_ID_LIST *Cid; 596193267Sjkim UINT32 i; 597193267Sjkim BOOLEAN Found; 598197104Sjkim int NoMatch; 599100966Siwasaki 600100966Siwasaki 601100966Siwasaki Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 602100966Siwasaki if (ACPI_FAILURE (Status)) 603100966Siwasaki { 604100966Siwasaki return (Status); 605100966Siwasaki } 606100966Siwasaki 607200553Sjkim Node = AcpiNsValidateHandle (ObjHandle); 608100966Siwasaki Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 609100966Siwasaki if (ACPI_FAILURE (Status)) 610100966Siwasaki { 611100966Siwasaki return (Status); 612100966Siwasaki } 613100966Siwasaki 614100966Siwasaki if (!Node) 615100966Siwasaki { 616100966Siwasaki return (AE_BAD_PARAMETER); 617100966Siwasaki } 618100966Siwasaki 619202771Sjkim /* 620202771Sjkim * First, filter based on the device HID and CID. 621202771Sjkim * 622202771Sjkim * 01/2010: For this case where a specific HID is requested, we don't 623202771Sjkim * want to run _STA until we have an actual HID match. Thus, we will 624202771Sjkim * not unnecessarily execute _STA on devices for which the caller 625202771Sjkim * doesn't care about. Previously, _STA was executed unconditionally 626202771Sjkim * on all devices found here. 627202771Sjkim * 628202771Sjkim * A side-effect of this change is that now we will continue to search 629202771Sjkim * for a matching HID even under device trees where the parent device 630202771Sjkim * would have returned a _STA that indicates it is not present or 631202771Sjkim * not functioning (thus aborting the search on that branch). 632202771Sjkim */ 633100966Siwasaki if (Info->Hid != NULL) 634100966Siwasaki { 635100966Siwasaki Status = AcpiUtExecute_HID (Node, &Hid); 636100966Siwasaki if (Status == AE_NOT_FOUND) 637100966Siwasaki { 638100966Siwasaki return (AE_OK); 639100966Siwasaki } 640100966Siwasaki else if (ACPI_FAILURE (Status)) 641100966Siwasaki { 642100966Siwasaki return (AE_CTRL_DEPTH); 643100966Siwasaki } 644100966Siwasaki 645197104Sjkim NoMatch = ACPI_STRCMP (Hid->String, Info->Hid); 646197104Sjkim ACPI_FREE (Hid); 647197104Sjkim 648197104Sjkim if (NoMatch) 649100966Siwasaki { 650193267Sjkim /* 651193267Sjkim * HID does not match, attempt match within the 652193267Sjkim * list of Compatible IDs (CIDs) 653193267Sjkim */ 654100966Siwasaki Status = AcpiUtExecute_CID (Node, &Cid); 655100966Siwasaki if (Status == AE_NOT_FOUND) 656100966Siwasaki { 657100966Siwasaki return (AE_OK); 658100966Siwasaki } 659100966Siwasaki else if (ACPI_FAILURE (Status)) 660100966Siwasaki { 661100966Siwasaki return (AE_CTRL_DEPTH); 662100966Siwasaki } 663100966Siwasaki 664117521Snjl /* Walk the CID list */ 665100966Siwasaki 666193267Sjkim Found = FALSE; 667117521Snjl for (i = 0; i < Cid->Count; i++) 668100966Siwasaki { 669197104Sjkim if (ACPI_STRCMP (Cid->Ids[i].String, Info->Hid) == 0) 670117521Snjl { 671193267Sjkim /* Found a matching CID */ 672193267Sjkim 673193267Sjkim Found = TRUE; 674193267Sjkim break; 675117521Snjl } 676100966Siwasaki } 677193267Sjkim 678167802Sjkim ACPI_FREE (Cid); 679193267Sjkim if (!Found) 680193267Sjkim { 681193267Sjkim return (AE_OK); 682193267Sjkim } 683100966Siwasaki } 684100966Siwasaki } 685100966Siwasaki 686202771Sjkim /* Run _STA to determine if device is present */ 687202771Sjkim 688202771Sjkim Status = AcpiUtExecute_STA (Node, &Flags); 689202771Sjkim if (ACPI_FAILURE (Status)) 690202771Sjkim { 691202771Sjkim return (AE_CTRL_DEPTH); 692202771Sjkim } 693202771Sjkim 694202771Sjkim if (!(Flags & ACPI_STA_DEVICE_PRESENT) && 695202771Sjkim !(Flags & ACPI_STA_DEVICE_FUNCTIONING)) 696202771Sjkim { 697202771Sjkim /* 698202771Sjkim * Don't examine the children of the device only when the 699202771Sjkim * device is neither present nor functional. See ACPI spec, 700202771Sjkim * description of _STA for more information. 701202771Sjkim */ 702202771Sjkim return (AE_CTRL_DEPTH); 703202771Sjkim } 704202771Sjkim 705193267Sjkim /* We have a valid device, invoke the user function */ 706193267Sjkim 707151937Sjkim Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context, 708151937Sjkim ReturnValue); 709100966Siwasaki return (Status); 710100966Siwasaki} 711100966Siwasaki 712100966Siwasaki 713100966Siwasaki/******************************************************************************* 714100966Siwasaki * 715100966Siwasaki * FUNCTION: AcpiGetDevices 716100966Siwasaki * 717100966Siwasaki * PARAMETERS: HID - HID to search for. Can be NULL. 718100966Siwasaki * UserFunction - Called when a matching object is found 719100966Siwasaki * Context - Passed to user function 720100966Siwasaki * ReturnValue - Location where return value of 721100966Siwasaki * UserFunction is put if terminated early 722100966Siwasaki * 723100966Siwasaki * RETURNS Return value from the UserFunction if terminated early. 724100966Siwasaki * Otherwise, returns NULL. 725100966Siwasaki * 726100966Siwasaki * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, 727100966Siwasaki * starting (and ending) at the object specified by StartHandle. 728117521Snjl * The UserFunction is called whenever an object of type 729117521Snjl * Device is found. If the user function returns 730100966Siwasaki * a non-zero value, the search is terminated immediately and this 731100966Siwasaki * value is returned to the caller. 732100966Siwasaki * 733100966Siwasaki * This is a wrapper for WalkNamespace, but the callback performs 734193267Sjkim * additional filtering. Please see AcpiNsGetDeviceCallback. 735100966Siwasaki * 736100966Siwasaki ******************************************************************************/ 737100966Siwasaki 738100966SiwasakiACPI_STATUS 739100966SiwasakiAcpiGetDevices ( 740114237Snjl char *HID, 741100966Siwasaki ACPI_WALK_CALLBACK UserFunction, 742100966Siwasaki void *Context, 743100966Siwasaki void **ReturnValue) 744100966Siwasaki{ 745100966Siwasaki ACPI_STATUS Status; 746100966Siwasaki ACPI_GET_DEVICES_INFO Info; 747100966Siwasaki 748100966Siwasaki 749167802Sjkim ACPI_FUNCTION_TRACE (AcpiGetDevices); 750100966Siwasaki 751100966Siwasaki 752100966Siwasaki /* Parameter validation */ 753100966Siwasaki 754100966Siwasaki if (!UserFunction) 755100966Siwasaki { 756100966Siwasaki return_ACPI_STATUS (AE_BAD_PARAMETER); 757100966Siwasaki } 758100966Siwasaki 759100966Siwasaki /* 760100966Siwasaki * We're going to call their callback from OUR callback, so we need 761100966Siwasaki * to know what it is, and their context parameter. 762100966Siwasaki */ 763167802Sjkim Info.Hid = HID; 764100966Siwasaki Info.Context = Context; 765100966Siwasaki Info.UserFunction = UserFunction; 766100966Siwasaki 767100966Siwasaki /* 768100966Siwasaki * Lock the namespace around the walk. 769100966Siwasaki * The namespace will be unlocked/locked around each call 770100966Siwasaki * to the user function - since this function 771100966Siwasaki * must be allowed to make Acpi calls itself. 772100966Siwasaki */ 773100966Siwasaki Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 774100966Siwasaki if (ACPI_FAILURE (Status)) 775100966Siwasaki { 776100966Siwasaki return_ACPI_STATUS (Status); 777100966Siwasaki } 778100966Siwasaki 779167802Sjkim Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 780167802Sjkim ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, 781199337Sjkim AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue); 782100966Siwasaki 783100966Siwasaki (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 784100966Siwasaki return_ACPI_STATUS (Status); 785100966Siwasaki} 786100966Siwasaki 787167802SjkimACPI_EXPORT_SYMBOL (AcpiGetDevices) 788100966Siwasaki 789167802Sjkim 790100966Siwasaki/******************************************************************************* 791100966Siwasaki * 792100966Siwasaki * FUNCTION: AcpiAttachData 793100966Siwasaki * 794114237Snjl * PARAMETERS: ObjHandle - Namespace node 795107325Siwasaki * Handler - Handler for this attachment 796107325Siwasaki * Data - Pointer to data to be attached 797100966Siwasaki * 798100966Siwasaki * RETURN: Status 799100966Siwasaki * 800107325Siwasaki * DESCRIPTION: Attach arbitrary data and handler to a namespace node. 801100966Siwasaki * 802100966Siwasaki ******************************************************************************/ 803100966Siwasaki 804100966SiwasakiACPI_STATUS 805100966SiwasakiAcpiAttachData ( 806100966Siwasaki ACPI_HANDLE ObjHandle, 807100966Siwasaki ACPI_OBJECT_HANDLER Handler, 808100966Siwasaki void *Data) 809100966Siwasaki{ 810100966Siwasaki ACPI_NAMESPACE_NODE *Node; 811100966Siwasaki ACPI_STATUS Status; 812100966Siwasaki 813100966Siwasaki 814100966Siwasaki /* Parameter validation */ 815100966Siwasaki 816100966Siwasaki if (!ObjHandle || 817100966Siwasaki !Handler || 818100966Siwasaki !Data) 819100966Siwasaki { 820100966Siwasaki return (AE_BAD_PARAMETER); 821100966Siwasaki } 822100966Siwasaki 823100966Siwasaki Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 824100966Siwasaki if (ACPI_FAILURE (Status)) 825100966Siwasaki { 826100966Siwasaki return (Status); 827100966Siwasaki } 828100966Siwasaki 829100966Siwasaki /* Convert and validate the handle */ 830100966Siwasaki 831200553Sjkim Node = AcpiNsValidateHandle (ObjHandle); 832100966Siwasaki if (!Node) 833100966Siwasaki { 834100966Siwasaki Status = AE_BAD_PARAMETER; 835100966Siwasaki goto UnlockAndExit; 836100966Siwasaki } 837100966Siwasaki 838100966Siwasaki Status = AcpiNsAttachData (Node, Handler, Data); 839100966Siwasaki 840100966SiwasakiUnlockAndExit: 841100966Siwasaki (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 842100966Siwasaki return (Status); 843100966Siwasaki} 844100966Siwasaki 845167802SjkimACPI_EXPORT_SYMBOL (AcpiAttachData) 846100966Siwasaki 847167802Sjkim 848100966Siwasaki/******************************************************************************* 849100966Siwasaki * 850100966Siwasaki * FUNCTION: AcpiDetachData 851100966Siwasaki * 852107325Siwasaki * PARAMETERS: ObjHandle - Namespace node handle 853107325Siwasaki * Handler - Handler used in call to AcpiAttachData 854100966Siwasaki * 855100966Siwasaki * RETURN: Status 856100966Siwasaki * 857107325Siwasaki * DESCRIPTION: Remove data that was previously attached to a node. 858100966Siwasaki * 859100966Siwasaki ******************************************************************************/ 860100966Siwasaki 861100966SiwasakiACPI_STATUS 862100966SiwasakiAcpiDetachData ( 863100966Siwasaki ACPI_HANDLE ObjHandle, 864100966Siwasaki ACPI_OBJECT_HANDLER Handler) 865100966Siwasaki{ 866100966Siwasaki ACPI_NAMESPACE_NODE *Node; 867100966Siwasaki ACPI_STATUS Status; 868100966Siwasaki 869100966Siwasaki 870100966Siwasaki /* Parameter validation */ 871100966Siwasaki 872100966Siwasaki if (!ObjHandle || 873100966Siwasaki !Handler) 874100966Siwasaki { 875100966Siwasaki return (AE_BAD_PARAMETER); 876100966Siwasaki } 877100966Siwasaki 878100966Siwasaki Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 879100966Siwasaki if (ACPI_FAILURE (Status)) 880100966Siwasaki { 881100966Siwasaki return (Status); 882100966Siwasaki } 883100966Siwasaki 884100966Siwasaki /* Convert and validate the handle */ 885100966Siwasaki 886200553Sjkim Node = AcpiNsValidateHandle (ObjHandle); 887100966Siwasaki if (!Node) 888100966Siwasaki { 889100966Siwasaki Status = AE_BAD_PARAMETER; 890100966Siwasaki goto UnlockAndExit; 891100966Siwasaki } 892100966Siwasaki 893100966Siwasaki Status = AcpiNsDetachData (Node, Handler); 894100966Siwasaki 895100966SiwasakiUnlockAndExit: 896100966Siwasaki (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 897100966Siwasaki return (Status); 898100966Siwasaki} 899100966Siwasaki 900167802SjkimACPI_EXPORT_SYMBOL (AcpiDetachData) 901100966Siwasaki 902167802Sjkim 903100966Siwasaki/******************************************************************************* 904100966Siwasaki * 905100966Siwasaki * FUNCTION: AcpiGetData 906100966Siwasaki * 907107325Siwasaki * PARAMETERS: ObjHandle - Namespace node 908107325Siwasaki * Handler - Handler used in call to AttachData 909107325Siwasaki * Data - Where the data is returned 910100966Siwasaki * 911100966Siwasaki * RETURN: Status 912100966Siwasaki * 913107325Siwasaki * DESCRIPTION: Retrieve data that was previously attached to a namespace node. 914100966Siwasaki * 915100966Siwasaki ******************************************************************************/ 916100966Siwasaki 917100966SiwasakiACPI_STATUS 918100966SiwasakiAcpiGetData ( 919100966Siwasaki ACPI_HANDLE ObjHandle, 920100966Siwasaki ACPI_OBJECT_HANDLER Handler, 921100966Siwasaki void **Data) 922100966Siwasaki{ 923100966Siwasaki ACPI_NAMESPACE_NODE *Node; 924100966Siwasaki ACPI_STATUS Status; 925100966Siwasaki 926100966Siwasaki 927100966Siwasaki /* Parameter validation */ 928100966Siwasaki 929100966Siwasaki if (!ObjHandle || 930100966Siwasaki !Handler || 931100966Siwasaki !Data) 932100966Siwasaki { 933100966Siwasaki return (AE_BAD_PARAMETER); 934100966Siwasaki } 935100966Siwasaki 936100966Siwasaki Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 937100966Siwasaki if (ACPI_FAILURE (Status)) 938100966Siwasaki { 939100966Siwasaki return (Status); 940100966Siwasaki } 941100966Siwasaki 942100966Siwasaki /* Convert and validate the handle */ 943100966Siwasaki 944200553Sjkim Node = AcpiNsValidateHandle (ObjHandle); 945100966Siwasaki if (!Node) 946100966Siwasaki { 947100966Siwasaki Status = AE_BAD_PARAMETER; 948100966Siwasaki goto UnlockAndExit; 949100966Siwasaki } 950100966Siwasaki 951100966Siwasaki Status = AcpiNsGetAttachedData (Node, Handler, Data); 952100966Siwasaki 953100966SiwasakiUnlockAndExit: 954100966Siwasaki (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 955100966Siwasaki return (Status); 956100966Siwasaki} 957100966Siwasaki 958167802SjkimACPI_EXPORT_SYMBOL (AcpiGetData) 959100966Siwasaki 960167802Sjkim 961