evhandler.c revision 244971
1244971Sjkim/****************************************************************************** 2244971Sjkim * 3244971Sjkim * Module Name: evhandler - Support for Address Space handlers 4244971Sjkim * 5244971Sjkim *****************************************************************************/ 6244971Sjkim 7244971Sjkim/* 8244971Sjkim * Copyright (C) 2000 - 2012, Intel Corp. 9244971Sjkim * All rights reserved. 10244971Sjkim * 11244971Sjkim * Redistribution and use in source and binary forms, with or without 12244971Sjkim * modification, are permitted provided that the following conditions 13244971Sjkim * are met: 14244971Sjkim * 1. Redistributions of source code must retain the above copyright 15244971Sjkim * notice, this list of conditions, and the following disclaimer, 16244971Sjkim * without modification. 17244971Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18244971Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19244971Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20244971Sjkim * including a substantially similar Disclaimer requirement for further 21244971Sjkim * binary redistribution. 22244971Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23244971Sjkim * of any contributors may be used to endorse or promote products derived 24244971Sjkim * from this software without specific prior written permission. 25244971Sjkim * 26244971Sjkim * Alternatively, this software may be distributed under the terms of the 27244971Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28244971Sjkim * Software Foundation. 29244971Sjkim * 30244971Sjkim * NO WARRANTY 31244971Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32244971Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33244971Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34244971Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35244971Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36244971Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37244971Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38244971Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39244971Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40244971Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41244971Sjkim * POSSIBILITY OF SUCH DAMAGES. 42244971Sjkim */ 43244971Sjkim 44244971Sjkim 45244971Sjkim#define __EVHANDLER_C__ 46244971Sjkim 47244971Sjkim#include "acpi.h" 48244971Sjkim#include "accommon.h" 49244971Sjkim#include "acevents.h" 50244971Sjkim#include "acnamesp.h" 51244971Sjkim#include "acinterp.h" 52244971Sjkim 53244971Sjkim#define _COMPONENT ACPI_EVENTS 54244971Sjkim ACPI_MODULE_NAME ("evhandler") 55244971Sjkim 56244971Sjkim 57244971Sjkim/* Local prototypes */ 58244971Sjkim 59244971Sjkimstatic ACPI_STATUS 60244971SjkimAcpiEvInstallHandler ( 61244971Sjkim ACPI_HANDLE ObjHandle, 62244971Sjkim UINT32 Level, 63244971Sjkim void *Context, 64244971Sjkim void **ReturnValue); 65244971Sjkim 66244971Sjkim/* These are the address spaces that will get default handlers */ 67244971Sjkim 68244971SjkimUINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] = 69244971Sjkim{ 70244971Sjkim ACPI_ADR_SPACE_SYSTEM_MEMORY, 71244971Sjkim ACPI_ADR_SPACE_SYSTEM_IO, 72244971Sjkim ACPI_ADR_SPACE_PCI_CONFIG, 73244971Sjkim ACPI_ADR_SPACE_DATA_TABLE 74244971Sjkim}; 75244971Sjkim 76244971Sjkim 77244971Sjkim/******************************************************************************* 78244971Sjkim * 79244971Sjkim * FUNCTION: AcpiEvInstallRegionHandlers 80244971Sjkim * 81244971Sjkim * PARAMETERS: None 82244971Sjkim * 83244971Sjkim * RETURN: Status 84244971Sjkim * 85244971Sjkim * DESCRIPTION: Installs the core subsystem default address space handlers. 86244971Sjkim * 87244971Sjkim ******************************************************************************/ 88244971Sjkim 89244971SjkimACPI_STATUS 90244971SjkimAcpiEvInstallRegionHandlers ( 91244971Sjkim void) 92244971Sjkim{ 93244971Sjkim ACPI_STATUS Status; 94244971Sjkim UINT32 i; 95244971Sjkim 96244971Sjkim 97244971Sjkim ACPI_FUNCTION_TRACE (EvInstallRegionHandlers); 98244971Sjkim 99244971Sjkim 100244971Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 101244971Sjkim if (ACPI_FAILURE (Status)) 102244971Sjkim { 103244971Sjkim return_ACPI_STATUS (Status); 104244971Sjkim } 105244971Sjkim 106244971Sjkim /* 107244971Sjkim * All address spaces (PCI Config, EC, SMBus) are scope dependent and 108244971Sjkim * registration must occur for a specific device. 109244971Sjkim * 110244971Sjkim * In the case of the system memory and IO address spaces there is 111244971Sjkim * currently no device associated with the address space. For these we 112244971Sjkim * use the root. 113244971Sjkim * 114244971Sjkim * We install the default PCI config space handler at the root so that 115244971Sjkim * this space is immediately available even though the we have not 116244971Sjkim * enumerated all the PCI Root Buses yet. This is to conform to the ACPI 117244971Sjkim * specification which states that the PCI config space must be always 118244971Sjkim * available -- even though we are nowhere near ready to find the PCI root 119244971Sjkim * buses at this point. 120244971Sjkim * 121244971Sjkim * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler 122244971Sjkim * has already been installed (via AcpiInstallAddressSpaceHandler). 123244971Sjkim * Similar for AE_SAME_HANDLER. 124244971Sjkim */ 125244971Sjkim for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) 126244971Sjkim { 127244971Sjkim Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode, 128244971Sjkim AcpiGbl_DefaultAddressSpaces[i], 129244971Sjkim ACPI_DEFAULT_HANDLER, NULL, NULL); 130244971Sjkim switch (Status) 131244971Sjkim { 132244971Sjkim case AE_OK: 133244971Sjkim case AE_SAME_HANDLER: 134244971Sjkim case AE_ALREADY_EXISTS: 135244971Sjkim 136244971Sjkim /* These exceptions are all OK */ 137244971Sjkim 138244971Sjkim Status = AE_OK; 139244971Sjkim break; 140244971Sjkim 141244971Sjkim default: 142244971Sjkim 143244971Sjkim goto UnlockAndExit; 144244971Sjkim } 145244971Sjkim } 146244971Sjkim 147244971SjkimUnlockAndExit: 148244971Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 149244971Sjkim return_ACPI_STATUS (Status); 150244971Sjkim} 151244971Sjkim 152244971Sjkim 153244971Sjkim/******************************************************************************* 154244971Sjkim * 155244971Sjkim * FUNCTION: AcpiEvHasDefaultHandler 156244971Sjkim * 157244971Sjkim * PARAMETERS: Node - Namespace node for the device 158244971Sjkim * SpaceId - The address space ID 159244971Sjkim * 160244971Sjkim * RETURN: TRUE if default handler is installed, FALSE otherwise 161244971Sjkim * 162244971Sjkim * DESCRIPTION: Check if the default handler is installed for the requested 163244971Sjkim * space ID. 164244971Sjkim * 165244971Sjkim ******************************************************************************/ 166244971Sjkim 167244971SjkimBOOLEAN 168244971SjkimAcpiEvHasDefaultHandler ( 169244971Sjkim ACPI_NAMESPACE_NODE *Node, 170244971Sjkim ACPI_ADR_SPACE_TYPE SpaceId) 171244971Sjkim{ 172244971Sjkim ACPI_OPERAND_OBJECT *ObjDesc; 173244971Sjkim ACPI_OPERAND_OBJECT *HandlerObj; 174244971Sjkim 175244971Sjkim 176244971Sjkim /* Must have an existing internal object */ 177244971Sjkim 178244971Sjkim ObjDesc = AcpiNsGetAttachedObject (Node); 179244971Sjkim if (ObjDesc) 180244971Sjkim { 181244971Sjkim HandlerObj = ObjDesc->Device.Handler; 182244971Sjkim 183244971Sjkim /* Walk the linked list of handlers for this object */ 184244971Sjkim 185244971Sjkim while (HandlerObj) 186244971Sjkim { 187244971Sjkim if (HandlerObj->AddressSpace.SpaceId == SpaceId) 188244971Sjkim { 189244971Sjkim if (HandlerObj->AddressSpace.HandlerFlags & 190244971Sjkim ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) 191244971Sjkim { 192244971Sjkim return (TRUE); 193244971Sjkim } 194244971Sjkim } 195244971Sjkim 196244971Sjkim HandlerObj = HandlerObj->AddressSpace.Next; 197244971Sjkim } 198244971Sjkim } 199244971Sjkim 200244971Sjkim return (FALSE); 201244971Sjkim} 202244971Sjkim 203244971Sjkim 204244971Sjkim/******************************************************************************* 205244971Sjkim * 206244971Sjkim * FUNCTION: AcpiEvInstallHandler 207244971Sjkim * 208244971Sjkim * PARAMETERS: WalkNamespace callback 209244971Sjkim * 210244971Sjkim * DESCRIPTION: This routine installs an address handler into objects that are 211244971Sjkim * of type Region or Device. 212244971Sjkim * 213244971Sjkim * If the Object is a Device, and the device has a handler of 214244971Sjkim * the same type then the search is terminated in that branch. 215244971Sjkim * 216244971Sjkim * This is because the existing handler is closer in proximity 217244971Sjkim * to any more regions than the one we are trying to install. 218244971Sjkim * 219244971Sjkim ******************************************************************************/ 220244971Sjkim 221244971Sjkimstatic ACPI_STATUS 222244971SjkimAcpiEvInstallHandler ( 223244971Sjkim ACPI_HANDLE ObjHandle, 224244971Sjkim UINT32 Level, 225244971Sjkim void *Context, 226244971Sjkim void **ReturnValue) 227244971Sjkim{ 228244971Sjkim ACPI_OPERAND_OBJECT *HandlerObj; 229244971Sjkim ACPI_OPERAND_OBJECT *NextHandlerObj; 230244971Sjkim ACPI_OPERAND_OBJECT *ObjDesc; 231244971Sjkim ACPI_NAMESPACE_NODE *Node; 232244971Sjkim ACPI_STATUS Status; 233244971Sjkim 234244971Sjkim 235244971Sjkim ACPI_FUNCTION_NAME (EvInstallHandler); 236244971Sjkim 237244971Sjkim 238244971Sjkim HandlerObj = (ACPI_OPERAND_OBJECT *) Context; 239244971Sjkim 240244971Sjkim /* Parameter validation */ 241244971Sjkim 242244971Sjkim if (!HandlerObj) 243244971Sjkim { 244244971Sjkim return (AE_OK); 245244971Sjkim } 246244971Sjkim 247244971Sjkim /* Convert and validate the device handle */ 248244971Sjkim 249244971Sjkim Node = AcpiNsValidateHandle (ObjHandle); 250244971Sjkim if (!Node) 251244971Sjkim { 252244971Sjkim return (AE_BAD_PARAMETER); 253244971Sjkim } 254244971Sjkim 255244971Sjkim /* 256244971Sjkim * We only care about regions and objects that are allowed to have 257244971Sjkim * address space handlers 258244971Sjkim */ 259244971Sjkim if ((Node->Type != ACPI_TYPE_DEVICE) && 260244971Sjkim (Node->Type != ACPI_TYPE_REGION) && 261244971Sjkim (Node != AcpiGbl_RootNode)) 262244971Sjkim { 263244971Sjkim return (AE_OK); 264244971Sjkim } 265244971Sjkim 266244971Sjkim /* Check for an existing internal object */ 267244971Sjkim 268244971Sjkim ObjDesc = AcpiNsGetAttachedObject (Node); 269244971Sjkim if (!ObjDesc) 270244971Sjkim { 271244971Sjkim /* No object, just exit */ 272244971Sjkim 273244971Sjkim return (AE_OK); 274244971Sjkim } 275244971Sjkim 276244971Sjkim /* Devices are handled different than regions */ 277244971Sjkim 278244971Sjkim if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE) 279244971Sjkim { 280244971Sjkim /* Check if this Device already has a handler for this address space */ 281244971Sjkim 282244971Sjkim NextHandlerObj = ObjDesc->Device.Handler; 283244971Sjkim while (NextHandlerObj) 284244971Sjkim { 285244971Sjkim /* Found a handler, is it for the same address space? */ 286244971Sjkim 287244971Sjkim if (NextHandlerObj->AddressSpace.SpaceId == 288244971Sjkim HandlerObj->AddressSpace.SpaceId) 289244971Sjkim { 290244971Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 291244971Sjkim "Found handler for region [%s] in device %p(%p) " 292244971Sjkim "handler %p\n", 293244971Sjkim AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId), 294244971Sjkim ObjDesc, NextHandlerObj, HandlerObj)); 295244971Sjkim 296244971Sjkim /* 297244971Sjkim * Since the object we found it on was a device, then it 298244971Sjkim * means that someone has already installed a handler for 299244971Sjkim * the branch of the namespace from this device on. Just 300244971Sjkim * bail out telling the walk routine to not traverse this 301244971Sjkim * branch. This preserves the scoping rule for handlers. 302244971Sjkim */ 303244971Sjkim return (AE_CTRL_DEPTH); 304244971Sjkim } 305244971Sjkim 306244971Sjkim /* Walk the linked list of handlers attached to this device */ 307244971Sjkim 308244971Sjkim NextHandlerObj = NextHandlerObj->AddressSpace.Next; 309244971Sjkim } 310244971Sjkim 311244971Sjkim /* 312244971Sjkim * As long as the device didn't have a handler for this space we 313244971Sjkim * don't care about it. We just ignore it and proceed. 314244971Sjkim */ 315244971Sjkim return (AE_OK); 316244971Sjkim } 317244971Sjkim 318244971Sjkim /* Object is a Region */ 319244971Sjkim 320244971Sjkim if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId) 321244971Sjkim { 322244971Sjkim /* This region is for a different address space, just ignore it */ 323244971Sjkim 324244971Sjkim return (AE_OK); 325244971Sjkim } 326244971Sjkim 327244971Sjkim /* 328244971Sjkim * Now we have a region and it is for the handler's address space type. 329244971Sjkim * 330244971Sjkim * First disconnect region for any previous handler (if any) 331244971Sjkim */ 332244971Sjkim AcpiEvDetachRegion (ObjDesc, FALSE); 333244971Sjkim 334244971Sjkim /* Connect the region to the new handler */ 335244971Sjkim 336244971Sjkim Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE); 337244971Sjkim return (Status); 338244971Sjkim} 339244971Sjkim 340244971Sjkim 341244971Sjkim/******************************************************************************* 342244971Sjkim * 343244971Sjkim * FUNCTION: AcpiEvInstallSpaceHandler 344244971Sjkim * 345244971Sjkim * PARAMETERS: Node - Namespace node for the device 346244971Sjkim * SpaceId - The address space ID 347244971Sjkim * Handler - Address of the handler 348244971Sjkim * Setup - Address of the setup function 349244971Sjkim * Context - Value passed to the handler on each access 350244971Sjkim * 351244971Sjkim * RETURN: Status 352244971Sjkim * 353244971Sjkim * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId. 354244971Sjkim * Assumes namespace is locked 355244971Sjkim * 356244971Sjkim ******************************************************************************/ 357244971Sjkim 358244971SjkimACPI_STATUS 359244971SjkimAcpiEvInstallSpaceHandler ( 360244971Sjkim ACPI_NAMESPACE_NODE *Node, 361244971Sjkim ACPI_ADR_SPACE_TYPE SpaceId, 362244971Sjkim ACPI_ADR_SPACE_HANDLER Handler, 363244971Sjkim ACPI_ADR_SPACE_SETUP Setup, 364244971Sjkim void *Context) 365244971Sjkim{ 366244971Sjkim ACPI_OPERAND_OBJECT *ObjDesc; 367244971Sjkim ACPI_OPERAND_OBJECT *HandlerObj; 368244971Sjkim ACPI_STATUS Status; 369244971Sjkim ACPI_OBJECT_TYPE Type; 370244971Sjkim UINT8 Flags = 0; 371244971Sjkim 372244971Sjkim 373244971Sjkim ACPI_FUNCTION_TRACE (EvInstallSpaceHandler); 374244971Sjkim 375244971Sjkim 376244971Sjkim /* 377244971Sjkim * This registration is valid for only the types below and the root. This 378244971Sjkim * is where the default handlers get placed. 379244971Sjkim */ 380244971Sjkim if ((Node->Type != ACPI_TYPE_DEVICE) && 381244971Sjkim (Node->Type != ACPI_TYPE_PROCESSOR) && 382244971Sjkim (Node->Type != ACPI_TYPE_THERMAL) && 383244971Sjkim (Node != AcpiGbl_RootNode)) 384244971Sjkim { 385244971Sjkim Status = AE_BAD_PARAMETER; 386244971Sjkim goto UnlockAndExit; 387244971Sjkim } 388244971Sjkim 389244971Sjkim if (Handler == ACPI_DEFAULT_HANDLER) 390244971Sjkim { 391244971Sjkim Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; 392244971Sjkim 393244971Sjkim switch (SpaceId) 394244971Sjkim { 395244971Sjkim case ACPI_ADR_SPACE_SYSTEM_MEMORY: 396244971Sjkim Handler = AcpiExSystemMemorySpaceHandler; 397244971Sjkim Setup = AcpiEvSystemMemoryRegionSetup; 398244971Sjkim break; 399244971Sjkim 400244971Sjkim case ACPI_ADR_SPACE_SYSTEM_IO: 401244971Sjkim Handler = AcpiExSystemIoSpaceHandler; 402244971Sjkim Setup = AcpiEvIoSpaceRegionSetup; 403244971Sjkim break; 404244971Sjkim 405244971Sjkim case ACPI_ADR_SPACE_PCI_CONFIG: 406244971Sjkim Handler = AcpiExPciConfigSpaceHandler; 407244971Sjkim Setup = AcpiEvPciConfigRegionSetup; 408244971Sjkim break; 409244971Sjkim 410244971Sjkim case ACPI_ADR_SPACE_CMOS: 411244971Sjkim Handler = AcpiExCmosSpaceHandler; 412244971Sjkim Setup = AcpiEvCmosRegionSetup; 413244971Sjkim break; 414244971Sjkim 415244971Sjkim case ACPI_ADR_SPACE_PCI_BAR_TARGET: 416244971Sjkim Handler = AcpiExPciBarSpaceHandler; 417244971Sjkim Setup = AcpiEvPciBarRegionSetup; 418244971Sjkim break; 419244971Sjkim 420244971Sjkim case ACPI_ADR_SPACE_DATA_TABLE: 421244971Sjkim Handler = AcpiExDataTableSpaceHandler; 422244971Sjkim Setup = NULL; 423244971Sjkim break; 424244971Sjkim 425244971Sjkim default: 426244971Sjkim Status = AE_BAD_PARAMETER; 427244971Sjkim goto UnlockAndExit; 428244971Sjkim } 429244971Sjkim } 430244971Sjkim 431244971Sjkim /* If the caller hasn't specified a setup routine, use the default */ 432244971Sjkim 433244971Sjkim if (!Setup) 434244971Sjkim { 435244971Sjkim Setup = AcpiEvDefaultRegionSetup; 436244971Sjkim } 437244971Sjkim 438244971Sjkim /* Check for an existing internal object */ 439244971Sjkim 440244971Sjkim ObjDesc = AcpiNsGetAttachedObject (Node); 441244971Sjkim if (ObjDesc) 442244971Sjkim { 443244971Sjkim /* 444244971Sjkim * The attached device object already exists. Make sure the handler 445244971Sjkim * is not already installed. 446244971Sjkim */ 447244971Sjkim HandlerObj = ObjDesc->Device.Handler; 448244971Sjkim 449244971Sjkim /* Walk the handler list for this device */ 450244971Sjkim 451244971Sjkim while (HandlerObj) 452244971Sjkim { 453244971Sjkim /* Same SpaceId indicates a handler already installed */ 454244971Sjkim 455244971Sjkim if (HandlerObj->AddressSpace.SpaceId == SpaceId) 456244971Sjkim { 457244971Sjkim if (HandlerObj->AddressSpace.Handler == Handler) 458244971Sjkim { 459244971Sjkim /* 460244971Sjkim * It is (relatively) OK to attempt to install the SAME 461244971Sjkim * handler twice. This can easily happen with the 462244971Sjkim * PCI_Config space. 463244971Sjkim */ 464244971Sjkim Status = AE_SAME_HANDLER; 465244971Sjkim goto UnlockAndExit; 466244971Sjkim } 467244971Sjkim else 468244971Sjkim { 469244971Sjkim /* A handler is already installed */ 470244971Sjkim 471244971Sjkim Status = AE_ALREADY_EXISTS; 472244971Sjkim } 473244971Sjkim goto UnlockAndExit; 474244971Sjkim } 475244971Sjkim 476244971Sjkim /* Walk the linked list of handlers */ 477244971Sjkim 478244971Sjkim HandlerObj = HandlerObj->AddressSpace.Next; 479244971Sjkim } 480244971Sjkim } 481244971Sjkim else 482244971Sjkim { 483244971Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 484244971Sjkim "Creating object on Device %p while installing handler\n", Node)); 485244971Sjkim 486244971Sjkim /* ObjDesc does not exist, create one */ 487244971Sjkim 488244971Sjkim if (Node->Type == ACPI_TYPE_ANY) 489244971Sjkim { 490244971Sjkim Type = ACPI_TYPE_DEVICE; 491244971Sjkim } 492244971Sjkim else 493244971Sjkim { 494244971Sjkim Type = Node->Type; 495244971Sjkim } 496244971Sjkim 497244971Sjkim ObjDesc = AcpiUtCreateInternalObject (Type); 498244971Sjkim if (!ObjDesc) 499244971Sjkim { 500244971Sjkim Status = AE_NO_MEMORY; 501244971Sjkim goto UnlockAndExit; 502244971Sjkim } 503244971Sjkim 504244971Sjkim /* Init new descriptor */ 505244971Sjkim 506244971Sjkim ObjDesc->Common.Type = (UINT8) Type; 507244971Sjkim 508244971Sjkim /* Attach the new object to the Node */ 509244971Sjkim 510244971Sjkim Status = AcpiNsAttachObject (Node, ObjDesc, Type); 511244971Sjkim 512244971Sjkim /* Remove local reference to the object */ 513244971Sjkim 514244971Sjkim AcpiUtRemoveReference (ObjDesc); 515244971Sjkim 516244971Sjkim if (ACPI_FAILURE (Status)) 517244971Sjkim { 518244971Sjkim goto UnlockAndExit; 519244971Sjkim } 520244971Sjkim } 521244971Sjkim 522244971Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 523244971Sjkim "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", 524244971Sjkim AcpiUtGetRegionName (SpaceId), SpaceId, 525244971Sjkim AcpiUtGetNodeName (Node), Node, ObjDesc)); 526244971Sjkim 527244971Sjkim /* 528244971Sjkim * Install the handler 529244971Sjkim * 530244971Sjkim * At this point there is no existing handler. Just allocate the object 531244971Sjkim * for the handler and link it into the list. 532244971Sjkim */ 533244971Sjkim HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER); 534244971Sjkim if (!HandlerObj) 535244971Sjkim { 536244971Sjkim Status = AE_NO_MEMORY; 537244971Sjkim goto UnlockAndExit; 538244971Sjkim } 539244971Sjkim 540244971Sjkim /* Init handler obj */ 541244971Sjkim 542244971Sjkim HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId; 543244971Sjkim HandlerObj->AddressSpace.HandlerFlags = Flags; 544244971Sjkim HandlerObj->AddressSpace.RegionList = NULL; 545244971Sjkim HandlerObj->AddressSpace.Node = Node; 546244971Sjkim HandlerObj->AddressSpace.Handler = Handler; 547244971Sjkim HandlerObj->AddressSpace.Context = Context; 548244971Sjkim HandlerObj->AddressSpace.Setup = Setup; 549244971Sjkim 550244971Sjkim /* Install at head of Device.AddressSpace list */ 551244971Sjkim 552244971Sjkim HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler; 553244971Sjkim 554244971Sjkim /* 555244971Sjkim * The Device object is the first reference on the HandlerObj. 556244971Sjkim * Each region that uses the handler adds a reference. 557244971Sjkim */ 558244971Sjkim ObjDesc->Device.Handler = HandlerObj; 559244971Sjkim 560244971Sjkim /* 561244971Sjkim * Walk the namespace finding all of the regions this 562244971Sjkim * handler will manage. 563244971Sjkim * 564244971Sjkim * Start at the device and search the branch toward 565244971Sjkim * the leaf nodes until either the leaf is encountered or 566244971Sjkim * a device is detected that has an address handler of the 567244971Sjkim * same type. 568244971Sjkim * 569244971Sjkim * In either case, back up and search down the remainder 570244971Sjkim * of the branch 571244971Sjkim */ 572244971Sjkim Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, 573244971Sjkim ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL, 574244971Sjkim HandlerObj, NULL); 575244971Sjkim 576244971SjkimUnlockAndExit: 577244971Sjkim return_ACPI_STATUS (Status); 578244971Sjkim} 579