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