xref: /minix3/minix/drivers/power/acpi/events/evxfregn.c (revision 29492bb71c7148a089a5afafa0c99409161218df)
1433d6423SLionel Sambuc /******************************************************************************
2433d6423SLionel Sambuc  *
3433d6423SLionel Sambuc  * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
4433d6423SLionel Sambuc  *                         Address Spaces.
5433d6423SLionel Sambuc  *
6433d6423SLionel Sambuc  *****************************************************************************/
7433d6423SLionel Sambuc 
8*29492bb7SDavid van Moolenbroek /*
9*29492bb7SDavid van Moolenbroek  * Copyright (C) 2000 - 2014, Intel Corp.
10433d6423SLionel Sambuc  * All rights reserved.
11433d6423SLionel Sambuc  *
12*29492bb7SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
13*29492bb7SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
14*29492bb7SDavid van Moolenbroek  * are met:
15*29492bb7SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
16*29492bb7SDavid van Moolenbroek  *    notice, this list of conditions, and the following disclaimer,
17*29492bb7SDavid van Moolenbroek  *    without modification.
18*29492bb7SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19*29492bb7SDavid van Moolenbroek  *    substantially similar to the "NO WARRANTY" disclaimer below
20*29492bb7SDavid van Moolenbroek  *    ("Disclaimer") and any redistribution must be conditioned upon
21*29492bb7SDavid van Moolenbroek  *    including a substantially similar Disclaimer requirement for further
22*29492bb7SDavid van Moolenbroek  *    binary redistribution.
23*29492bb7SDavid van Moolenbroek  * 3. Neither the names of the above-listed copyright holders nor the names
24*29492bb7SDavid van Moolenbroek  *    of any contributors may be used to endorse or promote products derived
25*29492bb7SDavid van Moolenbroek  *    from this software without specific prior written permission.
26433d6423SLionel Sambuc  *
27*29492bb7SDavid van Moolenbroek  * Alternatively, this software may be distributed under the terms of the
28*29492bb7SDavid van Moolenbroek  * GNU General Public License ("GPL") version 2 as published by the Free
29*29492bb7SDavid van Moolenbroek  * Software Foundation.
30433d6423SLionel Sambuc  *
31*29492bb7SDavid van Moolenbroek  * NO WARRANTY
32*29492bb7SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33*29492bb7SDavid van Moolenbroek  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34*29492bb7SDavid van Moolenbroek  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35*29492bb7SDavid van Moolenbroek  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36*29492bb7SDavid van Moolenbroek  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37*29492bb7SDavid van Moolenbroek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38*29492bb7SDavid van Moolenbroek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39*29492bb7SDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40*29492bb7SDavid van Moolenbroek  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41*29492bb7SDavid van Moolenbroek  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42*29492bb7SDavid van Moolenbroek  * POSSIBILITY OF SUCH DAMAGES.
43*29492bb7SDavid van Moolenbroek  */
44433d6423SLionel Sambuc 
45*29492bb7SDavid van Moolenbroek #define EXPORT_ACPI_INTERFACES
46433d6423SLionel Sambuc 
47433d6423SLionel Sambuc #include "acpi.h"
48433d6423SLionel Sambuc #include "accommon.h"
49433d6423SLionel Sambuc #include "acnamesp.h"
50433d6423SLionel Sambuc #include "acevents.h"
51433d6423SLionel Sambuc 
52433d6423SLionel Sambuc #define _COMPONENT          ACPI_EVENTS
53433d6423SLionel Sambuc         ACPI_MODULE_NAME    ("evxfregn")
54433d6423SLionel Sambuc 
55433d6423SLionel Sambuc 
56433d6423SLionel Sambuc /*******************************************************************************
57433d6423SLionel Sambuc  *
58433d6423SLionel Sambuc  * FUNCTION:    AcpiInstallAddressSpaceHandler
59433d6423SLionel Sambuc  *
60433d6423SLionel Sambuc  * PARAMETERS:  Device          - Handle for the device
61433d6423SLionel Sambuc  *              SpaceId         - The address space ID
62433d6423SLionel Sambuc  *              Handler         - Address of the handler
63433d6423SLionel Sambuc  *              Setup           - Address of the setup function
64433d6423SLionel Sambuc  *              Context         - Value passed to the handler on each access
65433d6423SLionel Sambuc  *
66433d6423SLionel Sambuc  * RETURN:      Status
67433d6423SLionel Sambuc  *
68433d6423SLionel Sambuc  * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
69433d6423SLionel Sambuc  *
70*29492bb7SDavid van Moolenbroek  * NOTE: This function should only be called after AcpiEnableSubsystem has
71*29492bb7SDavid van Moolenbroek  * been called. This is because any _REG methods associated with the Space ID
72*29492bb7SDavid van Moolenbroek  * are executed here, and these methods can only be safely executed after
73*29492bb7SDavid van Moolenbroek  * the default handlers have been installed and the hardware has been
74*29492bb7SDavid van Moolenbroek  * initialized (via AcpiEnableSubsystem.)
75*29492bb7SDavid van Moolenbroek  *
76433d6423SLionel Sambuc  ******************************************************************************/
77433d6423SLionel Sambuc 
78433d6423SLionel Sambuc ACPI_STATUS
AcpiInstallAddressSpaceHandler(ACPI_HANDLE Device,ACPI_ADR_SPACE_TYPE SpaceId,ACPI_ADR_SPACE_HANDLER Handler,ACPI_ADR_SPACE_SETUP Setup,void * Context)79433d6423SLionel Sambuc AcpiInstallAddressSpaceHandler (
80433d6423SLionel Sambuc     ACPI_HANDLE             Device,
81433d6423SLionel Sambuc     ACPI_ADR_SPACE_TYPE     SpaceId,
82433d6423SLionel Sambuc     ACPI_ADR_SPACE_HANDLER  Handler,
83433d6423SLionel Sambuc     ACPI_ADR_SPACE_SETUP    Setup,
84433d6423SLionel Sambuc     void                    *Context)
85433d6423SLionel Sambuc {
86433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *Node;
87433d6423SLionel Sambuc     ACPI_STATUS             Status;
88433d6423SLionel Sambuc 
89433d6423SLionel Sambuc 
90433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE (AcpiInstallAddressSpaceHandler);
91433d6423SLionel Sambuc 
92433d6423SLionel Sambuc 
93433d6423SLionel Sambuc     /* Parameter validation */
94433d6423SLionel Sambuc 
95433d6423SLionel Sambuc     if (!Device)
96433d6423SLionel Sambuc     {
97433d6423SLionel Sambuc         return_ACPI_STATUS (AE_BAD_PARAMETER);
98433d6423SLionel Sambuc     }
99433d6423SLionel Sambuc 
100433d6423SLionel Sambuc     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
101433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
102433d6423SLionel Sambuc     {
103433d6423SLionel Sambuc         return_ACPI_STATUS (Status);
104433d6423SLionel Sambuc     }
105433d6423SLionel Sambuc 
106433d6423SLionel Sambuc     /* Convert and validate the device handle */
107433d6423SLionel Sambuc 
108433d6423SLionel Sambuc     Node = AcpiNsValidateHandle (Device);
109433d6423SLionel Sambuc     if (!Node)
110433d6423SLionel Sambuc     {
111433d6423SLionel Sambuc         Status = AE_BAD_PARAMETER;
112433d6423SLionel Sambuc         goto UnlockAndExit;
113433d6423SLionel Sambuc     }
114433d6423SLionel Sambuc 
115433d6423SLionel Sambuc     /* Install the handler for all Regions for this Space ID */
116433d6423SLionel Sambuc 
117433d6423SLionel Sambuc     Status = AcpiEvInstallSpaceHandler (Node, SpaceId, Handler, Setup, Context);
118433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
119433d6423SLionel Sambuc     {
120433d6423SLionel Sambuc         goto UnlockAndExit;
121433d6423SLionel Sambuc     }
122433d6423SLionel Sambuc 
123*29492bb7SDavid van Moolenbroek     /*
124*29492bb7SDavid van Moolenbroek      * For the default SpaceIDs, (the IDs for which there are default region handlers
125*29492bb7SDavid van Moolenbroek      * installed) Only execute the _REG methods if the global initialization _REG
126*29492bb7SDavid van Moolenbroek      * methods have already been run (via AcpiInitializeObjects). In other words,
127*29492bb7SDavid van Moolenbroek      * we will defer the execution of the _REG methods for these SpaceIDs until
128*29492bb7SDavid van Moolenbroek      * execution of AcpiInitializeObjects. This is done because we need the handlers
129*29492bb7SDavid van Moolenbroek      * for the default spaces (mem/io/pci/table) to be installed before we can run
130*29492bb7SDavid van Moolenbroek      * any control methods (or _REG methods). There is known BIOS code that depends
131*29492bb7SDavid van Moolenbroek      * on this.
132*29492bb7SDavid van Moolenbroek      *
133*29492bb7SDavid van Moolenbroek      * For all other SpaceIDs, we can safely execute the _REG methods immediately.
134*29492bb7SDavid van Moolenbroek      * This means that for IDs like EmbeddedController, this function should be called
135*29492bb7SDavid van Moolenbroek      * only after AcpiEnableSubsystem has been called.
136*29492bb7SDavid van Moolenbroek      */
137*29492bb7SDavid van Moolenbroek     switch (SpaceId)
138*29492bb7SDavid van Moolenbroek     {
139*29492bb7SDavid van Moolenbroek     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
140*29492bb7SDavid van Moolenbroek     case ACPI_ADR_SPACE_SYSTEM_IO:
141*29492bb7SDavid van Moolenbroek     case ACPI_ADR_SPACE_PCI_CONFIG:
142*29492bb7SDavid van Moolenbroek     case ACPI_ADR_SPACE_DATA_TABLE:
143*29492bb7SDavid van Moolenbroek 
144*29492bb7SDavid van Moolenbroek         if (!AcpiGbl_RegMethodsExecuted)
145*29492bb7SDavid van Moolenbroek         {
146*29492bb7SDavid van Moolenbroek             /* We will defer execution of the _REG methods for this space */
147*29492bb7SDavid van Moolenbroek             goto UnlockAndExit;
148*29492bb7SDavid van Moolenbroek         }
149*29492bb7SDavid van Moolenbroek         break;
150*29492bb7SDavid van Moolenbroek 
151*29492bb7SDavid van Moolenbroek     default:
152*29492bb7SDavid van Moolenbroek 
153*29492bb7SDavid van Moolenbroek         break;
154*29492bb7SDavid van Moolenbroek     }
155*29492bb7SDavid van Moolenbroek 
156433d6423SLionel Sambuc     /* Run all _REG methods for this address space */
157433d6423SLionel Sambuc 
158433d6423SLionel Sambuc     Status = AcpiEvExecuteRegMethods (Node, SpaceId);
159433d6423SLionel Sambuc 
160*29492bb7SDavid van Moolenbroek 
161433d6423SLionel Sambuc UnlockAndExit:
162433d6423SLionel Sambuc     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
163433d6423SLionel Sambuc     return_ACPI_STATUS (Status);
164433d6423SLionel Sambuc }
165433d6423SLionel Sambuc 
ACPI_EXPORT_SYMBOL(AcpiInstallAddressSpaceHandler)166433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiInstallAddressSpaceHandler)
167433d6423SLionel Sambuc 
168433d6423SLionel Sambuc 
169433d6423SLionel Sambuc /*******************************************************************************
170433d6423SLionel Sambuc  *
171433d6423SLionel Sambuc  * FUNCTION:    AcpiRemoveAddressSpaceHandler
172433d6423SLionel Sambuc  *
173433d6423SLionel Sambuc  * PARAMETERS:  Device          - Handle for the device
174433d6423SLionel Sambuc  *              SpaceId         - The address space ID
175433d6423SLionel Sambuc  *              Handler         - Address of the handler
176433d6423SLionel Sambuc  *
177433d6423SLionel Sambuc  * RETURN:      Status
178433d6423SLionel Sambuc  *
179433d6423SLionel Sambuc  * DESCRIPTION: Remove a previously installed handler.
180433d6423SLionel Sambuc  *
181433d6423SLionel Sambuc  ******************************************************************************/
182433d6423SLionel Sambuc 
183433d6423SLionel Sambuc ACPI_STATUS
184433d6423SLionel Sambuc AcpiRemoveAddressSpaceHandler (
185433d6423SLionel Sambuc     ACPI_HANDLE             Device,
186433d6423SLionel Sambuc     ACPI_ADR_SPACE_TYPE     SpaceId,
187433d6423SLionel Sambuc     ACPI_ADR_SPACE_HANDLER  Handler)
188433d6423SLionel Sambuc {
189433d6423SLionel Sambuc     ACPI_OPERAND_OBJECT     *ObjDesc;
190433d6423SLionel Sambuc     ACPI_OPERAND_OBJECT     *HandlerObj;
191433d6423SLionel Sambuc     ACPI_OPERAND_OBJECT     *RegionObj;
192433d6423SLionel Sambuc     ACPI_OPERAND_OBJECT     **LastObjPtr;
193433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *Node;
194433d6423SLionel Sambuc     ACPI_STATUS             Status;
195433d6423SLionel Sambuc 
196433d6423SLionel Sambuc 
197433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE (AcpiRemoveAddressSpaceHandler);
198433d6423SLionel Sambuc 
199433d6423SLionel Sambuc 
200433d6423SLionel Sambuc     /* Parameter validation */
201433d6423SLionel Sambuc 
202433d6423SLionel Sambuc     if (!Device)
203433d6423SLionel Sambuc     {
204433d6423SLionel Sambuc         return_ACPI_STATUS (AE_BAD_PARAMETER);
205433d6423SLionel Sambuc     }
206433d6423SLionel Sambuc 
207433d6423SLionel Sambuc     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
208433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
209433d6423SLionel Sambuc     {
210433d6423SLionel Sambuc         return_ACPI_STATUS (Status);
211433d6423SLionel Sambuc     }
212433d6423SLionel Sambuc 
213433d6423SLionel Sambuc     /* Convert and validate the device handle */
214433d6423SLionel Sambuc 
215433d6423SLionel Sambuc     Node = AcpiNsValidateHandle (Device);
216433d6423SLionel Sambuc     if (!Node ||
217433d6423SLionel Sambuc         ((Node->Type != ACPI_TYPE_DEVICE)    &&
218433d6423SLionel Sambuc          (Node->Type != ACPI_TYPE_PROCESSOR) &&
219433d6423SLionel Sambuc          (Node->Type != ACPI_TYPE_THERMAL)   &&
220433d6423SLionel Sambuc          (Node != AcpiGbl_RootNode)))
221433d6423SLionel Sambuc     {
222433d6423SLionel Sambuc         Status = AE_BAD_PARAMETER;
223433d6423SLionel Sambuc         goto UnlockAndExit;
224433d6423SLionel Sambuc     }
225433d6423SLionel Sambuc 
226433d6423SLionel Sambuc     /* Make sure the internal object exists */
227433d6423SLionel Sambuc 
228433d6423SLionel Sambuc     ObjDesc = AcpiNsGetAttachedObject (Node);
229433d6423SLionel Sambuc     if (!ObjDesc)
230433d6423SLionel Sambuc     {
231433d6423SLionel Sambuc         Status = AE_NOT_EXIST;
232433d6423SLionel Sambuc         goto UnlockAndExit;
233433d6423SLionel Sambuc     }
234433d6423SLionel Sambuc 
235433d6423SLionel Sambuc     /* Find the address handler the user requested */
236433d6423SLionel Sambuc 
237433d6423SLionel Sambuc     HandlerObj = ObjDesc->Device.Handler;
238433d6423SLionel Sambuc     LastObjPtr = &ObjDesc->Device.Handler;
239433d6423SLionel Sambuc     while (HandlerObj)
240433d6423SLionel Sambuc     {
241433d6423SLionel Sambuc         /* We have a handler, see if user requested this one */
242433d6423SLionel Sambuc 
243433d6423SLionel Sambuc         if (HandlerObj->AddressSpace.SpaceId == SpaceId)
244433d6423SLionel Sambuc         {
245433d6423SLionel Sambuc             /* Handler must be the same as the installed handler */
246433d6423SLionel Sambuc 
247433d6423SLionel Sambuc             if (HandlerObj->AddressSpace.Handler != Handler)
248433d6423SLionel Sambuc             {
249433d6423SLionel Sambuc                 Status = AE_BAD_PARAMETER;
250433d6423SLionel Sambuc                 goto UnlockAndExit;
251433d6423SLionel Sambuc             }
252433d6423SLionel Sambuc 
253433d6423SLionel Sambuc             /* Matched SpaceId, first dereference this in the Regions */
254433d6423SLionel Sambuc 
255433d6423SLionel Sambuc             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
256433d6423SLionel Sambuc                 "Removing address handler %p(%p) for region %s "
257433d6423SLionel Sambuc                 "on Device %p(%p)\n",
258433d6423SLionel Sambuc                 HandlerObj, Handler, AcpiUtGetRegionName (SpaceId),
259433d6423SLionel Sambuc                 Node, ObjDesc));
260433d6423SLionel Sambuc 
261433d6423SLionel Sambuc             RegionObj = HandlerObj->AddressSpace.RegionList;
262433d6423SLionel Sambuc 
263433d6423SLionel Sambuc             /* Walk the handler's region list */
264433d6423SLionel Sambuc 
265433d6423SLionel Sambuc             while (RegionObj)
266433d6423SLionel Sambuc             {
267433d6423SLionel Sambuc                 /*
268433d6423SLionel Sambuc                  * First disassociate the handler from the region.
269433d6423SLionel Sambuc                  *
270433d6423SLionel Sambuc                  * NOTE: this doesn't mean that the region goes away
271433d6423SLionel Sambuc                  * The region is just inaccessible as indicated to
272433d6423SLionel Sambuc                  * the _REG method
273433d6423SLionel Sambuc                  */
274433d6423SLionel Sambuc                 AcpiEvDetachRegion (RegionObj, TRUE);
275433d6423SLionel Sambuc 
276433d6423SLionel Sambuc                 /*
277433d6423SLionel Sambuc                  * Walk the list: Just grab the head because the
278433d6423SLionel Sambuc                  * DetachRegion removed the previous head.
279433d6423SLionel Sambuc                  */
280433d6423SLionel Sambuc                 RegionObj = HandlerObj->AddressSpace.RegionList;
281433d6423SLionel Sambuc 
282433d6423SLionel Sambuc             }
283433d6423SLionel Sambuc 
284433d6423SLionel Sambuc             /* Remove this Handler object from the list */
285433d6423SLionel Sambuc 
286433d6423SLionel Sambuc             *LastObjPtr = HandlerObj->AddressSpace.Next;
287433d6423SLionel Sambuc 
288433d6423SLionel Sambuc             /* Now we can delete the handler object */
289433d6423SLionel Sambuc 
290433d6423SLionel Sambuc             AcpiUtRemoveReference (HandlerObj);
291433d6423SLionel Sambuc             goto UnlockAndExit;
292433d6423SLionel Sambuc         }
293433d6423SLionel Sambuc 
294433d6423SLionel Sambuc         /* Walk the linked list of handlers */
295433d6423SLionel Sambuc 
296433d6423SLionel Sambuc         LastObjPtr = &HandlerObj->AddressSpace.Next;
297433d6423SLionel Sambuc         HandlerObj = HandlerObj->AddressSpace.Next;
298433d6423SLionel Sambuc     }
299433d6423SLionel Sambuc 
300433d6423SLionel Sambuc     /* The handler does not exist */
301433d6423SLionel Sambuc 
302433d6423SLionel Sambuc     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
303433d6423SLionel Sambuc         "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
304433d6423SLionel Sambuc         Handler, AcpiUtGetRegionName (SpaceId), SpaceId, Node, ObjDesc));
305433d6423SLionel Sambuc 
306433d6423SLionel Sambuc     Status = AE_NOT_EXIST;
307433d6423SLionel Sambuc 
308433d6423SLionel Sambuc UnlockAndExit:
309433d6423SLionel Sambuc     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
310433d6423SLionel Sambuc     return_ACPI_STATUS (Status);
311433d6423SLionel Sambuc }
312433d6423SLionel Sambuc 
313433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiRemoveAddressSpaceHandler)
314