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