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