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