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