xref: /titanic_50/usr/src/uts/intel/io/acpica/events/evhandler.c (revision 385cc6b4ad1792caef3f84eb61eed3f27085801f)
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