evhandler.c revision 306536
1244971Sjkim/****************************************************************************** 2244971Sjkim * 3244971Sjkim * Module Name: evhandler - Support for Address Space handlers 4244971Sjkim * 5244971Sjkim *****************************************************************************/ 6244971Sjkim 7244971Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, 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 44245582Sjkim#include <contrib/dev/acpica/include/acpi.h> 45245582Sjkim#include <contrib/dev/acpica/include/accommon.h> 46245582Sjkim#include <contrib/dev/acpica/include/acevents.h> 47245582Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 48245582Sjkim#include <contrib/dev/acpica/include/acinterp.h> 49244971Sjkim 50244971Sjkim#define _COMPONENT ACPI_EVENTS 51244971Sjkim ACPI_MODULE_NAME ("evhandler") 52244971Sjkim 53244971Sjkim 54244971Sjkim/* Local prototypes */ 55244971Sjkim 56244971Sjkimstatic ACPI_STATUS 57244971SjkimAcpiEvInstallHandler ( 58244971Sjkim ACPI_HANDLE ObjHandle, 59244971Sjkim UINT32 Level, 60244971Sjkim void *Context, 61244971Sjkim void **ReturnValue); 62244971Sjkim 63306536Sjkim 64244971Sjkim/* These are the address spaces that will get default handlers */ 65244971Sjkim 66244971SjkimUINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] = 67244971Sjkim{ 68244971Sjkim ACPI_ADR_SPACE_SYSTEM_MEMORY, 69244971Sjkim ACPI_ADR_SPACE_SYSTEM_IO, 70244971Sjkim ACPI_ADR_SPACE_PCI_CONFIG, 71244971Sjkim ACPI_ADR_SPACE_DATA_TABLE 72244971Sjkim}; 73244971Sjkim 74244971Sjkim 75244971Sjkim/******************************************************************************* 76244971Sjkim * 77244971Sjkim * FUNCTION: AcpiEvInstallRegionHandlers 78244971Sjkim * 79244971Sjkim * PARAMETERS: None 80244971Sjkim * 81244971Sjkim * RETURN: Status 82244971Sjkim * 83244971Sjkim * DESCRIPTION: Installs the core subsystem default address space handlers. 84244971Sjkim * 85244971Sjkim ******************************************************************************/ 86244971Sjkim 87244971SjkimACPI_STATUS 88244971SjkimAcpiEvInstallRegionHandlers ( 89244971Sjkim void) 90244971Sjkim{ 91244971Sjkim ACPI_STATUS Status; 92244971Sjkim UINT32 i; 93244971Sjkim 94244971Sjkim 95244971Sjkim ACPI_FUNCTION_TRACE (EvInstallRegionHandlers); 96244971Sjkim 97244971Sjkim 98244971Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 99244971Sjkim if (ACPI_FAILURE (Status)) 100244971Sjkim { 101244971Sjkim return_ACPI_STATUS (Status); 102244971Sjkim } 103244971Sjkim 104244971Sjkim /* 105244971Sjkim * All address spaces (PCI Config, EC, SMBus) are scope dependent and 106244971Sjkim * registration must occur for a specific device. 107244971Sjkim * 108244971Sjkim * In the case of the system memory and IO address spaces there is 109244971Sjkim * currently no device associated with the address space. For these we 110244971Sjkim * use the root. 111244971Sjkim * 112244971Sjkim * We install the default PCI config space handler at the root so that 113244971Sjkim * this space is immediately available even though the we have not 114244971Sjkim * enumerated all the PCI Root Buses yet. This is to conform to the ACPI 115244971Sjkim * specification which states that the PCI config space must be always 116244971Sjkim * available -- even though we are nowhere near ready to find the PCI root 117244971Sjkim * buses at this point. 118244971Sjkim * 119244971Sjkim * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler 120244971Sjkim * has already been installed (via AcpiInstallAddressSpaceHandler). 121244971Sjkim * Similar for AE_SAME_HANDLER. 122244971Sjkim */ 123244971Sjkim for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) 124244971Sjkim { 125244971Sjkim Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode, 126306536Sjkim AcpiGbl_DefaultAddressSpaces[i], 127306536Sjkim ACPI_DEFAULT_HANDLER, NULL, NULL); 128244971Sjkim switch (Status) 129244971Sjkim { 130244971Sjkim case AE_OK: 131244971Sjkim case AE_SAME_HANDLER: 132244971Sjkim case AE_ALREADY_EXISTS: 133244971Sjkim 134244971Sjkim /* These exceptions are all OK */ 135244971Sjkim 136244971Sjkim Status = AE_OK; 137244971Sjkim break; 138244971Sjkim 139244971Sjkim default: 140244971Sjkim 141244971Sjkim goto UnlockAndExit; 142244971Sjkim } 143244971Sjkim } 144244971Sjkim 145244971SjkimUnlockAndExit: 146244971Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 147244971Sjkim return_ACPI_STATUS (Status); 148244971Sjkim} 149244971Sjkim 150244971Sjkim 151244971Sjkim/******************************************************************************* 152244971Sjkim * 153244971Sjkim * FUNCTION: AcpiEvHasDefaultHandler 154244971Sjkim * 155244971Sjkim * PARAMETERS: Node - Namespace node for the device 156244971Sjkim * SpaceId - The address space ID 157244971Sjkim * 158244971Sjkim * RETURN: TRUE if default handler is installed, FALSE otherwise 159244971Sjkim * 160244971Sjkim * DESCRIPTION: Check if the default handler is installed for the requested 161244971Sjkim * space ID. 162244971Sjkim * 163244971Sjkim ******************************************************************************/ 164244971Sjkim 165244971SjkimBOOLEAN 166244971SjkimAcpiEvHasDefaultHandler ( 167244971Sjkim ACPI_NAMESPACE_NODE *Node, 168244971Sjkim ACPI_ADR_SPACE_TYPE SpaceId) 169244971Sjkim{ 170244971Sjkim ACPI_OPERAND_OBJECT *ObjDesc; 171244971Sjkim ACPI_OPERAND_OBJECT *HandlerObj; 172244971Sjkim 173244971Sjkim 174244971Sjkim /* Must have an existing internal object */ 175244971Sjkim 176244971Sjkim ObjDesc = AcpiNsGetAttachedObject (Node); 177244971Sjkim if (ObjDesc) 178244971Sjkim { 179306536Sjkim HandlerObj = ObjDesc->CommonNotify.Handler; 180244971Sjkim 181244971Sjkim /* Walk the linked list of handlers for this object */ 182244971Sjkim 183244971Sjkim while (HandlerObj) 184244971Sjkim { 185244971Sjkim if (HandlerObj->AddressSpace.SpaceId == SpaceId) 186244971Sjkim { 187244971Sjkim if (HandlerObj->AddressSpace.HandlerFlags & 188306536Sjkim ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) 189244971Sjkim { 190244971Sjkim return (TRUE); 191244971Sjkim } 192244971Sjkim } 193244971Sjkim 194244971Sjkim HandlerObj = HandlerObj->AddressSpace.Next; 195244971Sjkim } 196244971Sjkim } 197244971Sjkim 198244971Sjkim return (FALSE); 199244971Sjkim} 200244971Sjkim 201244971Sjkim 202244971Sjkim/******************************************************************************* 203244971Sjkim * 204244971Sjkim * FUNCTION: AcpiEvInstallHandler 205244971Sjkim * 206244971Sjkim * PARAMETERS: WalkNamespace callback 207244971Sjkim * 208244971Sjkim * DESCRIPTION: This routine installs an address handler into objects that are 209244971Sjkim * of type Region or Device. 210244971Sjkim * 211244971Sjkim * If the Object is a Device, and the device has a handler of 212244971Sjkim * the same type then the search is terminated in that branch. 213244971Sjkim * 214244971Sjkim * This is because the existing handler is closer in proximity 215244971Sjkim * to any more regions than the one we are trying to install. 216244971Sjkim * 217244971Sjkim ******************************************************************************/ 218244971Sjkim 219244971Sjkimstatic ACPI_STATUS 220244971SjkimAcpiEvInstallHandler ( 221244971Sjkim ACPI_HANDLE ObjHandle, 222244971Sjkim UINT32 Level, 223244971Sjkim void *Context, 224244971Sjkim void **ReturnValue) 225244971Sjkim{ 226244971Sjkim ACPI_OPERAND_OBJECT *HandlerObj; 227244971Sjkim ACPI_OPERAND_OBJECT *NextHandlerObj; 228244971Sjkim ACPI_OPERAND_OBJECT *ObjDesc; 229244971Sjkim ACPI_NAMESPACE_NODE *Node; 230244971Sjkim ACPI_STATUS Status; 231244971Sjkim 232244971Sjkim 233244971Sjkim ACPI_FUNCTION_NAME (EvInstallHandler); 234244971Sjkim 235244971Sjkim 236244971Sjkim HandlerObj = (ACPI_OPERAND_OBJECT *) Context; 237244971Sjkim 238244971Sjkim /* Parameter validation */ 239244971Sjkim 240244971Sjkim if (!HandlerObj) 241244971Sjkim { 242244971Sjkim return (AE_OK); 243244971Sjkim } 244244971Sjkim 245244971Sjkim /* Convert and validate the device handle */ 246244971Sjkim 247244971Sjkim Node = AcpiNsValidateHandle (ObjHandle); 248244971Sjkim if (!Node) 249244971Sjkim { 250244971Sjkim return (AE_BAD_PARAMETER); 251244971Sjkim } 252244971Sjkim 253244971Sjkim /* 254244971Sjkim * We only care about regions and objects that are allowed to have 255244971Sjkim * address space handlers 256244971Sjkim */ 257244971Sjkim if ((Node->Type != ACPI_TYPE_DEVICE) && 258244971Sjkim (Node->Type != ACPI_TYPE_REGION) && 259244971Sjkim (Node != AcpiGbl_RootNode)) 260244971Sjkim { 261244971Sjkim return (AE_OK); 262244971Sjkim } 263244971Sjkim 264244971Sjkim /* Check for an existing internal object */ 265244971Sjkim 266244971Sjkim ObjDesc = AcpiNsGetAttachedObject (Node); 267244971Sjkim if (!ObjDesc) 268244971Sjkim { 269244971Sjkim /* No object, just exit */ 270244971Sjkim 271244971Sjkim return (AE_OK); 272244971Sjkim } 273244971Sjkim 274244971Sjkim /* Devices are handled different than regions */ 275244971Sjkim 276244971Sjkim if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE) 277244971Sjkim { 278244971Sjkim /* Check if this Device already has a handler for this address space */ 279244971Sjkim 280306536Sjkim NextHandlerObj = AcpiEvFindRegionHandler ( 281306536Sjkim HandlerObj->AddressSpace.SpaceId, ObjDesc->CommonNotify.Handler); 282306536Sjkim if (NextHandlerObj) 283244971Sjkim { 284244971Sjkim /* Found a handler, is it for the same address space? */ 285244971Sjkim 286306536Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 287306536Sjkim "Found handler for region [%s] in device %p(%p) handler %p\n", 288306536Sjkim AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId), 289306536Sjkim ObjDesc, NextHandlerObj, HandlerObj)); 290244971Sjkim 291306536Sjkim /* 292306536Sjkim * Since the object we found it on was a device, then it means 293306536Sjkim * that someone has already installed a handler for the branch 294306536Sjkim * of the namespace from this device on. Just bail out telling 295306536Sjkim * the walk routine to not traverse this branch. This preserves 296306536Sjkim * the scoping rule for handlers. 297306536Sjkim */ 298306536Sjkim return (AE_CTRL_DEPTH); 299244971Sjkim } 300244971Sjkim 301244971Sjkim /* 302244971Sjkim * As long as the device didn't have a handler for this space we 303244971Sjkim * don't care about it. We just ignore it and proceed. 304244971Sjkim */ 305244971Sjkim return (AE_OK); 306244971Sjkim } 307244971Sjkim 308244971Sjkim /* Object is a Region */ 309244971Sjkim 310244971Sjkim if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId) 311244971Sjkim { 312244971Sjkim /* This region is for a different address space, just ignore it */ 313244971Sjkim 314244971Sjkim return (AE_OK); 315244971Sjkim } 316244971Sjkim 317244971Sjkim /* 318244971Sjkim * Now we have a region and it is for the handler's address space type. 319244971Sjkim * 320244971Sjkim * First disconnect region for any previous handler (if any) 321244971Sjkim */ 322244971Sjkim AcpiEvDetachRegion (ObjDesc, FALSE); 323244971Sjkim 324244971Sjkim /* Connect the region to the new handler */ 325244971Sjkim 326244971Sjkim Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE); 327244971Sjkim return (Status); 328244971Sjkim} 329244971Sjkim 330244971Sjkim 331244971Sjkim/******************************************************************************* 332244971Sjkim * 333306536Sjkim * FUNCTION: AcpiEvFindRegionHandler 334306536Sjkim * 335306536Sjkim * PARAMETERS: SpaceId - The address space ID 336306536Sjkim * HandlerObj - Head of the handler object list 337306536Sjkim * 338306536Sjkim * RETURN: Matching handler object. NULL if space ID not matched 339306536Sjkim * 340306536Sjkim * DESCRIPTION: Search a handler object list for a match on the address 341306536Sjkim * space ID. 342306536Sjkim * 343306536Sjkim ******************************************************************************/ 344306536Sjkim 345306536SjkimACPI_OPERAND_OBJECT * 346306536SjkimAcpiEvFindRegionHandler ( 347306536Sjkim ACPI_ADR_SPACE_TYPE SpaceId, 348306536Sjkim ACPI_OPERAND_OBJECT *HandlerObj) 349306536Sjkim{ 350306536Sjkim 351306536Sjkim /* Walk the handler list for this device */ 352306536Sjkim 353306536Sjkim while (HandlerObj) 354306536Sjkim { 355306536Sjkim /* Same SpaceId indicates a handler is installed */ 356306536Sjkim 357306536Sjkim if (HandlerObj->AddressSpace.SpaceId == SpaceId) 358306536Sjkim { 359306536Sjkim return (HandlerObj); 360306536Sjkim } 361306536Sjkim 362306536Sjkim /* Next handler object */ 363306536Sjkim 364306536Sjkim HandlerObj = HandlerObj->AddressSpace.Next; 365306536Sjkim } 366306536Sjkim 367306536Sjkim return (NULL); 368306536Sjkim} 369306536Sjkim 370306536Sjkim 371306536Sjkim/******************************************************************************* 372306536Sjkim * 373244971Sjkim * FUNCTION: AcpiEvInstallSpaceHandler 374244971Sjkim * 375244971Sjkim * PARAMETERS: Node - Namespace node for the device 376244971Sjkim * SpaceId - The address space ID 377244971Sjkim * Handler - Address of the handler 378244971Sjkim * Setup - Address of the setup function 379244971Sjkim * Context - Value passed to the handler on each access 380244971Sjkim * 381244971Sjkim * RETURN: Status 382244971Sjkim * 383244971Sjkim * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId. 384244971Sjkim * Assumes namespace is locked 385244971Sjkim * 386244971Sjkim ******************************************************************************/ 387244971Sjkim 388244971SjkimACPI_STATUS 389244971SjkimAcpiEvInstallSpaceHandler ( 390244971Sjkim ACPI_NAMESPACE_NODE *Node, 391244971Sjkim ACPI_ADR_SPACE_TYPE SpaceId, 392244971Sjkim ACPI_ADR_SPACE_HANDLER Handler, 393244971Sjkim ACPI_ADR_SPACE_SETUP Setup, 394244971Sjkim void *Context) 395244971Sjkim{ 396244971Sjkim ACPI_OPERAND_OBJECT *ObjDesc; 397244971Sjkim ACPI_OPERAND_OBJECT *HandlerObj; 398306536Sjkim ACPI_STATUS Status = AE_OK; 399244971Sjkim ACPI_OBJECT_TYPE Type; 400306536Sjkim UINT8 Flags = 0; 401244971Sjkim 402244971Sjkim 403244971Sjkim ACPI_FUNCTION_TRACE (EvInstallSpaceHandler); 404244971Sjkim 405244971Sjkim 406244971Sjkim /* 407306536Sjkim * This registration is valid for only the types below and the root. 408306536Sjkim * The root node is where the default handlers get installed. 409244971Sjkim */ 410244971Sjkim if ((Node->Type != ACPI_TYPE_DEVICE) && 411244971Sjkim (Node->Type != ACPI_TYPE_PROCESSOR) && 412244971Sjkim (Node->Type != ACPI_TYPE_THERMAL) && 413244971Sjkim (Node != AcpiGbl_RootNode)) 414244971Sjkim { 415244971Sjkim Status = AE_BAD_PARAMETER; 416244971Sjkim goto UnlockAndExit; 417244971Sjkim } 418244971Sjkim 419244971Sjkim if (Handler == ACPI_DEFAULT_HANDLER) 420244971Sjkim { 421244971Sjkim Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; 422244971Sjkim 423244971Sjkim switch (SpaceId) 424244971Sjkim { 425244971Sjkim case ACPI_ADR_SPACE_SYSTEM_MEMORY: 426250838Sjkim 427244971Sjkim Handler = AcpiExSystemMemorySpaceHandler; 428244971Sjkim Setup = AcpiEvSystemMemoryRegionSetup; 429244971Sjkim break; 430244971Sjkim 431244971Sjkim case ACPI_ADR_SPACE_SYSTEM_IO: 432250838Sjkim 433244971Sjkim Handler = AcpiExSystemIoSpaceHandler; 434244971Sjkim Setup = AcpiEvIoSpaceRegionSetup; 435244971Sjkim break; 436244971Sjkim 437244971Sjkim case ACPI_ADR_SPACE_PCI_CONFIG: 438250838Sjkim 439244971Sjkim Handler = AcpiExPciConfigSpaceHandler; 440244971Sjkim Setup = AcpiEvPciConfigRegionSetup; 441244971Sjkim break; 442244971Sjkim 443244971Sjkim case ACPI_ADR_SPACE_CMOS: 444250838Sjkim 445244971Sjkim Handler = AcpiExCmosSpaceHandler; 446244971Sjkim Setup = AcpiEvCmosRegionSetup; 447244971Sjkim break; 448244971Sjkim 449244971Sjkim case ACPI_ADR_SPACE_PCI_BAR_TARGET: 450250838Sjkim 451244971Sjkim Handler = AcpiExPciBarSpaceHandler; 452244971Sjkim Setup = AcpiEvPciBarRegionSetup; 453244971Sjkim break; 454244971Sjkim 455244971Sjkim case ACPI_ADR_SPACE_DATA_TABLE: 456250838Sjkim 457244971Sjkim Handler = AcpiExDataTableSpaceHandler; 458244971Sjkim Setup = NULL; 459244971Sjkim break; 460244971Sjkim 461244971Sjkim default: 462250838Sjkim 463244971Sjkim Status = AE_BAD_PARAMETER; 464244971Sjkim goto UnlockAndExit; 465244971Sjkim } 466244971Sjkim } 467244971Sjkim 468244971Sjkim /* If the caller hasn't specified a setup routine, use the default */ 469244971Sjkim 470244971Sjkim if (!Setup) 471244971Sjkim { 472244971Sjkim Setup = AcpiEvDefaultRegionSetup; 473244971Sjkim } 474244971Sjkim 475244971Sjkim /* Check for an existing internal object */ 476244971Sjkim 477244971Sjkim ObjDesc = AcpiNsGetAttachedObject (Node); 478244971Sjkim if (ObjDesc) 479244971Sjkim { 480244971Sjkim /* 481306536Sjkim * The attached device object already exists. Now make sure 482306536Sjkim * the handler is not already installed. 483244971Sjkim */ 484306536Sjkim HandlerObj = AcpiEvFindRegionHandler (SpaceId, 485306536Sjkim ObjDesc->CommonNotify.Handler); 486244971Sjkim 487306536Sjkim if (HandlerObj) 488244971Sjkim { 489306536Sjkim if (HandlerObj->AddressSpace.Handler == Handler) 490244971Sjkim { 491306536Sjkim /* 492306536Sjkim * It is (relatively) OK to attempt to install the SAME 493306536Sjkim * handler twice. This can easily happen with the 494306536Sjkim * PCI_Config space. 495306536Sjkim */ 496306536Sjkim Status = AE_SAME_HANDLER; 497244971Sjkim goto UnlockAndExit; 498244971Sjkim } 499306536Sjkim else 500306536Sjkim { 501306536Sjkim /* A handler is already installed */ 502244971Sjkim 503306536Sjkim Status = AE_ALREADY_EXISTS; 504306536Sjkim } 505244971Sjkim 506306536Sjkim goto UnlockAndExit; 507244971Sjkim } 508244971Sjkim } 509244971Sjkim else 510244971Sjkim { 511244971Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 512306536Sjkim "Creating object on Device %p while installing handler\n", 513306536Sjkim Node)); 514244971Sjkim 515244971Sjkim /* ObjDesc does not exist, create one */ 516244971Sjkim 517244971Sjkim if (Node->Type == ACPI_TYPE_ANY) 518244971Sjkim { 519244971Sjkim Type = ACPI_TYPE_DEVICE; 520244971Sjkim } 521244971Sjkim else 522244971Sjkim { 523244971Sjkim Type = Node->Type; 524244971Sjkim } 525244971Sjkim 526244971Sjkim ObjDesc = AcpiUtCreateInternalObject (Type); 527244971Sjkim if (!ObjDesc) 528244971Sjkim { 529244971Sjkim Status = AE_NO_MEMORY; 530244971Sjkim goto UnlockAndExit; 531244971Sjkim } 532244971Sjkim 533244971Sjkim /* Init new descriptor */ 534244971Sjkim 535244971Sjkim ObjDesc->Common.Type = (UINT8) Type; 536244971Sjkim 537244971Sjkim /* Attach the new object to the Node */ 538244971Sjkim 539244971Sjkim Status = AcpiNsAttachObject (Node, ObjDesc, Type); 540244971Sjkim 541244971Sjkim /* Remove local reference to the object */ 542244971Sjkim 543244971Sjkim AcpiUtRemoveReference (ObjDesc); 544244971Sjkim 545244971Sjkim if (ACPI_FAILURE (Status)) 546244971Sjkim { 547244971Sjkim goto UnlockAndExit; 548244971Sjkim } 549244971Sjkim } 550244971Sjkim 551244971Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 552306536Sjkim "Installing address handler for region %s(%X) " 553306536Sjkim "on Device %4.4s %p(%p)\n", 554244971Sjkim AcpiUtGetRegionName (SpaceId), SpaceId, 555244971Sjkim AcpiUtGetNodeName (Node), Node, ObjDesc)); 556244971Sjkim 557244971Sjkim /* 558244971Sjkim * Install the handler 559244971Sjkim * 560244971Sjkim * At this point there is no existing handler. Just allocate the object 561244971Sjkim * for the handler and link it into the list. 562244971Sjkim */ 563244971Sjkim HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER); 564244971Sjkim if (!HandlerObj) 565244971Sjkim { 566244971Sjkim Status = AE_NO_MEMORY; 567244971Sjkim goto UnlockAndExit; 568244971Sjkim } 569244971Sjkim 570244971Sjkim /* Init handler obj */ 571244971Sjkim 572244971Sjkim HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId; 573244971Sjkim HandlerObj->AddressSpace.HandlerFlags = Flags; 574244971Sjkim HandlerObj->AddressSpace.RegionList = NULL; 575244971Sjkim HandlerObj->AddressSpace.Node = Node; 576244971Sjkim HandlerObj->AddressSpace.Handler = Handler; 577244971Sjkim HandlerObj->AddressSpace.Context = Context; 578306536Sjkim HandlerObj->AddressSpace.Setup = Setup; 579244971Sjkim 580244971Sjkim /* Install at head of Device.AddressSpace list */ 581244971Sjkim 582306536Sjkim HandlerObj->AddressSpace.Next = ObjDesc->CommonNotify.Handler; 583244971Sjkim 584244971Sjkim /* 585244971Sjkim * The Device object is the first reference on the HandlerObj. 586244971Sjkim * Each region that uses the handler adds a reference. 587244971Sjkim */ 588306536Sjkim ObjDesc->CommonNotify.Handler = HandlerObj; 589244971Sjkim 590244971Sjkim /* 591306536Sjkim * Walk the namespace finding all of the regions this handler will 592306536Sjkim * manage. 593244971Sjkim * 594306536Sjkim * Start at the device and search the branch toward the leaf nodes 595306536Sjkim * until either the leaf is encountered or a device is detected that 596306536Sjkim * has an address handler of the same type. 597244971Sjkim * 598306536Sjkim * In either case, back up and search down the remainder of the branch 599244971Sjkim */ 600306536Sjkim Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, 601306536Sjkim ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, 602306536Sjkim AcpiEvInstallHandler, NULL, HandlerObj, NULL); 603244971Sjkim 604244971SjkimUnlockAndExit: 605244971Sjkim return_ACPI_STATUS (Status); 606244971Sjkim} 607