1 /****************************************************************************** 2 * 3 * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and 4 * Address Spaces. 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2018, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #define EXPORT_ACPI_INTERFACES 46 47 #include "acpi.h" 48 #include "accommon.h" 49 #include "acnamesp.h" 50 #include "acevents.h" 51 52 #define _COMPONENT ACPI_EVENTS 53 ACPI_MODULE_NAME ("evxfregn") 54 55 56 /******************************************************************************* 57 * 58 * FUNCTION: AcpiInstallAddressSpaceHandler 59 * 60 * PARAMETERS: Device - Handle for the device 61 * SpaceId - The address space ID 62 * Handler - Address of the handler 63 * Setup - Address of the setup function 64 * Context - Value passed to the handler on each access 65 * 66 * RETURN: Status 67 * 68 * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId. 69 * 70 * NOTE: This function should only be called after AcpiEnableSubsystem has 71 * been called. This is because any _REG methods associated with the Space ID 72 * are executed here, and these methods can only be safely executed after 73 * the default handlers have been installed and the hardware has been 74 * initialized (via AcpiEnableSubsystem.) 75 * 76 ******************************************************************************/ 77 78 ACPI_STATUS 79 AcpiInstallAddressSpaceHandler ( 80 ACPI_HANDLE Device, 81 ACPI_ADR_SPACE_TYPE SpaceId, 82 ACPI_ADR_SPACE_HANDLER Handler, 83 ACPI_ADR_SPACE_SETUP Setup, 84 void *Context) 85 { 86 ACPI_NAMESPACE_NODE *Node; 87 ACPI_STATUS Status; 88 89 90 ACPI_FUNCTION_TRACE (AcpiInstallAddressSpaceHandler); 91 92 93 /* Parameter validation */ 94 95 if (!Device) 96 { 97 return_ACPI_STATUS (AE_BAD_PARAMETER); 98 } 99 100 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 101 if (ACPI_FAILURE (Status)) 102 { 103 return_ACPI_STATUS (Status); 104 } 105 106 /* Convert and validate the device handle */ 107 108 Node = AcpiNsValidateHandle (Device); 109 if (!Node) 110 { 111 Status = AE_BAD_PARAMETER; 112 goto UnlockAndExit; 113 } 114 115 /* Install the handler for all Regions for this Space ID */ 116 117 Status = AcpiEvInstallSpaceHandler ( 118 Node, SpaceId, Handler, Setup, Context); 119 if (ACPI_FAILURE (Status)) 120 { 121 goto UnlockAndExit; 122 } 123 124 /* Run all _REG methods for this address space */ 125 126 AcpiEvExecuteRegMethods (Node, SpaceId, ACPI_REG_CONNECT); 127 128 129 UnlockAndExit: 130 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 131 return_ACPI_STATUS (Status); 132 } 133 134 ACPI_EXPORT_SYMBOL (AcpiInstallAddressSpaceHandler) 135 136 137 /******************************************************************************* 138 * 139 * FUNCTION: AcpiRemoveAddressSpaceHandler 140 * 141 * PARAMETERS: Device - Handle for the device 142 * SpaceId - The address space ID 143 * Handler - Address of the handler 144 * 145 * RETURN: Status 146 * 147 * DESCRIPTION: Remove a previously installed handler. 148 * 149 ******************************************************************************/ 150 151 ACPI_STATUS 152 AcpiRemoveAddressSpaceHandler ( 153 ACPI_HANDLE Device, 154 ACPI_ADR_SPACE_TYPE SpaceId, 155 ACPI_ADR_SPACE_HANDLER Handler) 156 { 157 ACPI_OPERAND_OBJECT *ObjDesc; 158 ACPI_OPERAND_OBJECT *HandlerObj; 159 ACPI_OPERAND_OBJECT *RegionObj; 160 ACPI_OPERAND_OBJECT **LastObjPtr; 161 ACPI_NAMESPACE_NODE *Node; 162 ACPI_STATUS Status; 163 164 165 ACPI_FUNCTION_TRACE (AcpiRemoveAddressSpaceHandler); 166 167 168 /* Parameter validation */ 169 170 if (!Device) 171 { 172 return_ACPI_STATUS (AE_BAD_PARAMETER); 173 } 174 175 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 176 if (ACPI_FAILURE (Status)) 177 { 178 return_ACPI_STATUS (Status); 179 } 180 181 /* Convert and validate the device handle */ 182 183 Node = AcpiNsValidateHandle (Device); 184 if (!Node || 185 ((Node->Type != ACPI_TYPE_DEVICE) && 186 (Node->Type != ACPI_TYPE_PROCESSOR) && 187 (Node->Type != ACPI_TYPE_THERMAL) && 188 (Node != AcpiGbl_RootNode))) 189 { 190 Status = AE_BAD_PARAMETER; 191 goto UnlockAndExit; 192 } 193 194 /* Make sure the internal object exists */ 195 196 ObjDesc = AcpiNsGetAttachedObject (Node); 197 if (!ObjDesc) 198 { 199 Status = AE_NOT_EXIST; 200 goto UnlockAndExit; 201 } 202 203 /* Find the address handler the user requested */ 204 205 HandlerObj = ObjDesc->CommonNotify.Handler; 206 LastObjPtr = &ObjDesc->CommonNotify.Handler; 207 while (HandlerObj) 208 { 209 /* We have a handler, see if user requested this one */ 210 211 if (HandlerObj->AddressSpace.SpaceId == SpaceId) 212 { 213 /* Handler must be the same as the installed handler */ 214 215 if (HandlerObj->AddressSpace.Handler != Handler) 216 { 217 Status = AE_BAD_PARAMETER; 218 goto UnlockAndExit; 219 } 220 221 /* Matched SpaceId, first dereference this in the Regions */ 222 223 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 224 "Removing address handler %p(%p) for region %s " 225 "on Device %p(%p)\n", 226 HandlerObj, Handler, AcpiUtGetRegionName (SpaceId), 227 Node, ObjDesc)); 228 229 RegionObj = HandlerObj->AddressSpace.RegionList; 230 231 /* Walk the handler's region list */ 232 233 while (RegionObj) 234 { 235 /* 236 * First disassociate the handler from the region. 237 * 238 * NOTE: this doesn't mean that the region goes away 239 * The region is just inaccessible as indicated to 240 * the _REG method 241 */ 242 AcpiEvDetachRegion (RegionObj, TRUE); 243 244 /* 245 * Walk the list: Just grab the head because the 246 * DetachRegion removed the previous head. 247 */ 248 RegionObj = HandlerObj->AddressSpace.RegionList; 249 } 250 251 /* Remove this Handler object from the list */ 252 253 *LastObjPtr = HandlerObj->AddressSpace.Next; 254 255 /* Now we can delete the handler object */ 256 257 AcpiUtRemoveReference (HandlerObj); 258 goto UnlockAndExit; 259 } 260 261 /* Walk the linked list of handlers */ 262 263 LastObjPtr = &HandlerObj->AddressSpace.Next; 264 HandlerObj = HandlerObj->AddressSpace.Next; 265 } 266 267 /* The handler does not exist */ 268 269 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 270 "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n", 271 Handler, AcpiUtGetRegionName (SpaceId), SpaceId, Node, ObjDesc)); 272 273 Status = AE_NOT_EXIST; 274 275 UnlockAndExit: 276 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 277 return_ACPI_STATUS (Status); 278 } 279 280 ACPI_EXPORT_SYMBOL (AcpiRemoveAddressSpaceHandler) 281