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