1efcc2a30SJung-uk Kim /****************************************************************************** 2efcc2a30SJung-uk Kim * 3efcc2a30SJung-uk Kim * Module Name: evhandler - Support for Address Space handlers 4efcc2a30SJung-uk Kim * 5efcc2a30SJung-uk Kim *****************************************************************************/ 6efcc2a30SJung-uk Kim 7efcc2a30SJung-uk Kim /* 8efcc2a30SJung-uk Kim * Copyright (C) 2000 - 2013, Intel Corp. 9efcc2a30SJung-uk Kim * All rights reserved. 10efcc2a30SJung-uk Kim * 11efcc2a30SJung-uk Kim * Redistribution and use in source and binary forms, with or without 12efcc2a30SJung-uk Kim * modification, are permitted provided that the following conditions 13efcc2a30SJung-uk Kim * are met: 14efcc2a30SJung-uk Kim * 1. Redistributions of source code must retain the above copyright 15efcc2a30SJung-uk Kim * notice, this list of conditions, and the following disclaimer, 16efcc2a30SJung-uk Kim * without modification. 17efcc2a30SJung-uk Kim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18efcc2a30SJung-uk Kim * substantially similar to the "NO WARRANTY" disclaimer below 19efcc2a30SJung-uk Kim * ("Disclaimer") and any redistribution must be conditioned upon 20efcc2a30SJung-uk Kim * including a substantially similar Disclaimer requirement for further 21efcc2a30SJung-uk Kim * binary redistribution. 22efcc2a30SJung-uk Kim * 3. Neither the names of the above-listed copyright holders nor the names 23efcc2a30SJung-uk Kim * of any contributors may be used to endorse or promote products derived 24efcc2a30SJung-uk Kim * from this software without specific prior written permission. 25efcc2a30SJung-uk Kim * 26efcc2a30SJung-uk Kim * Alternatively, this software may be distributed under the terms of the 27efcc2a30SJung-uk Kim * GNU General Public License ("GPL") version 2 as published by the Free 28efcc2a30SJung-uk Kim * Software Foundation. 29efcc2a30SJung-uk Kim * 30efcc2a30SJung-uk Kim * NO WARRANTY 31efcc2a30SJung-uk Kim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32efcc2a30SJung-uk Kim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33efcc2a30SJung-uk Kim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34efcc2a30SJung-uk Kim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35efcc2a30SJung-uk Kim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36efcc2a30SJung-uk Kim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37efcc2a30SJung-uk Kim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38efcc2a30SJung-uk Kim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39efcc2a30SJung-uk Kim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40efcc2a30SJung-uk Kim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41efcc2a30SJung-uk Kim * POSSIBILITY OF SUCH DAMAGES. 42efcc2a30SJung-uk Kim */ 43efcc2a30SJung-uk Kim 44efcc2a30SJung-uk Kim 45efcc2a30SJung-uk Kim #define __EVHANDLER_C__ 46efcc2a30SJung-uk Kim 47efcc2a30SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h> 48efcc2a30SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h> 49efcc2a30SJung-uk Kim #include <contrib/dev/acpica/include/acevents.h> 50efcc2a30SJung-uk Kim #include <contrib/dev/acpica/include/acnamesp.h> 51efcc2a30SJung-uk Kim #include <contrib/dev/acpica/include/acinterp.h> 52efcc2a30SJung-uk Kim 53efcc2a30SJung-uk Kim #define _COMPONENT ACPI_EVENTS 54efcc2a30SJung-uk Kim ACPI_MODULE_NAME ("evhandler") 55efcc2a30SJung-uk Kim 56efcc2a30SJung-uk Kim 57efcc2a30SJung-uk Kim /* Local prototypes */ 58efcc2a30SJung-uk Kim 59efcc2a30SJung-uk Kim static ACPI_STATUS 60efcc2a30SJung-uk Kim AcpiEvInstallHandler ( 61efcc2a30SJung-uk Kim ACPI_HANDLE ObjHandle, 62efcc2a30SJung-uk Kim UINT32 Level, 63efcc2a30SJung-uk Kim void *Context, 64efcc2a30SJung-uk Kim void **ReturnValue); 65efcc2a30SJung-uk Kim 66efcc2a30SJung-uk Kim /* These are the address spaces that will get default handlers */ 67efcc2a30SJung-uk Kim 68efcc2a30SJung-uk Kim UINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] = 69efcc2a30SJung-uk Kim { 70efcc2a30SJung-uk Kim ACPI_ADR_SPACE_SYSTEM_MEMORY, 71efcc2a30SJung-uk Kim ACPI_ADR_SPACE_SYSTEM_IO, 72efcc2a30SJung-uk Kim ACPI_ADR_SPACE_PCI_CONFIG, 73efcc2a30SJung-uk Kim ACPI_ADR_SPACE_DATA_TABLE 74efcc2a30SJung-uk Kim }; 75efcc2a30SJung-uk Kim 76efcc2a30SJung-uk Kim 77efcc2a30SJung-uk Kim /******************************************************************************* 78efcc2a30SJung-uk Kim * 79efcc2a30SJung-uk Kim * FUNCTION: AcpiEvInstallRegionHandlers 80efcc2a30SJung-uk Kim * 81efcc2a30SJung-uk Kim * PARAMETERS: None 82efcc2a30SJung-uk Kim * 83efcc2a30SJung-uk Kim * RETURN: Status 84efcc2a30SJung-uk Kim * 85efcc2a30SJung-uk Kim * DESCRIPTION: Installs the core subsystem default address space handlers. 86efcc2a30SJung-uk Kim * 87efcc2a30SJung-uk Kim ******************************************************************************/ 88efcc2a30SJung-uk Kim 89efcc2a30SJung-uk Kim ACPI_STATUS 90efcc2a30SJung-uk Kim AcpiEvInstallRegionHandlers ( 91efcc2a30SJung-uk Kim void) 92efcc2a30SJung-uk Kim { 93efcc2a30SJung-uk Kim ACPI_STATUS Status; 94efcc2a30SJung-uk Kim UINT32 i; 95efcc2a30SJung-uk Kim 96efcc2a30SJung-uk Kim 97efcc2a30SJung-uk Kim ACPI_FUNCTION_TRACE (EvInstallRegionHandlers); 98efcc2a30SJung-uk Kim 99efcc2a30SJung-uk Kim 100efcc2a30SJung-uk Kim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 101efcc2a30SJung-uk Kim if (ACPI_FAILURE (Status)) 102efcc2a30SJung-uk Kim { 103efcc2a30SJung-uk Kim return_ACPI_STATUS (Status); 104efcc2a30SJung-uk Kim } 105efcc2a30SJung-uk Kim 106efcc2a30SJung-uk Kim /* 107efcc2a30SJung-uk Kim * All address spaces (PCI Config, EC, SMBus) are scope dependent and 108efcc2a30SJung-uk Kim * registration must occur for a specific device. 109efcc2a30SJung-uk Kim * 110efcc2a30SJung-uk Kim * In the case of the system memory and IO address spaces there is 111efcc2a30SJung-uk Kim * currently no device associated with the address space. For these we 112efcc2a30SJung-uk Kim * use the root. 113efcc2a30SJung-uk Kim * 114efcc2a30SJung-uk Kim * We install the default PCI config space handler at the root so that 115efcc2a30SJung-uk Kim * this space is immediately available even though the we have not 116efcc2a30SJung-uk Kim * enumerated all the PCI Root Buses yet. This is to conform to the ACPI 117efcc2a30SJung-uk Kim * specification which states that the PCI config space must be always 118efcc2a30SJung-uk Kim * available -- even though we are nowhere near ready to find the PCI root 119efcc2a30SJung-uk Kim * buses at this point. 120efcc2a30SJung-uk Kim * 121efcc2a30SJung-uk Kim * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler 122efcc2a30SJung-uk Kim * has already been installed (via AcpiInstallAddressSpaceHandler). 123efcc2a30SJung-uk Kim * Similar for AE_SAME_HANDLER. 124efcc2a30SJung-uk Kim */ 125efcc2a30SJung-uk Kim for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) 126efcc2a30SJung-uk Kim { 127efcc2a30SJung-uk Kim Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode, 128efcc2a30SJung-uk Kim AcpiGbl_DefaultAddressSpaces[i], 129efcc2a30SJung-uk Kim ACPI_DEFAULT_HANDLER, NULL, NULL); 130efcc2a30SJung-uk Kim switch (Status) 131efcc2a30SJung-uk Kim { 132efcc2a30SJung-uk Kim case AE_OK: 133efcc2a30SJung-uk Kim case AE_SAME_HANDLER: 134efcc2a30SJung-uk Kim case AE_ALREADY_EXISTS: 135efcc2a30SJung-uk Kim 136efcc2a30SJung-uk Kim /* These exceptions are all OK */ 137efcc2a30SJung-uk Kim 138efcc2a30SJung-uk Kim Status = AE_OK; 139efcc2a30SJung-uk Kim break; 140efcc2a30SJung-uk Kim 141efcc2a30SJung-uk Kim default: 142efcc2a30SJung-uk Kim 143efcc2a30SJung-uk Kim goto UnlockAndExit; 144efcc2a30SJung-uk Kim } 145efcc2a30SJung-uk Kim } 146efcc2a30SJung-uk Kim 147efcc2a30SJung-uk Kim UnlockAndExit: 148efcc2a30SJung-uk Kim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 149efcc2a30SJung-uk Kim return_ACPI_STATUS (Status); 150efcc2a30SJung-uk Kim } 151efcc2a30SJung-uk Kim 152efcc2a30SJung-uk Kim 153efcc2a30SJung-uk Kim /******************************************************************************* 154efcc2a30SJung-uk Kim * 155efcc2a30SJung-uk Kim * FUNCTION: AcpiEvHasDefaultHandler 156efcc2a30SJung-uk Kim * 157efcc2a30SJung-uk Kim * PARAMETERS: Node - Namespace node for the device 158efcc2a30SJung-uk Kim * SpaceId - The address space ID 159efcc2a30SJung-uk Kim * 160efcc2a30SJung-uk Kim * RETURN: TRUE if default handler is installed, FALSE otherwise 161efcc2a30SJung-uk Kim * 162efcc2a30SJung-uk Kim * DESCRIPTION: Check if the default handler is installed for the requested 163efcc2a30SJung-uk Kim * space ID. 164efcc2a30SJung-uk Kim * 165efcc2a30SJung-uk Kim ******************************************************************************/ 166efcc2a30SJung-uk Kim 167efcc2a30SJung-uk Kim BOOLEAN 168efcc2a30SJung-uk Kim AcpiEvHasDefaultHandler ( 169efcc2a30SJung-uk Kim ACPI_NAMESPACE_NODE *Node, 170efcc2a30SJung-uk Kim ACPI_ADR_SPACE_TYPE SpaceId) 171efcc2a30SJung-uk Kim { 172efcc2a30SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc; 173efcc2a30SJung-uk Kim ACPI_OPERAND_OBJECT *HandlerObj; 174efcc2a30SJung-uk Kim 175efcc2a30SJung-uk Kim 176efcc2a30SJung-uk Kim /* Must have an existing internal object */ 177efcc2a30SJung-uk Kim 178efcc2a30SJung-uk Kim ObjDesc = AcpiNsGetAttachedObject (Node); 179efcc2a30SJung-uk Kim if (ObjDesc) 180efcc2a30SJung-uk Kim { 181efcc2a30SJung-uk Kim HandlerObj = ObjDesc->Device.Handler; 182efcc2a30SJung-uk Kim 183efcc2a30SJung-uk Kim /* Walk the linked list of handlers for this object */ 184efcc2a30SJung-uk Kim 185efcc2a30SJung-uk Kim while (HandlerObj) 186efcc2a30SJung-uk Kim { 187efcc2a30SJung-uk Kim if (HandlerObj->AddressSpace.SpaceId == SpaceId) 188efcc2a30SJung-uk Kim { 189efcc2a30SJung-uk Kim if (HandlerObj->AddressSpace.HandlerFlags & 190efcc2a30SJung-uk Kim ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) 191efcc2a30SJung-uk Kim { 192efcc2a30SJung-uk Kim return (TRUE); 193efcc2a30SJung-uk Kim } 194efcc2a30SJung-uk Kim } 195efcc2a30SJung-uk Kim 196efcc2a30SJung-uk Kim HandlerObj = HandlerObj->AddressSpace.Next; 197efcc2a30SJung-uk Kim } 198efcc2a30SJung-uk Kim } 199efcc2a30SJung-uk Kim 200efcc2a30SJung-uk Kim return (FALSE); 201efcc2a30SJung-uk Kim } 202efcc2a30SJung-uk Kim 203efcc2a30SJung-uk Kim 204efcc2a30SJung-uk Kim /******************************************************************************* 205efcc2a30SJung-uk Kim * 206efcc2a30SJung-uk Kim * FUNCTION: AcpiEvInstallHandler 207efcc2a30SJung-uk Kim * 208efcc2a30SJung-uk Kim * PARAMETERS: WalkNamespace callback 209efcc2a30SJung-uk Kim * 210efcc2a30SJung-uk Kim * DESCRIPTION: This routine installs an address handler into objects that are 211efcc2a30SJung-uk Kim * of type Region or Device. 212efcc2a30SJung-uk Kim * 213efcc2a30SJung-uk Kim * If the Object is a Device, and the device has a handler of 214efcc2a30SJung-uk Kim * the same type then the search is terminated in that branch. 215efcc2a30SJung-uk Kim * 216efcc2a30SJung-uk Kim * This is because the existing handler is closer in proximity 217efcc2a30SJung-uk Kim * to any more regions than the one we are trying to install. 218efcc2a30SJung-uk Kim * 219efcc2a30SJung-uk Kim ******************************************************************************/ 220efcc2a30SJung-uk Kim 221efcc2a30SJung-uk Kim static ACPI_STATUS 222efcc2a30SJung-uk Kim AcpiEvInstallHandler ( 223efcc2a30SJung-uk Kim ACPI_HANDLE ObjHandle, 224efcc2a30SJung-uk Kim UINT32 Level, 225efcc2a30SJung-uk Kim void *Context, 226efcc2a30SJung-uk Kim void **ReturnValue) 227efcc2a30SJung-uk Kim { 228efcc2a30SJung-uk Kim ACPI_OPERAND_OBJECT *HandlerObj; 229efcc2a30SJung-uk Kim ACPI_OPERAND_OBJECT *NextHandlerObj; 230efcc2a30SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc; 231efcc2a30SJung-uk Kim ACPI_NAMESPACE_NODE *Node; 232efcc2a30SJung-uk Kim ACPI_STATUS Status; 233efcc2a30SJung-uk Kim 234efcc2a30SJung-uk Kim 235efcc2a30SJung-uk Kim ACPI_FUNCTION_NAME (EvInstallHandler); 236efcc2a30SJung-uk Kim 237efcc2a30SJung-uk Kim 238efcc2a30SJung-uk Kim HandlerObj = (ACPI_OPERAND_OBJECT *) Context; 239efcc2a30SJung-uk Kim 240efcc2a30SJung-uk Kim /* Parameter validation */ 241efcc2a30SJung-uk Kim 242efcc2a30SJung-uk Kim if (!HandlerObj) 243efcc2a30SJung-uk Kim { 244efcc2a30SJung-uk Kim return (AE_OK); 245efcc2a30SJung-uk Kim } 246efcc2a30SJung-uk Kim 247efcc2a30SJung-uk Kim /* Convert and validate the device handle */ 248efcc2a30SJung-uk Kim 249efcc2a30SJung-uk Kim Node = AcpiNsValidateHandle (ObjHandle); 250efcc2a30SJung-uk Kim if (!Node) 251efcc2a30SJung-uk Kim { 252efcc2a30SJung-uk Kim return (AE_BAD_PARAMETER); 253efcc2a30SJung-uk Kim } 254efcc2a30SJung-uk Kim 255efcc2a30SJung-uk Kim /* 256efcc2a30SJung-uk Kim * We only care about regions and objects that are allowed to have 257efcc2a30SJung-uk Kim * address space handlers 258efcc2a30SJung-uk Kim */ 259efcc2a30SJung-uk Kim if ((Node->Type != ACPI_TYPE_DEVICE) && 260efcc2a30SJung-uk Kim (Node->Type != ACPI_TYPE_REGION) && 261efcc2a30SJung-uk Kim (Node != AcpiGbl_RootNode)) 262efcc2a30SJung-uk Kim { 263efcc2a30SJung-uk Kim return (AE_OK); 264efcc2a30SJung-uk Kim } 265efcc2a30SJung-uk Kim 266efcc2a30SJung-uk Kim /* Check for an existing internal object */ 267efcc2a30SJung-uk Kim 268efcc2a30SJung-uk Kim ObjDesc = AcpiNsGetAttachedObject (Node); 269efcc2a30SJung-uk Kim if (!ObjDesc) 270efcc2a30SJung-uk Kim { 271efcc2a30SJung-uk Kim /* No object, just exit */ 272efcc2a30SJung-uk Kim 273efcc2a30SJung-uk Kim return (AE_OK); 274efcc2a30SJung-uk Kim } 275efcc2a30SJung-uk Kim 276efcc2a30SJung-uk Kim /* Devices are handled different than regions */ 277efcc2a30SJung-uk Kim 278efcc2a30SJung-uk Kim if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE) 279efcc2a30SJung-uk Kim { 280efcc2a30SJung-uk Kim /* Check if this Device already has a handler for this address space */ 281efcc2a30SJung-uk Kim 282efcc2a30SJung-uk Kim NextHandlerObj = ObjDesc->Device.Handler; 283efcc2a30SJung-uk Kim while (NextHandlerObj) 284efcc2a30SJung-uk Kim { 285efcc2a30SJung-uk Kim /* Found a handler, is it for the same address space? */ 286efcc2a30SJung-uk Kim 287efcc2a30SJung-uk Kim if (NextHandlerObj->AddressSpace.SpaceId == 288efcc2a30SJung-uk Kim HandlerObj->AddressSpace.SpaceId) 289efcc2a30SJung-uk Kim { 290efcc2a30SJung-uk Kim ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 291efcc2a30SJung-uk Kim "Found handler for region [%s] in device %p(%p) " 292efcc2a30SJung-uk Kim "handler %p\n", 293efcc2a30SJung-uk Kim AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId), 294efcc2a30SJung-uk Kim ObjDesc, NextHandlerObj, HandlerObj)); 295efcc2a30SJung-uk Kim 296efcc2a30SJung-uk Kim /* 297efcc2a30SJung-uk Kim * Since the object we found it on was a device, then it 298efcc2a30SJung-uk Kim * means that someone has already installed a handler for 299efcc2a30SJung-uk Kim * the branch of the namespace from this device on. Just 300efcc2a30SJung-uk Kim * bail out telling the walk routine to not traverse this 301efcc2a30SJung-uk Kim * branch. This preserves the scoping rule for handlers. 302efcc2a30SJung-uk Kim */ 303efcc2a30SJung-uk Kim return (AE_CTRL_DEPTH); 304efcc2a30SJung-uk Kim } 305efcc2a30SJung-uk Kim 306efcc2a30SJung-uk Kim /* Walk the linked list of handlers attached to this device */ 307efcc2a30SJung-uk Kim 308efcc2a30SJung-uk Kim NextHandlerObj = NextHandlerObj->AddressSpace.Next; 309efcc2a30SJung-uk Kim } 310efcc2a30SJung-uk Kim 311efcc2a30SJung-uk Kim /* 312efcc2a30SJung-uk Kim * As long as the device didn't have a handler for this space we 313efcc2a30SJung-uk Kim * don't care about it. We just ignore it and proceed. 314efcc2a30SJung-uk Kim */ 315efcc2a30SJung-uk Kim return (AE_OK); 316efcc2a30SJung-uk Kim } 317efcc2a30SJung-uk Kim 318efcc2a30SJung-uk Kim /* Object is a Region */ 319efcc2a30SJung-uk Kim 320efcc2a30SJung-uk Kim if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId) 321efcc2a30SJung-uk Kim { 322efcc2a30SJung-uk Kim /* This region is for a different address space, just ignore it */ 323efcc2a30SJung-uk Kim 324efcc2a30SJung-uk Kim return (AE_OK); 325efcc2a30SJung-uk Kim } 326efcc2a30SJung-uk Kim 327efcc2a30SJung-uk Kim /* 328efcc2a30SJung-uk Kim * Now we have a region and it is for the handler's address space type. 329efcc2a30SJung-uk Kim * 330efcc2a30SJung-uk Kim * First disconnect region for any previous handler (if any) 331efcc2a30SJung-uk Kim */ 332efcc2a30SJung-uk Kim AcpiEvDetachRegion (ObjDesc, FALSE); 333efcc2a30SJung-uk Kim 334efcc2a30SJung-uk Kim /* Connect the region to the new handler */ 335efcc2a30SJung-uk Kim 336efcc2a30SJung-uk Kim Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE); 337efcc2a30SJung-uk Kim return (Status); 338efcc2a30SJung-uk Kim } 339efcc2a30SJung-uk Kim 340efcc2a30SJung-uk Kim 341efcc2a30SJung-uk Kim /******************************************************************************* 342efcc2a30SJung-uk Kim * 343efcc2a30SJung-uk Kim * FUNCTION: AcpiEvInstallSpaceHandler 344efcc2a30SJung-uk Kim * 345efcc2a30SJung-uk Kim * PARAMETERS: Node - Namespace node for the device 346efcc2a30SJung-uk Kim * SpaceId - The address space ID 347efcc2a30SJung-uk Kim * Handler - Address of the handler 348efcc2a30SJung-uk Kim * Setup - Address of the setup function 349efcc2a30SJung-uk Kim * Context - Value passed to the handler on each access 350efcc2a30SJung-uk Kim * 351efcc2a30SJung-uk Kim * RETURN: Status 352efcc2a30SJung-uk Kim * 353efcc2a30SJung-uk Kim * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId. 354efcc2a30SJung-uk Kim * Assumes namespace is locked 355efcc2a30SJung-uk Kim * 356efcc2a30SJung-uk Kim ******************************************************************************/ 357efcc2a30SJung-uk Kim 358efcc2a30SJung-uk Kim ACPI_STATUS 359efcc2a30SJung-uk Kim AcpiEvInstallSpaceHandler ( 360efcc2a30SJung-uk Kim ACPI_NAMESPACE_NODE *Node, 361efcc2a30SJung-uk Kim ACPI_ADR_SPACE_TYPE SpaceId, 362efcc2a30SJung-uk Kim ACPI_ADR_SPACE_HANDLER Handler, 363efcc2a30SJung-uk Kim ACPI_ADR_SPACE_SETUP Setup, 364efcc2a30SJung-uk Kim void *Context) 365efcc2a30SJung-uk Kim { 366efcc2a30SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc; 367efcc2a30SJung-uk Kim ACPI_OPERAND_OBJECT *HandlerObj; 368efcc2a30SJung-uk Kim ACPI_STATUS Status; 369efcc2a30SJung-uk Kim ACPI_OBJECT_TYPE Type; 370efcc2a30SJung-uk Kim UINT8 Flags = 0; 371efcc2a30SJung-uk Kim 372efcc2a30SJung-uk Kim 373efcc2a30SJung-uk Kim ACPI_FUNCTION_TRACE (EvInstallSpaceHandler); 374efcc2a30SJung-uk Kim 375efcc2a30SJung-uk Kim 376efcc2a30SJung-uk Kim /* 377efcc2a30SJung-uk Kim * This registration is valid for only the types below and the root. This 378efcc2a30SJung-uk Kim * is where the default handlers get placed. 379efcc2a30SJung-uk Kim */ 380efcc2a30SJung-uk Kim if ((Node->Type != ACPI_TYPE_DEVICE) && 381efcc2a30SJung-uk Kim (Node->Type != ACPI_TYPE_PROCESSOR) && 382efcc2a30SJung-uk Kim (Node->Type != ACPI_TYPE_THERMAL) && 383efcc2a30SJung-uk Kim (Node != AcpiGbl_RootNode)) 384efcc2a30SJung-uk Kim { 385efcc2a30SJung-uk Kim Status = AE_BAD_PARAMETER; 386efcc2a30SJung-uk Kim goto UnlockAndExit; 387efcc2a30SJung-uk Kim } 388efcc2a30SJung-uk Kim 389efcc2a30SJung-uk Kim if (Handler == ACPI_DEFAULT_HANDLER) 390efcc2a30SJung-uk Kim { 391efcc2a30SJung-uk Kim Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; 392efcc2a30SJung-uk Kim 393efcc2a30SJung-uk Kim switch (SpaceId) 394efcc2a30SJung-uk Kim { 395efcc2a30SJung-uk Kim case ACPI_ADR_SPACE_SYSTEM_MEMORY: 396*a9d8d09cSJung-uk Kim 397efcc2a30SJung-uk Kim Handler = AcpiExSystemMemorySpaceHandler; 398efcc2a30SJung-uk Kim Setup = AcpiEvSystemMemoryRegionSetup; 399efcc2a30SJung-uk Kim break; 400efcc2a30SJung-uk Kim 401efcc2a30SJung-uk Kim case ACPI_ADR_SPACE_SYSTEM_IO: 402*a9d8d09cSJung-uk Kim 403efcc2a30SJung-uk Kim Handler = AcpiExSystemIoSpaceHandler; 404efcc2a30SJung-uk Kim Setup = AcpiEvIoSpaceRegionSetup; 405efcc2a30SJung-uk Kim break; 406efcc2a30SJung-uk Kim 407efcc2a30SJung-uk Kim case ACPI_ADR_SPACE_PCI_CONFIG: 408*a9d8d09cSJung-uk Kim 409efcc2a30SJung-uk Kim Handler = AcpiExPciConfigSpaceHandler; 410efcc2a30SJung-uk Kim Setup = AcpiEvPciConfigRegionSetup; 411efcc2a30SJung-uk Kim break; 412efcc2a30SJung-uk Kim 413efcc2a30SJung-uk Kim case ACPI_ADR_SPACE_CMOS: 414*a9d8d09cSJung-uk Kim 415efcc2a30SJung-uk Kim Handler = AcpiExCmosSpaceHandler; 416efcc2a30SJung-uk Kim Setup = AcpiEvCmosRegionSetup; 417efcc2a30SJung-uk Kim break; 418efcc2a30SJung-uk Kim 419efcc2a30SJung-uk Kim case ACPI_ADR_SPACE_PCI_BAR_TARGET: 420*a9d8d09cSJung-uk Kim 421efcc2a30SJung-uk Kim Handler = AcpiExPciBarSpaceHandler; 422efcc2a30SJung-uk Kim Setup = AcpiEvPciBarRegionSetup; 423efcc2a30SJung-uk Kim break; 424efcc2a30SJung-uk Kim 425efcc2a30SJung-uk Kim case ACPI_ADR_SPACE_DATA_TABLE: 426*a9d8d09cSJung-uk Kim 427efcc2a30SJung-uk Kim Handler = AcpiExDataTableSpaceHandler; 428efcc2a30SJung-uk Kim Setup = NULL; 429efcc2a30SJung-uk Kim break; 430efcc2a30SJung-uk Kim 431efcc2a30SJung-uk Kim default: 432*a9d8d09cSJung-uk Kim 433efcc2a30SJung-uk Kim Status = AE_BAD_PARAMETER; 434efcc2a30SJung-uk Kim goto UnlockAndExit; 435efcc2a30SJung-uk Kim } 436efcc2a30SJung-uk Kim } 437efcc2a30SJung-uk Kim 438efcc2a30SJung-uk Kim /* If the caller hasn't specified a setup routine, use the default */ 439efcc2a30SJung-uk Kim 440efcc2a30SJung-uk Kim if (!Setup) 441efcc2a30SJung-uk Kim { 442efcc2a30SJung-uk Kim Setup = AcpiEvDefaultRegionSetup; 443efcc2a30SJung-uk Kim } 444efcc2a30SJung-uk Kim 445efcc2a30SJung-uk Kim /* Check for an existing internal object */ 446efcc2a30SJung-uk Kim 447efcc2a30SJung-uk Kim ObjDesc = AcpiNsGetAttachedObject (Node); 448efcc2a30SJung-uk Kim if (ObjDesc) 449efcc2a30SJung-uk Kim { 450efcc2a30SJung-uk Kim /* 451efcc2a30SJung-uk Kim * The attached device object already exists. Make sure the handler 452efcc2a30SJung-uk Kim * is not already installed. 453efcc2a30SJung-uk Kim */ 454efcc2a30SJung-uk Kim HandlerObj = ObjDesc->Device.Handler; 455efcc2a30SJung-uk Kim 456efcc2a30SJung-uk Kim /* Walk the handler list for this device */ 457efcc2a30SJung-uk Kim 458efcc2a30SJung-uk Kim while (HandlerObj) 459efcc2a30SJung-uk Kim { 460efcc2a30SJung-uk Kim /* Same SpaceId indicates a handler already installed */ 461efcc2a30SJung-uk Kim 462efcc2a30SJung-uk Kim if (HandlerObj->AddressSpace.SpaceId == SpaceId) 463efcc2a30SJung-uk Kim { 464efcc2a30SJung-uk Kim if (HandlerObj->AddressSpace.Handler == Handler) 465efcc2a30SJung-uk Kim { 466efcc2a30SJung-uk Kim /* 467efcc2a30SJung-uk Kim * It is (relatively) OK to attempt to install the SAME 468efcc2a30SJung-uk Kim * handler twice. This can easily happen with the 469efcc2a30SJung-uk Kim * PCI_Config space. 470efcc2a30SJung-uk Kim */ 471efcc2a30SJung-uk Kim Status = AE_SAME_HANDLER; 472efcc2a30SJung-uk Kim goto UnlockAndExit; 473efcc2a30SJung-uk Kim } 474efcc2a30SJung-uk Kim else 475efcc2a30SJung-uk Kim { 476efcc2a30SJung-uk Kim /* A handler is already installed */ 477efcc2a30SJung-uk Kim 478efcc2a30SJung-uk Kim Status = AE_ALREADY_EXISTS; 479efcc2a30SJung-uk Kim } 480efcc2a30SJung-uk Kim goto UnlockAndExit; 481efcc2a30SJung-uk Kim } 482efcc2a30SJung-uk Kim 483efcc2a30SJung-uk Kim /* Walk the linked list of handlers */ 484efcc2a30SJung-uk Kim 485efcc2a30SJung-uk Kim HandlerObj = HandlerObj->AddressSpace.Next; 486efcc2a30SJung-uk Kim } 487efcc2a30SJung-uk Kim } 488efcc2a30SJung-uk Kim else 489efcc2a30SJung-uk Kim { 490efcc2a30SJung-uk Kim ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 491efcc2a30SJung-uk Kim "Creating object on Device %p while installing handler\n", Node)); 492efcc2a30SJung-uk Kim 493efcc2a30SJung-uk Kim /* ObjDesc does not exist, create one */ 494efcc2a30SJung-uk Kim 495efcc2a30SJung-uk Kim if (Node->Type == ACPI_TYPE_ANY) 496efcc2a30SJung-uk Kim { 497efcc2a30SJung-uk Kim Type = ACPI_TYPE_DEVICE; 498efcc2a30SJung-uk Kim } 499efcc2a30SJung-uk Kim else 500efcc2a30SJung-uk Kim { 501efcc2a30SJung-uk Kim Type = Node->Type; 502efcc2a30SJung-uk Kim } 503efcc2a30SJung-uk Kim 504efcc2a30SJung-uk Kim ObjDesc = AcpiUtCreateInternalObject (Type); 505efcc2a30SJung-uk Kim if (!ObjDesc) 506efcc2a30SJung-uk Kim { 507efcc2a30SJung-uk Kim Status = AE_NO_MEMORY; 508efcc2a30SJung-uk Kim goto UnlockAndExit; 509efcc2a30SJung-uk Kim } 510efcc2a30SJung-uk Kim 511efcc2a30SJung-uk Kim /* Init new descriptor */ 512efcc2a30SJung-uk Kim 513efcc2a30SJung-uk Kim ObjDesc->Common.Type = (UINT8) Type; 514efcc2a30SJung-uk Kim 515efcc2a30SJung-uk Kim /* Attach the new object to the Node */ 516efcc2a30SJung-uk Kim 517efcc2a30SJung-uk Kim Status = AcpiNsAttachObject (Node, ObjDesc, Type); 518efcc2a30SJung-uk Kim 519efcc2a30SJung-uk Kim /* Remove local reference to the object */ 520efcc2a30SJung-uk Kim 521efcc2a30SJung-uk Kim AcpiUtRemoveReference (ObjDesc); 522efcc2a30SJung-uk Kim 523efcc2a30SJung-uk Kim if (ACPI_FAILURE (Status)) 524efcc2a30SJung-uk Kim { 525efcc2a30SJung-uk Kim goto UnlockAndExit; 526efcc2a30SJung-uk Kim } 527efcc2a30SJung-uk Kim } 528efcc2a30SJung-uk Kim 529efcc2a30SJung-uk Kim ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 530efcc2a30SJung-uk Kim "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", 531efcc2a30SJung-uk Kim AcpiUtGetRegionName (SpaceId), SpaceId, 532efcc2a30SJung-uk Kim AcpiUtGetNodeName (Node), Node, ObjDesc)); 533efcc2a30SJung-uk Kim 534efcc2a30SJung-uk Kim /* 535efcc2a30SJung-uk Kim * Install the handler 536efcc2a30SJung-uk Kim * 537efcc2a30SJung-uk Kim * At this point there is no existing handler. Just allocate the object 538efcc2a30SJung-uk Kim * for the handler and link it into the list. 539efcc2a30SJung-uk Kim */ 540efcc2a30SJung-uk Kim HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER); 541efcc2a30SJung-uk Kim if (!HandlerObj) 542efcc2a30SJung-uk Kim { 543efcc2a30SJung-uk Kim Status = AE_NO_MEMORY; 544efcc2a30SJung-uk Kim goto UnlockAndExit; 545efcc2a30SJung-uk Kim } 546efcc2a30SJung-uk Kim 547efcc2a30SJung-uk Kim /* Init handler obj */ 548efcc2a30SJung-uk Kim 549efcc2a30SJung-uk Kim HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId; 550efcc2a30SJung-uk Kim HandlerObj->AddressSpace.HandlerFlags = Flags; 551efcc2a30SJung-uk Kim HandlerObj->AddressSpace.RegionList = NULL; 552efcc2a30SJung-uk Kim HandlerObj->AddressSpace.Node = Node; 553efcc2a30SJung-uk Kim HandlerObj->AddressSpace.Handler = Handler; 554efcc2a30SJung-uk Kim HandlerObj->AddressSpace.Context = Context; 555efcc2a30SJung-uk Kim HandlerObj->AddressSpace.Setup = Setup; 556efcc2a30SJung-uk Kim 557efcc2a30SJung-uk Kim /* Install at head of Device.AddressSpace list */ 558efcc2a30SJung-uk Kim 559efcc2a30SJung-uk Kim HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler; 560efcc2a30SJung-uk Kim 561efcc2a30SJung-uk Kim /* 562efcc2a30SJung-uk Kim * The Device object is the first reference on the HandlerObj. 563efcc2a30SJung-uk Kim * Each region that uses the handler adds a reference. 564efcc2a30SJung-uk Kim */ 565efcc2a30SJung-uk Kim ObjDesc->Device.Handler = HandlerObj; 566efcc2a30SJung-uk Kim 567efcc2a30SJung-uk Kim /* 568efcc2a30SJung-uk Kim * Walk the namespace finding all of the regions this 569efcc2a30SJung-uk Kim * handler will manage. 570efcc2a30SJung-uk Kim * 571efcc2a30SJung-uk Kim * Start at the device and search the branch toward 572efcc2a30SJung-uk Kim * the leaf nodes until either the leaf is encountered or 573efcc2a30SJung-uk Kim * a device is detected that has an address handler of the 574efcc2a30SJung-uk Kim * same type. 575efcc2a30SJung-uk Kim * 576efcc2a30SJung-uk Kim * In either case, back up and search down the remainder 577efcc2a30SJung-uk Kim * of the branch 578efcc2a30SJung-uk Kim */ 579efcc2a30SJung-uk Kim Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, 580efcc2a30SJung-uk Kim ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL, 581efcc2a30SJung-uk Kim HandlerObj, NULL); 582efcc2a30SJung-uk Kim 583efcc2a30SJung-uk Kim UnlockAndExit: 584efcc2a30SJung-uk Kim return_ACPI_STATUS (Status); 585efcc2a30SJung-uk Kim } 586