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