xref: /netbsd-src/sys/external/bsd/acpica/dist/events/evxfregn.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
1 /******************************************************************************
2  *
3  * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
4  *                         Address Spaces.
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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:    AcpiInstallAddressSpaceHandlerInternal
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  *              Run_Reg         - Run _REG methods for this address space?
66  *
67  * RETURN:      Status
68  *
69  * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
70  *
71  * NOTE: This function should only be called after AcpiEnableSubsystem has
72  * been called. This is because any _REG methods associated with the Space ID
73  * are executed here, and these methods can only be safely executed after
74  * the default handlers have been installed and the hardware has been
75  * initialized (via AcpiEnableSubsystem.)
76  * To avoid this problem pass FALSE for Run_Reg and later on call
77  * AcpiExecuteRegMethods() to execute _REG.
78  *
79  ******************************************************************************/
80 
81 static ACPI_STATUS
AcpiInstallAddressSpaceHandlerInternal(ACPI_HANDLE Device,ACPI_ADR_SPACE_TYPE SpaceId,ACPI_ADR_SPACE_HANDLER Handler,ACPI_ADR_SPACE_SETUP Setup,void * Context,BOOLEAN Run_Reg)82 AcpiInstallAddressSpaceHandlerInternal (
83     ACPI_HANDLE             Device,
84     ACPI_ADR_SPACE_TYPE     SpaceId,
85     ACPI_ADR_SPACE_HANDLER  Handler,
86     ACPI_ADR_SPACE_SETUP    Setup,
87     void                    *Context,
88     BOOLEAN                 Run_Reg)
89 {
90     ACPI_NAMESPACE_NODE     *Node;
91     ACPI_STATUS             Status;
92 
93 
94     ACPI_FUNCTION_TRACE (AcpiInstallAddressSpaceHandler);
95 
96 
97     /* Parameter validation */
98 
99     if (!Device)
100     {
101         return_ACPI_STATUS (AE_BAD_PARAMETER);
102     }
103 
104     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
105     if (ACPI_FAILURE (Status))
106     {
107         return_ACPI_STATUS (Status);
108     }
109 
110     /* Convert and validate the device handle */
111 
112     Node = AcpiNsValidateHandle (Device);
113     if (!Node)
114     {
115         Status = AE_BAD_PARAMETER;
116         goto UnlockAndExit;
117     }
118 
119     /* Install the handler for all Regions for this Space ID */
120 
121     Status = AcpiEvInstallSpaceHandler (
122         Node, SpaceId, Handler, Setup, Context);
123     if (ACPI_FAILURE (Status))
124     {
125         goto UnlockAndExit;
126     }
127 
128     /* Run all _REG methods for this address space */
129 
130     if (Run_Reg)
131     {
132         AcpiEvExecuteRegMethods (Node, SpaceId, ACPI_REG_CONNECT);
133     }
134 
135 UnlockAndExit:
136     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
137     return_ACPI_STATUS (Status);
138 }
139 
140 ACPI_STATUS
AcpiInstallAddressSpaceHandler(ACPI_HANDLE Device,ACPI_ADR_SPACE_TYPE SpaceId,ACPI_ADR_SPACE_HANDLER Handler,ACPI_ADR_SPACE_SETUP Setup,void * Context)141 AcpiInstallAddressSpaceHandler (
142     ACPI_HANDLE             Device,
143     ACPI_ADR_SPACE_TYPE     SpaceId,
144     ACPI_ADR_SPACE_HANDLER  Handler,
145     ACPI_ADR_SPACE_SETUP    Setup,
146     void                    *Context)
147 {
148     return AcpiInstallAddressSpaceHandlerInternal (Device, SpaceId, Handler, Setup, Context, TRUE);
149 }
150 
ACPI_EXPORT_SYMBOL(AcpiInstallAddressSpaceHandler)151 ACPI_EXPORT_SYMBOL (AcpiInstallAddressSpaceHandler)
152 
153 ACPI_STATUS
154 AcpiInstallAddressSpaceHandlerNo_Reg (
155     ACPI_HANDLE             Device,
156     ACPI_ADR_SPACE_TYPE     SpaceId,
157     ACPI_ADR_SPACE_HANDLER  Handler,
158     ACPI_ADR_SPACE_SETUP    Setup,
159     void                    *Context)
160 {
161     return AcpiInstallAddressSpaceHandlerInternal (Device, SpaceId, Handler, Setup, Context, FALSE);
162 }
163 
ACPI_EXPORT_SYMBOL(AcpiInstallAddressSpaceHandlerNo_Reg)164 ACPI_EXPORT_SYMBOL (AcpiInstallAddressSpaceHandlerNo_Reg)
165 
166 
167 /*******************************************************************************
168  *
169  * FUNCTION:    AcpiRemoveAddressSpaceHandler
170  *
171  * PARAMETERS:  Device          - Handle for the device
172  *              SpaceId         - The address space ID
173  *              Handler         - Address of the handler
174  *
175  * RETURN:      Status
176  *
177  * DESCRIPTION: Remove a previously installed handler.
178  *
179  ******************************************************************************/
180 
181 ACPI_STATUS
182 AcpiRemoveAddressSpaceHandler (
183     ACPI_HANDLE             Device,
184     ACPI_ADR_SPACE_TYPE     SpaceId,
185     ACPI_ADR_SPACE_HANDLER  Handler)
186 {
187     ACPI_OPERAND_OBJECT     *ObjDesc;
188     ACPI_OPERAND_OBJECT     *HandlerObj;
189     ACPI_OPERAND_OBJECT     *RegionObj;
190     ACPI_OPERAND_OBJECT     **LastObjPtr;
191     ACPI_NAMESPACE_NODE     *Node;
192     ACPI_STATUS             Status;
193 
194 
195     ACPI_FUNCTION_TRACE (AcpiRemoveAddressSpaceHandler);
196 
197 
198     /* Parameter validation */
199 
200     if (!Device)
201     {
202         return_ACPI_STATUS (AE_BAD_PARAMETER);
203     }
204 
205     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
206     if (ACPI_FAILURE (Status))
207     {
208         return_ACPI_STATUS (Status);
209     }
210 
211     /* Convert and validate the device handle */
212 
213     Node = AcpiNsValidateHandle (Device);
214     if (!Node ||
215         ((Node->Type != ACPI_TYPE_DEVICE)    &&
216          (Node->Type != ACPI_TYPE_PROCESSOR) &&
217          (Node->Type != ACPI_TYPE_THERMAL)   &&
218          (Node != AcpiGbl_RootNode)))
219     {
220         Status = AE_BAD_PARAMETER;
221         goto UnlockAndExit;
222     }
223 
224     /* Make sure the internal object exists */
225 
226     ObjDesc = AcpiNsGetAttachedObject (Node);
227     if (!ObjDesc)
228     {
229         Status = AE_NOT_EXIST;
230         goto UnlockAndExit;
231     }
232 
233     /* Find the address handler the user requested */
234 
235     HandlerObj = ObjDesc->CommonNotify.Handler;
236     LastObjPtr = &ObjDesc->CommonNotify.Handler;
237     while (HandlerObj)
238     {
239         /* We have a handler, see if user requested this one */
240 
241         if (HandlerObj->AddressSpace.SpaceId == SpaceId)
242         {
243             /* Handler must be the same as the installed handler */
244 
245             if (HandlerObj->AddressSpace.Handler != Handler)
246             {
247                 Status = AE_BAD_PARAMETER;
248                 goto UnlockAndExit;
249             }
250 
251             /* Matched SpaceId, first dereference this in the Regions */
252 
253             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
254                 "Removing address handler %p(%p) for region %s "
255                 "on Device %p(%p)\n",
256                 HandlerObj, Handler, AcpiUtGetRegionName (SpaceId),
257                 Node, ObjDesc));
258 
259             RegionObj = HandlerObj->AddressSpace.RegionList;
260 
261             /* Walk the handler's region list */
262 
263             while (RegionObj)
264             {
265                 /*
266                  * First disassociate the handler from the region.
267                  *
268                  * NOTE: this doesn't mean that the region goes away
269                  * The region is just inaccessible as indicated to
270                  * the _REG method
271                  */
272                 AcpiEvDetachRegion (RegionObj, TRUE);
273 
274                 /*
275                  * Walk the list: Just grab the head because the
276                  * DetachRegion removed the previous head.
277                  */
278                 RegionObj = HandlerObj->AddressSpace.RegionList;
279             }
280 
281             /* Remove this Handler object from the list */
282 
283             *LastObjPtr = HandlerObj->AddressSpace.Next;
284 
285             /* Now we can delete the handler object */
286 
287             AcpiOsReleaseMutex (HandlerObj->AddressSpace.ContextMutex);
288             AcpiUtRemoveReference (HandlerObj);
289             goto UnlockAndExit;
290         }
291 
292         /* Walk the linked list of handlers */
293 
294         LastObjPtr = &HandlerObj->AddressSpace.Next;
295         HandlerObj = HandlerObj->AddressSpace.Next;
296     }
297 
298     /* The handler does not exist */
299 
300     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
301         "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
302         Handler, AcpiUtGetRegionName (SpaceId), SpaceId, Node, ObjDesc));
303 
304     Status = AE_NOT_EXIST;
305 
306 UnlockAndExit:
307     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
308     return_ACPI_STATUS (Status);
309 }
310 
ACPI_EXPORT_SYMBOL(AcpiRemoveAddressSpaceHandler)311 ACPI_EXPORT_SYMBOL (AcpiRemoveAddressSpaceHandler)
312 
313 
314 /*******************************************************************************
315  *
316  * FUNCTION:    AcpiExecuteRegMethods
317  *
318  * PARAMETERS:  Device          - Handle for the device
319  *              SpaceId         - The address space ID
320  *
321  * RETURN:      Status
322  *
323  * DESCRIPTION: Execute _REG for all OpRegions of a given SpaceId.
324  *
325  ******************************************************************************/
326 
327 ACPI_STATUS
328 AcpiExecuteRegMethods (
329     ACPI_HANDLE             Device,
330     ACPI_ADR_SPACE_TYPE     SpaceId)
331 {
332     ACPI_NAMESPACE_NODE     *Node;
333     ACPI_STATUS             Status;
334 
335 
336     ACPI_FUNCTION_TRACE (AcpiExecuteRegMethods);
337 
338 
339     /* Parameter validation */
340 
341     if (!Device)
342     {
343         return_ACPI_STATUS (AE_BAD_PARAMETER);
344     }
345 
346     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
347     if (ACPI_FAILURE (Status))
348     {
349         return_ACPI_STATUS (Status);
350     }
351 
352     /* Convert and validate the device handle */
353 
354     Node = AcpiNsValidateHandle (Device);
355     if (Node)
356     {
357         /* Run all _REG methods for this address space */
358 
359         AcpiEvExecuteRegMethods (Node, SpaceId, ACPI_REG_CONNECT);
360     }
361     else
362     {
363         Status = AE_BAD_PARAMETER;
364     }
365 
366     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
367     return_ACPI_STATUS (Status);
368 }
369 
370 ACPI_EXPORT_SYMBOL (AcpiExecuteRegMethods)
371