xref: /minix3/minix/drivers/power/acpi/events/evrgnini.c (revision 29492bb71c7148a089a5afafa0c99409161218df)
1433d6423SLionel Sambuc /******************************************************************************
2433d6423SLionel Sambuc  *
3433d6423SLionel Sambuc  * Module Name: evrgnini- ACPI AddressSpace (OpRegion) init
4433d6423SLionel Sambuc  *
5433d6423SLionel Sambuc  *****************************************************************************/
6433d6423SLionel Sambuc 
7*29492bb7SDavid van Moolenbroek /*
8*29492bb7SDavid van Moolenbroek  * Copyright (C) 2000 - 2014, Intel Corp.
9433d6423SLionel Sambuc  * All rights reserved.
10433d6423SLionel Sambuc  *
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.
25433d6423SLionel Sambuc  *
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.
29433d6423SLionel Sambuc  *
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  */
43433d6423SLionel Sambuc 
44433d6423SLionel Sambuc #include "acpi.h"
45433d6423SLionel Sambuc #include "accommon.h"
46433d6423SLionel Sambuc #include "acevents.h"
47433d6423SLionel Sambuc #include "acnamesp.h"
48433d6423SLionel Sambuc 
49433d6423SLionel Sambuc #define _COMPONENT          ACPI_EVENTS
50433d6423SLionel Sambuc         ACPI_MODULE_NAME    ("evrgnini")
51433d6423SLionel Sambuc 
52433d6423SLionel Sambuc /* Local prototypes */
53433d6423SLionel Sambuc 
54433d6423SLionel Sambuc static BOOLEAN
55433d6423SLionel Sambuc AcpiEvIsPciRootBridge (
56433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *Node);
57433d6423SLionel Sambuc 
58433d6423SLionel Sambuc 
59433d6423SLionel Sambuc /*******************************************************************************
60433d6423SLionel Sambuc  *
61433d6423SLionel Sambuc  * FUNCTION:    AcpiEvSystemMemoryRegionSetup
62433d6423SLionel Sambuc  *
63433d6423SLionel Sambuc  * PARAMETERS:  Handle              - Region we are interested in
64433d6423SLionel Sambuc  *              Function            - Start or stop
65433d6423SLionel Sambuc  *              HandlerContext      - Address space handler context
66433d6423SLionel Sambuc  *              RegionContext       - Region specific context
67433d6423SLionel Sambuc  *
68433d6423SLionel Sambuc  * RETURN:      Status
69433d6423SLionel Sambuc  *
70433d6423SLionel Sambuc  * DESCRIPTION: Setup a SystemMemory operation region
71433d6423SLionel Sambuc  *
72433d6423SLionel Sambuc  ******************************************************************************/
73433d6423SLionel Sambuc 
74433d6423SLionel Sambuc ACPI_STATUS
AcpiEvSystemMemoryRegionSetup(ACPI_HANDLE Handle,UINT32 Function,void * HandlerContext,void ** RegionContext)75433d6423SLionel Sambuc AcpiEvSystemMemoryRegionSetup (
76433d6423SLionel Sambuc     ACPI_HANDLE             Handle,
77433d6423SLionel Sambuc     UINT32                  Function,
78433d6423SLionel Sambuc     void                    *HandlerContext,
79433d6423SLionel Sambuc     void                    **RegionContext)
80433d6423SLionel Sambuc {
81433d6423SLionel Sambuc     ACPI_OPERAND_OBJECT     *RegionDesc = (ACPI_OPERAND_OBJECT *) Handle;
82433d6423SLionel Sambuc     ACPI_MEM_SPACE_CONTEXT  *LocalRegionContext;
83433d6423SLionel Sambuc 
84433d6423SLionel Sambuc 
85433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE (EvSystemMemoryRegionSetup);
86433d6423SLionel Sambuc 
87433d6423SLionel Sambuc 
88433d6423SLionel Sambuc     if (Function == ACPI_REGION_DEACTIVATE)
89433d6423SLionel Sambuc     {
90433d6423SLionel Sambuc         if (*RegionContext)
91433d6423SLionel Sambuc         {
92433d6423SLionel Sambuc             LocalRegionContext = (ACPI_MEM_SPACE_CONTEXT *) *RegionContext;
93433d6423SLionel Sambuc 
94433d6423SLionel Sambuc             /* Delete a cached mapping if present */
95433d6423SLionel Sambuc 
96433d6423SLionel Sambuc             if (LocalRegionContext->MappedLength)
97433d6423SLionel Sambuc             {
98433d6423SLionel Sambuc                 AcpiOsUnmapMemory (LocalRegionContext->MappedLogicalAddress,
99433d6423SLionel Sambuc                     LocalRegionContext->MappedLength);
100433d6423SLionel Sambuc             }
101433d6423SLionel Sambuc             ACPI_FREE (LocalRegionContext);
102433d6423SLionel Sambuc             *RegionContext = NULL;
103433d6423SLionel Sambuc         }
104433d6423SLionel Sambuc         return_ACPI_STATUS (AE_OK);
105433d6423SLionel Sambuc     }
106433d6423SLionel Sambuc 
107433d6423SLionel Sambuc     /* Create a new context */
108433d6423SLionel Sambuc 
109433d6423SLionel Sambuc     LocalRegionContext = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_MEM_SPACE_CONTEXT));
110433d6423SLionel Sambuc     if (!(LocalRegionContext))
111433d6423SLionel Sambuc     {
112433d6423SLionel Sambuc         return_ACPI_STATUS (AE_NO_MEMORY);
113433d6423SLionel Sambuc     }
114433d6423SLionel Sambuc 
115433d6423SLionel Sambuc     /* Save the region length and address for use in the handler */
116433d6423SLionel Sambuc 
117433d6423SLionel Sambuc     LocalRegionContext->Length  = RegionDesc->Region.Length;
118433d6423SLionel Sambuc     LocalRegionContext->Address = RegionDesc->Region.Address;
119433d6423SLionel Sambuc 
120433d6423SLionel Sambuc     *RegionContext = LocalRegionContext;
121433d6423SLionel Sambuc     return_ACPI_STATUS (AE_OK);
122433d6423SLionel Sambuc }
123433d6423SLionel Sambuc 
124433d6423SLionel Sambuc 
125433d6423SLionel Sambuc /*******************************************************************************
126433d6423SLionel Sambuc  *
127433d6423SLionel Sambuc  * FUNCTION:    AcpiEvIoSpaceRegionSetup
128433d6423SLionel Sambuc  *
129433d6423SLionel Sambuc  * PARAMETERS:  Handle              - Region we are interested in
130433d6423SLionel Sambuc  *              Function            - Start or stop
131433d6423SLionel Sambuc  *              HandlerContext      - Address space handler context
132433d6423SLionel Sambuc  *              RegionContext       - Region specific context
133433d6423SLionel Sambuc  *
134433d6423SLionel Sambuc  * RETURN:      Status
135433d6423SLionel Sambuc  *
136433d6423SLionel Sambuc  * DESCRIPTION: Setup a IO operation region
137433d6423SLionel Sambuc  *
138433d6423SLionel Sambuc  ******************************************************************************/
139433d6423SLionel Sambuc 
140433d6423SLionel Sambuc ACPI_STATUS
AcpiEvIoSpaceRegionSetup(ACPI_HANDLE Handle,UINT32 Function,void * HandlerContext,void ** RegionContext)141433d6423SLionel Sambuc AcpiEvIoSpaceRegionSetup (
142433d6423SLionel Sambuc     ACPI_HANDLE             Handle,
143433d6423SLionel Sambuc     UINT32                  Function,
144433d6423SLionel Sambuc     void                    *HandlerContext,
145433d6423SLionel Sambuc     void                    **RegionContext)
146433d6423SLionel Sambuc {
147433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE (EvIoSpaceRegionSetup);
148433d6423SLionel Sambuc 
149433d6423SLionel Sambuc 
150433d6423SLionel Sambuc     if (Function == ACPI_REGION_DEACTIVATE)
151433d6423SLionel Sambuc     {
152433d6423SLionel Sambuc         *RegionContext = NULL;
153433d6423SLionel Sambuc     }
154433d6423SLionel Sambuc     else
155433d6423SLionel Sambuc     {
156433d6423SLionel Sambuc         *RegionContext = HandlerContext;
157433d6423SLionel Sambuc     }
158433d6423SLionel Sambuc 
159433d6423SLionel Sambuc     return_ACPI_STATUS (AE_OK);
160433d6423SLionel Sambuc }
161433d6423SLionel Sambuc 
162433d6423SLionel Sambuc 
163433d6423SLionel Sambuc /*******************************************************************************
164433d6423SLionel Sambuc  *
165433d6423SLionel Sambuc  * FUNCTION:    AcpiEvPciConfigRegionSetup
166433d6423SLionel Sambuc  *
167433d6423SLionel Sambuc  * PARAMETERS:  Handle              - Region we are interested in
168433d6423SLionel Sambuc  *              Function            - Start or stop
169433d6423SLionel Sambuc  *              HandlerContext      - Address space handler context
170433d6423SLionel Sambuc  *              RegionContext       - Region specific context
171433d6423SLionel Sambuc  *
172433d6423SLionel Sambuc  * RETURN:      Status
173433d6423SLionel Sambuc  *
174433d6423SLionel Sambuc  * DESCRIPTION: Setup a PCI_Config operation region
175433d6423SLionel Sambuc  *
176433d6423SLionel Sambuc  * MUTEX:       Assumes namespace is not locked
177433d6423SLionel Sambuc  *
178433d6423SLionel Sambuc  ******************************************************************************/
179433d6423SLionel Sambuc 
180433d6423SLionel Sambuc ACPI_STATUS
AcpiEvPciConfigRegionSetup(ACPI_HANDLE Handle,UINT32 Function,void * HandlerContext,void ** RegionContext)181433d6423SLionel Sambuc AcpiEvPciConfigRegionSetup (
182433d6423SLionel Sambuc     ACPI_HANDLE             Handle,
183433d6423SLionel Sambuc     UINT32                  Function,
184433d6423SLionel Sambuc     void                    *HandlerContext,
185433d6423SLionel Sambuc     void                    **RegionContext)
186433d6423SLionel Sambuc {
187433d6423SLionel Sambuc     ACPI_STATUS             Status = AE_OK;
188433d6423SLionel Sambuc     UINT64                  PciValue;
189433d6423SLionel Sambuc     ACPI_PCI_ID             *PciId = *RegionContext;
190433d6423SLionel Sambuc     ACPI_OPERAND_OBJECT     *HandlerObj;
191433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *ParentNode;
192433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *PciRootNode;
193433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *PciDeviceNode;
194433d6423SLionel Sambuc     ACPI_OPERAND_OBJECT     *RegionObj = (ACPI_OPERAND_OBJECT  *) Handle;
195433d6423SLionel Sambuc 
196433d6423SLionel Sambuc 
197433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE (EvPciConfigRegionSetup);
198433d6423SLionel Sambuc 
199433d6423SLionel Sambuc 
200433d6423SLionel Sambuc     HandlerObj = RegionObj->Region.Handler;
201433d6423SLionel Sambuc     if (!HandlerObj)
202433d6423SLionel Sambuc     {
203433d6423SLionel Sambuc         /*
204433d6423SLionel Sambuc          * No installed handler. This shouldn't happen because the dispatch
205433d6423SLionel Sambuc          * routine checks before we get here, but we check again just in case.
206433d6423SLionel Sambuc          */
207433d6423SLionel Sambuc         ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
208433d6423SLionel Sambuc             "Attempting to init a region %p, with no handler\n", RegionObj));
209433d6423SLionel Sambuc         return_ACPI_STATUS (AE_NOT_EXIST);
210433d6423SLionel Sambuc     }
211433d6423SLionel Sambuc 
212433d6423SLionel Sambuc     *RegionContext = NULL;
213433d6423SLionel Sambuc     if (Function == ACPI_REGION_DEACTIVATE)
214433d6423SLionel Sambuc     {
215433d6423SLionel Sambuc         if (PciId)
216433d6423SLionel Sambuc         {
217433d6423SLionel Sambuc             ACPI_FREE (PciId);
218433d6423SLionel Sambuc         }
219433d6423SLionel Sambuc         return_ACPI_STATUS (Status);
220433d6423SLionel Sambuc     }
221433d6423SLionel Sambuc 
222433d6423SLionel Sambuc     ParentNode = RegionObj->Region.Node->Parent;
223433d6423SLionel Sambuc 
224433d6423SLionel Sambuc     /*
225433d6423SLionel Sambuc      * Get the _SEG and _BBN values from the device upon which the handler
226433d6423SLionel Sambuc      * is installed.
227433d6423SLionel Sambuc      *
228433d6423SLionel Sambuc      * We need to get the _SEG and _BBN objects relative to the PCI BUS device.
229433d6423SLionel Sambuc      * This is the device the handler has been registered to handle.
230433d6423SLionel Sambuc      */
231433d6423SLionel Sambuc 
232433d6423SLionel Sambuc     /*
233433d6423SLionel Sambuc      * If the AddressSpace.Node is still pointing to the root, we need
234433d6423SLionel Sambuc      * to scan upward for a PCI Root bridge and re-associate the OpRegion
235433d6423SLionel Sambuc      * handlers with that device.
236433d6423SLionel Sambuc      */
237433d6423SLionel Sambuc     if (HandlerObj->AddressSpace.Node == AcpiGbl_RootNode)
238433d6423SLionel Sambuc     {
239433d6423SLionel Sambuc         /* Start search from the parent object */
240433d6423SLionel Sambuc 
241433d6423SLionel Sambuc         PciRootNode = ParentNode;
242433d6423SLionel Sambuc         while (PciRootNode != AcpiGbl_RootNode)
243433d6423SLionel Sambuc         {
244433d6423SLionel Sambuc             /* Get the _HID/_CID in order to detect a RootBridge */
245433d6423SLionel Sambuc 
246433d6423SLionel Sambuc             if (AcpiEvIsPciRootBridge (PciRootNode))
247433d6423SLionel Sambuc             {
248433d6423SLionel Sambuc                 /* Install a handler for this PCI root bridge */
249433d6423SLionel Sambuc 
250433d6423SLionel Sambuc                 Status = AcpiInstallAddressSpaceHandler (
251433d6423SLionel Sambuc                             (ACPI_HANDLE) PciRootNode,
252433d6423SLionel Sambuc                             ACPI_ADR_SPACE_PCI_CONFIG,
253433d6423SLionel Sambuc                             ACPI_DEFAULT_HANDLER, NULL, NULL);
254433d6423SLionel Sambuc                 if (ACPI_FAILURE (Status))
255433d6423SLionel Sambuc                 {
256433d6423SLionel Sambuc                     if (Status == AE_SAME_HANDLER)
257433d6423SLionel Sambuc                     {
258433d6423SLionel Sambuc                         /*
259433d6423SLionel Sambuc                          * It is OK if the handler is already installed on the
260433d6423SLionel Sambuc                          * root bridge. Still need to return a context object
261433d6423SLionel Sambuc                          * for the new PCI_Config operation region, however.
262433d6423SLionel Sambuc                          */
263433d6423SLionel Sambuc                         Status = AE_OK;
264433d6423SLionel Sambuc                     }
265433d6423SLionel Sambuc                     else
266433d6423SLionel Sambuc                     {
267433d6423SLionel Sambuc                         ACPI_EXCEPTION ((AE_INFO, Status,
268433d6423SLionel Sambuc                             "Could not install PciConfig handler "
269433d6423SLionel Sambuc                             "for Root Bridge %4.4s",
270433d6423SLionel Sambuc                             AcpiUtGetNodeName (PciRootNode)));
271433d6423SLionel Sambuc                     }
272433d6423SLionel Sambuc                 }
273433d6423SLionel Sambuc                 break;
274433d6423SLionel Sambuc             }
275433d6423SLionel Sambuc 
276433d6423SLionel Sambuc             PciRootNode = PciRootNode->Parent;
277433d6423SLionel Sambuc         }
278433d6423SLionel Sambuc 
279433d6423SLionel Sambuc         /* PCI root bridge not found, use namespace root node */
280433d6423SLionel Sambuc     }
281433d6423SLionel Sambuc     else
282433d6423SLionel Sambuc     {
283433d6423SLionel Sambuc         PciRootNode = HandlerObj->AddressSpace.Node;
284433d6423SLionel Sambuc     }
285433d6423SLionel Sambuc 
286433d6423SLionel Sambuc     /*
287433d6423SLionel Sambuc      * If this region is now initialized, we are done.
288433d6423SLionel Sambuc      * (InstallAddressSpaceHandler could have initialized it)
289433d6423SLionel Sambuc      */
290433d6423SLionel Sambuc     if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
291433d6423SLionel Sambuc     {
292433d6423SLionel Sambuc         return_ACPI_STATUS (AE_OK);
293433d6423SLionel Sambuc     }
294433d6423SLionel Sambuc 
295433d6423SLionel Sambuc     /* Region is still not initialized. Create a new context */
296433d6423SLionel Sambuc 
297433d6423SLionel Sambuc     PciId = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PCI_ID));
298433d6423SLionel Sambuc     if (!PciId)
299433d6423SLionel Sambuc     {
300433d6423SLionel Sambuc         return_ACPI_STATUS (AE_NO_MEMORY);
301433d6423SLionel Sambuc     }
302433d6423SLionel Sambuc 
303433d6423SLionel Sambuc     /*
304433d6423SLionel Sambuc      * For PCI_Config space access, we need the segment, bus, device and
305433d6423SLionel Sambuc      * function numbers. Acquire them here.
306433d6423SLionel Sambuc      *
307433d6423SLionel Sambuc      * Find the parent device object. (This allows the operation region to be
308433d6423SLionel Sambuc      * within a subscope under the device, such as a control method.)
309433d6423SLionel Sambuc      */
310433d6423SLionel Sambuc     PciDeviceNode = RegionObj->Region.Node;
311433d6423SLionel Sambuc     while (PciDeviceNode && (PciDeviceNode->Type != ACPI_TYPE_DEVICE))
312433d6423SLionel Sambuc     {
313433d6423SLionel Sambuc         PciDeviceNode = PciDeviceNode->Parent;
314433d6423SLionel Sambuc     }
315433d6423SLionel Sambuc 
316433d6423SLionel Sambuc     if (!PciDeviceNode)
317433d6423SLionel Sambuc     {
318433d6423SLionel Sambuc         ACPI_FREE (PciId);
319433d6423SLionel Sambuc         return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
320433d6423SLionel Sambuc     }
321433d6423SLionel Sambuc 
322433d6423SLionel Sambuc     /*
323*29492bb7SDavid van Moolenbroek      * Get the PCI device and function numbers from the _ADR object
324*29492bb7SDavid van Moolenbroek      * contained in the parent's scope.
325433d6423SLionel Sambuc      */
326433d6423SLionel Sambuc     Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR,
327433d6423SLionel Sambuc                 PciDeviceNode, &PciValue);
328433d6423SLionel Sambuc 
329433d6423SLionel Sambuc     /*
330433d6423SLionel Sambuc      * The default is zero, and since the allocation above zeroed the data,
331433d6423SLionel Sambuc      * just do nothing on failure.
332433d6423SLionel Sambuc      */
333433d6423SLionel Sambuc     if (ACPI_SUCCESS (Status))
334433d6423SLionel Sambuc     {
335433d6423SLionel Sambuc         PciId->Device   = ACPI_HIWORD (ACPI_LODWORD (PciValue));
336433d6423SLionel Sambuc         PciId->Function = ACPI_LOWORD (ACPI_LODWORD (PciValue));
337433d6423SLionel Sambuc     }
338433d6423SLionel Sambuc 
339433d6423SLionel Sambuc     /* The PCI segment number comes from the _SEG method */
340433d6423SLionel Sambuc 
341433d6423SLionel Sambuc     Status = AcpiUtEvaluateNumericObject (METHOD_NAME__SEG,
342433d6423SLionel Sambuc                 PciRootNode, &PciValue);
343433d6423SLionel Sambuc     if (ACPI_SUCCESS (Status))
344433d6423SLionel Sambuc     {
345433d6423SLionel Sambuc         PciId->Segment = ACPI_LOWORD (PciValue);
346433d6423SLionel Sambuc     }
347433d6423SLionel Sambuc 
348433d6423SLionel Sambuc     /* The PCI bus number comes from the _BBN method */
349433d6423SLionel Sambuc 
350433d6423SLionel Sambuc     Status = AcpiUtEvaluateNumericObject (METHOD_NAME__BBN,
351433d6423SLionel Sambuc                 PciRootNode, &PciValue);
352433d6423SLionel Sambuc     if (ACPI_SUCCESS (Status))
353433d6423SLionel Sambuc     {
354433d6423SLionel Sambuc         PciId->Bus = ACPI_LOWORD (PciValue);
355433d6423SLionel Sambuc     }
356433d6423SLionel Sambuc 
357*29492bb7SDavid van Moolenbroek     /* Complete/update the PCI ID for this device */
358433d6423SLionel Sambuc 
359*29492bb7SDavid van Moolenbroek     Status = AcpiHwDerivePciId (PciId, PciRootNode, RegionObj->Region.Node);
360*29492bb7SDavid van Moolenbroek     if (ACPI_FAILURE (Status))
361*29492bb7SDavid van Moolenbroek     {
362*29492bb7SDavid van Moolenbroek         ACPI_FREE (PciId);
363*29492bb7SDavid van Moolenbroek         return_ACPI_STATUS (Status);
364*29492bb7SDavid van Moolenbroek     }
365433d6423SLionel Sambuc 
366433d6423SLionel Sambuc     *RegionContext = PciId;
367433d6423SLionel Sambuc     return_ACPI_STATUS (AE_OK);
368433d6423SLionel Sambuc }
369433d6423SLionel Sambuc 
370433d6423SLionel Sambuc 
371433d6423SLionel Sambuc /*******************************************************************************
372433d6423SLionel Sambuc  *
373433d6423SLionel Sambuc  * FUNCTION:    AcpiEvIsPciRootBridge
374433d6423SLionel Sambuc  *
375433d6423SLionel Sambuc  * PARAMETERS:  Node            - Device node being examined
376433d6423SLionel Sambuc  *
377433d6423SLionel Sambuc  * RETURN:      TRUE if device is a PCI/PCI-Express Root Bridge
378433d6423SLionel Sambuc  *
379433d6423SLionel Sambuc  * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by
380433d6423SLionel Sambuc  *              examining the _HID and _CID for the device.
381433d6423SLionel Sambuc  *
382433d6423SLionel Sambuc  ******************************************************************************/
383433d6423SLionel Sambuc 
384433d6423SLionel Sambuc static BOOLEAN
AcpiEvIsPciRootBridge(ACPI_NAMESPACE_NODE * Node)385433d6423SLionel Sambuc AcpiEvIsPciRootBridge (
386433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *Node)
387433d6423SLionel Sambuc {
388433d6423SLionel Sambuc     ACPI_STATUS             Status;
389*29492bb7SDavid van Moolenbroek     ACPI_PNP_DEVICE_ID      *Hid;
390*29492bb7SDavid van Moolenbroek     ACPI_PNP_DEVICE_ID_LIST *Cid;
391433d6423SLionel Sambuc     UINT32                  i;
392433d6423SLionel Sambuc     BOOLEAN                 Match;
393433d6423SLionel Sambuc 
394433d6423SLionel Sambuc 
395433d6423SLionel Sambuc     /* Get the _HID and check for a PCI Root Bridge */
396433d6423SLionel Sambuc 
397433d6423SLionel Sambuc     Status = AcpiUtExecute_HID (Node, &Hid);
398433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
399433d6423SLionel Sambuc     {
400433d6423SLionel Sambuc         return (FALSE);
401433d6423SLionel Sambuc     }
402433d6423SLionel Sambuc 
403433d6423SLionel Sambuc     Match = AcpiUtIsPciRootBridge (Hid->String);
404433d6423SLionel Sambuc     ACPI_FREE (Hid);
405433d6423SLionel Sambuc 
406433d6423SLionel Sambuc     if (Match)
407433d6423SLionel Sambuc     {
408433d6423SLionel Sambuc         return (TRUE);
409433d6423SLionel Sambuc     }
410433d6423SLionel Sambuc 
411433d6423SLionel Sambuc     /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */
412433d6423SLionel Sambuc 
413433d6423SLionel Sambuc     Status = AcpiUtExecute_CID (Node, &Cid);
414433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
415433d6423SLionel Sambuc     {
416433d6423SLionel Sambuc         return (FALSE);
417433d6423SLionel Sambuc     }
418433d6423SLionel Sambuc 
419433d6423SLionel Sambuc     /* Check all _CIDs in the returned list */
420433d6423SLionel Sambuc 
421433d6423SLionel Sambuc     for (i = 0; i < Cid->Count; i++)
422433d6423SLionel Sambuc     {
423433d6423SLionel Sambuc         if (AcpiUtIsPciRootBridge (Cid->Ids[i].String))
424433d6423SLionel Sambuc         {
425433d6423SLionel Sambuc             ACPI_FREE (Cid);
426433d6423SLionel Sambuc             return (TRUE);
427433d6423SLionel Sambuc         }
428433d6423SLionel Sambuc     }
429433d6423SLionel Sambuc 
430433d6423SLionel Sambuc     ACPI_FREE (Cid);
431433d6423SLionel Sambuc     return (FALSE);
432433d6423SLionel Sambuc }
433433d6423SLionel Sambuc 
434433d6423SLionel Sambuc 
435433d6423SLionel Sambuc /*******************************************************************************
436433d6423SLionel Sambuc  *
437433d6423SLionel Sambuc  * FUNCTION:    AcpiEvPciBarRegionSetup
438433d6423SLionel Sambuc  *
439433d6423SLionel Sambuc  * PARAMETERS:  Handle              - Region we are interested in
440433d6423SLionel Sambuc  *              Function            - Start or stop
441433d6423SLionel Sambuc  *              HandlerContext      - Address space handler context
442433d6423SLionel Sambuc  *              RegionContext       - Region specific context
443433d6423SLionel Sambuc  *
444433d6423SLionel Sambuc  * RETURN:      Status
445433d6423SLionel Sambuc  *
446433d6423SLionel Sambuc  * DESCRIPTION: Setup a PciBAR operation region
447433d6423SLionel Sambuc  *
448433d6423SLionel Sambuc  * MUTEX:       Assumes namespace is not locked
449433d6423SLionel Sambuc  *
450433d6423SLionel Sambuc  ******************************************************************************/
451433d6423SLionel Sambuc 
452433d6423SLionel Sambuc ACPI_STATUS
AcpiEvPciBarRegionSetup(ACPI_HANDLE Handle,UINT32 Function,void * HandlerContext,void ** RegionContext)453433d6423SLionel Sambuc AcpiEvPciBarRegionSetup (
454433d6423SLionel Sambuc     ACPI_HANDLE             Handle,
455433d6423SLionel Sambuc     UINT32                  Function,
456433d6423SLionel Sambuc     void                    *HandlerContext,
457433d6423SLionel Sambuc     void                    **RegionContext)
458433d6423SLionel Sambuc {
459433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE (EvPciBarRegionSetup);
460433d6423SLionel Sambuc 
461433d6423SLionel Sambuc 
462433d6423SLionel Sambuc     return_ACPI_STATUS (AE_OK);
463433d6423SLionel Sambuc }
464433d6423SLionel Sambuc 
465433d6423SLionel Sambuc 
466433d6423SLionel Sambuc /*******************************************************************************
467433d6423SLionel Sambuc  *
468433d6423SLionel Sambuc  * FUNCTION:    AcpiEvCmosRegionSetup
469433d6423SLionel Sambuc  *
470433d6423SLionel Sambuc  * PARAMETERS:  Handle              - Region we are interested in
471433d6423SLionel Sambuc  *              Function            - Start or stop
472433d6423SLionel Sambuc  *              HandlerContext      - Address space handler context
473433d6423SLionel Sambuc  *              RegionContext       - Region specific context
474433d6423SLionel Sambuc  *
475433d6423SLionel Sambuc  * RETURN:      Status
476433d6423SLionel Sambuc  *
477433d6423SLionel Sambuc  * DESCRIPTION: Setup a CMOS operation region
478433d6423SLionel Sambuc  *
479433d6423SLionel Sambuc  * MUTEX:       Assumes namespace is not locked
480433d6423SLionel Sambuc  *
481433d6423SLionel Sambuc  ******************************************************************************/
482433d6423SLionel Sambuc 
483433d6423SLionel Sambuc ACPI_STATUS
AcpiEvCmosRegionSetup(ACPI_HANDLE Handle,UINT32 Function,void * HandlerContext,void ** RegionContext)484433d6423SLionel Sambuc AcpiEvCmosRegionSetup (
485433d6423SLionel Sambuc     ACPI_HANDLE             Handle,
486433d6423SLionel Sambuc     UINT32                  Function,
487433d6423SLionel Sambuc     void                    *HandlerContext,
488433d6423SLionel Sambuc     void                    **RegionContext)
489433d6423SLionel Sambuc {
490433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE (EvCmosRegionSetup);
491433d6423SLionel Sambuc 
492433d6423SLionel Sambuc 
493433d6423SLionel Sambuc     return_ACPI_STATUS (AE_OK);
494433d6423SLionel Sambuc }
495433d6423SLionel Sambuc 
496433d6423SLionel Sambuc 
497433d6423SLionel Sambuc /*******************************************************************************
498433d6423SLionel Sambuc  *
499433d6423SLionel Sambuc  * FUNCTION:    AcpiEvDefaultRegionSetup
500433d6423SLionel Sambuc  *
501433d6423SLionel Sambuc  * PARAMETERS:  Handle              - Region we are interested in
502433d6423SLionel Sambuc  *              Function            - Start or stop
503433d6423SLionel Sambuc  *              HandlerContext      - Address space handler context
504433d6423SLionel Sambuc  *              RegionContext       - Region specific context
505433d6423SLionel Sambuc  *
506433d6423SLionel Sambuc  * RETURN:      Status
507433d6423SLionel Sambuc  *
508433d6423SLionel Sambuc  * DESCRIPTION: Default region initialization
509433d6423SLionel Sambuc  *
510433d6423SLionel Sambuc  ******************************************************************************/
511433d6423SLionel Sambuc 
512433d6423SLionel Sambuc ACPI_STATUS
AcpiEvDefaultRegionSetup(ACPI_HANDLE Handle,UINT32 Function,void * HandlerContext,void ** RegionContext)513433d6423SLionel Sambuc AcpiEvDefaultRegionSetup (
514433d6423SLionel Sambuc     ACPI_HANDLE             Handle,
515433d6423SLionel Sambuc     UINT32                  Function,
516433d6423SLionel Sambuc     void                    *HandlerContext,
517433d6423SLionel Sambuc     void                    **RegionContext)
518433d6423SLionel Sambuc {
519433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE (EvDefaultRegionSetup);
520433d6423SLionel Sambuc 
521433d6423SLionel Sambuc 
522433d6423SLionel Sambuc     if (Function == ACPI_REGION_DEACTIVATE)
523433d6423SLionel Sambuc     {
524433d6423SLionel Sambuc         *RegionContext = NULL;
525433d6423SLionel Sambuc     }
526433d6423SLionel Sambuc     else
527433d6423SLionel Sambuc     {
528433d6423SLionel Sambuc         *RegionContext = HandlerContext;
529433d6423SLionel Sambuc     }
530433d6423SLionel Sambuc 
531433d6423SLionel Sambuc     return_ACPI_STATUS (AE_OK);
532433d6423SLionel Sambuc }
533433d6423SLionel Sambuc 
534433d6423SLionel Sambuc 
535433d6423SLionel Sambuc /*******************************************************************************
536433d6423SLionel Sambuc  *
537433d6423SLionel Sambuc  * FUNCTION:    AcpiEvInitializeRegion
538433d6423SLionel Sambuc  *
539433d6423SLionel Sambuc  * PARAMETERS:  RegionObj       - Region we are initializing
540433d6423SLionel Sambuc  *              AcpiNsLocked    - Is namespace locked?
541433d6423SLionel Sambuc  *
542433d6423SLionel Sambuc  * RETURN:      Status
543433d6423SLionel Sambuc  *
544433d6423SLionel Sambuc  * DESCRIPTION: Initializes the region, finds any _REG methods and saves them
545433d6423SLionel Sambuc  *              for execution at a later time
546433d6423SLionel Sambuc  *
547433d6423SLionel Sambuc  *              Get the appropriate address space handler for a newly
548433d6423SLionel Sambuc  *              created region.
549433d6423SLionel Sambuc  *
550433d6423SLionel Sambuc  *              This also performs address space specific initialization. For
551433d6423SLionel Sambuc  *              example, PCI regions must have an _ADR object that contains
552433d6423SLionel Sambuc  *              a PCI address in the scope of the definition. This address is
553433d6423SLionel Sambuc  *              required to perform an access to PCI config space.
554433d6423SLionel Sambuc  *
555433d6423SLionel Sambuc  * MUTEX:       Interpreter should be unlocked, because we may run the _REG
556433d6423SLionel Sambuc  *              method for this region.
557433d6423SLionel Sambuc  *
558433d6423SLionel Sambuc  ******************************************************************************/
559433d6423SLionel Sambuc 
560433d6423SLionel Sambuc ACPI_STATUS
AcpiEvInitializeRegion(ACPI_OPERAND_OBJECT * RegionObj,BOOLEAN AcpiNsLocked)561433d6423SLionel Sambuc AcpiEvInitializeRegion (
562433d6423SLionel Sambuc     ACPI_OPERAND_OBJECT     *RegionObj,
563433d6423SLionel Sambuc     BOOLEAN                 AcpiNsLocked)
564433d6423SLionel Sambuc {
565433d6423SLionel Sambuc     ACPI_OPERAND_OBJECT     *HandlerObj;
566433d6423SLionel Sambuc     ACPI_OPERAND_OBJECT     *ObjDesc;
567433d6423SLionel Sambuc     ACPI_ADR_SPACE_TYPE     SpaceId;
568433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *Node;
569433d6423SLionel Sambuc     ACPI_STATUS             Status;
570433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *MethodNode;
571433d6423SLionel Sambuc     ACPI_NAME               *RegNamePtr = (ACPI_NAME *) METHOD_NAME__REG;
572433d6423SLionel Sambuc     ACPI_OPERAND_OBJECT     *RegionObj2;
573433d6423SLionel Sambuc 
574433d6423SLionel Sambuc 
575433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE_U32 (EvInitializeRegion, AcpiNsLocked);
576433d6423SLionel Sambuc 
577433d6423SLionel Sambuc 
578433d6423SLionel Sambuc     if (!RegionObj)
579433d6423SLionel Sambuc     {
580433d6423SLionel Sambuc         return_ACPI_STATUS (AE_BAD_PARAMETER);
581433d6423SLionel Sambuc     }
582433d6423SLionel Sambuc 
583433d6423SLionel Sambuc     if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED)
584433d6423SLionel Sambuc     {
585433d6423SLionel Sambuc         return_ACPI_STATUS (AE_OK);
586433d6423SLionel Sambuc     }
587433d6423SLionel Sambuc 
588433d6423SLionel Sambuc     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
589433d6423SLionel Sambuc     if (!RegionObj2)
590433d6423SLionel Sambuc     {
591433d6423SLionel Sambuc         return_ACPI_STATUS (AE_NOT_EXIST);
592433d6423SLionel Sambuc     }
593433d6423SLionel Sambuc 
594433d6423SLionel Sambuc     Node = RegionObj->Region.Node->Parent;
595433d6423SLionel Sambuc     SpaceId = RegionObj->Region.SpaceId;
596433d6423SLionel Sambuc 
597433d6423SLionel Sambuc     /* Setup defaults */
598433d6423SLionel Sambuc 
599433d6423SLionel Sambuc     RegionObj->Region.Handler = NULL;
600433d6423SLionel Sambuc     RegionObj2->Extra.Method_REG = NULL;
601433d6423SLionel Sambuc     RegionObj->Common.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
602433d6423SLionel Sambuc     RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED;
603433d6423SLionel Sambuc 
604433d6423SLionel Sambuc     /* Find any "_REG" method associated with this region definition */
605433d6423SLionel Sambuc 
606433d6423SLionel Sambuc     Status = AcpiNsSearchOneScope (
607433d6423SLionel Sambuc                 *RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode);
608433d6423SLionel Sambuc     if (ACPI_SUCCESS (Status))
609433d6423SLionel Sambuc     {
610433d6423SLionel Sambuc         /*
611433d6423SLionel Sambuc          * The _REG method is optional and there can be only one per region
612433d6423SLionel Sambuc          * definition. This will be executed when the handler is attached
613433d6423SLionel Sambuc          * or removed
614433d6423SLionel Sambuc          */
615433d6423SLionel Sambuc         RegionObj2->Extra.Method_REG = MethodNode;
616433d6423SLionel Sambuc     }
617433d6423SLionel Sambuc 
618433d6423SLionel Sambuc     /*
619433d6423SLionel Sambuc      * The following loop depends upon the root Node having no parent
620433d6423SLionel Sambuc      * ie: AcpiGbl_RootNode->ParentEntry being set to NULL
621433d6423SLionel Sambuc      */
622433d6423SLionel Sambuc     while (Node)
623433d6423SLionel Sambuc     {
624433d6423SLionel Sambuc         /* Check to see if a handler exists */
625433d6423SLionel Sambuc 
626433d6423SLionel Sambuc         HandlerObj = NULL;
627433d6423SLionel Sambuc         ObjDesc = AcpiNsGetAttachedObject (Node);
628433d6423SLionel Sambuc         if (ObjDesc)
629433d6423SLionel Sambuc         {
630433d6423SLionel Sambuc             /* Can only be a handler if the object exists */
631433d6423SLionel Sambuc 
632433d6423SLionel Sambuc             switch (Node->Type)
633433d6423SLionel Sambuc             {
634433d6423SLionel Sambuc             case ACPI_TYPE_DEVICE:
635433d6423SLionel Sambuc 
636433d6423SLionel Sambuc                 HandlerObj = ObjDesc->Device.Handler;
637433d6423SLionel Sambuc                 break;
638433d6423SLionel Sambuc 
639433d6423SLionel Sambuc             case ACPI_TYPE_PROCESSOR:
640433d6423SLionel Sambuc 
641433d6423SLionel Sambuc                 HandlerObj = ObjDesc->Processor.Handler;
642433d6423SLionel Sambuc                 break;
643433d6423SLionel Sambuc 
644433d6423SLionel Sambuc             case ACPI_TYPE_THERMAL:
645433d6423SLionel Sambuc 
646433d6423SLionel Sambuc                 HandlerObj = ObjDesc->ThermalZone.Handler;
647433d6423SLionel Sambuc                 break;
648433d6423SLionel Sambuc 
649433d6423SLionel Sambuc             case ACPI_TYPE_METHOD:
650433d6423SLionel Sambuc                 /*
651433d6423SLionel Sambuc                  * If we are executing module level code, the original
652433d6423SLionel Sambuc                  * Node's object was replaced by this Method object and we
653433d6423SLionel Sambuc                  * saved the handler in the method object.
654433d6423SLionel Sambuc                  *
655433d6423SLionel Sambuc                  * See AcpiNsExecModuleCode
656433d6423SLionel Sambuc                  */
657*29492bb7SDavid van Moolenbroek                 if (ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL)
658433d6423SLionel Sambuc                 {
659*29492bb7SDavid van Moolenbroek                     HandlerObj = ObjDesc->Method.Dispatch.Handler;
660433d6423SLionel Sambuc                 }
661433d6423SLionel Sambuc                 break;
662433d6423SLionel Sambuc 
663433d6423SLionel Sambuc             default:
664*29492bb7SDavid van Moolenbroek 
665433d6423SLionel Sambuc                 /* Ignore other objects */
666*29492bb7SDavid van Moolenbroek 
667433d6423SLionel Sambuc                 break;
668433d6423SLionel Sambuc             }
669433d6423SLionel Sambuc 
670433d6423SLionel Sambuc             while (HandlerObj)
671433d6423SLionel Sambuc             {
672433d6423SLionel Sambuc                 /* Is this handler of the correct type? */
673433d6423SLionel Sambuc 
674433d6423SLionel Sambuc                 if (HandlerObj->AddressSpace.SpaceId == SpaceId)
675433d6423SLionel Sambuc                 {
676433d6423SLionel Sambuc                     /* Found correct handler */
677433d6423SLionel Sambuc 
678433d6423SLionel Sambuc                     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
679433d6423SLionel Sambuc                         "Found handler %p for region %p in obj %p\n",
680433d6423SLionel Sambuc                         HandlerObj, RegionObj, ObjDesc));
681433d6423SLionel Sambuc 
682433d6423SLionel Sambuc                     Status = AcpiEvAttachRegion (HandlerObj, RegionObj,
683433d6423SLionel Sambuc                                 AcpiNsLocked);
684433d6423SLionel Sambuc 
685433d6423SLionel Sambuc                     /*
686433d6423SLionel Sambuc                      * Tell all users that this region is usable by
687433d6423SLionel Sambuc                      * running the _REG method
688433d6423SLionel Sambuc                      */
689433d6423SLionel Sambuc                     if (AcpiNsLocked)
690433d6423SLionel Sambuc                     {
691433d6423SLionel Sambuc                         Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
692433d6423SLionel Sambuc                         if (ACPI_FAILURE (Status))
693433d6423SLionel Sambuc                         {
694433d6423SLionel Sambuc                             return_ACPI_STATUS (Status);
695433d6423SLionel Sambuc                         }
696433d6423SLionel Sambuc                     }
697433d6423SLionel Sambuc 
698*29492bb7SDavid van Moolenbroek                     Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT);
699433d6423SLionel Sambuc 
700433d6423SLionel Sambuc                     if (AcpiNsLocked)
701433d6423SLionel Sambuc                     {
702433d6423SLionel Sambuc                         Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
703433d6423SLionel Sambuc                         if (ACPI_FAILURE (Status))
704433d6423SLionel Sambuc                         {
705433d6423SLionel Sambuc                             return_ACPI_STATUS (Status);
706433d6423SLionel Sambuc                         }
707433d6423SLionel Sambuc                     }
708433d6423SLionel Sambuc 
709433d6423SLionel Sambuc                     return_ACPI_STATUS (AE_OK);
710433d6423SLionel Sambuc                 }
711433d6423SLionel Sambuc 
712433d6423SLionel Sambuc                 /* Try next handler in the list */
713433d6423SLionel Sambuc 
714433d6423SLionel Sambuc                 HandlerObj = HandlerObj->AddressSpace.Next;
715433d6423SLionel Sambuc             }
716433d6423SLionel Sambuc         }
717433d6423SLionel Sambuc 
718433d6423SLionel Sambuc         /* This node does not have the handler we need; Pop up one level */
719433d6423SLionel Sambuc 
720433d6423SLionel Sambuc         Node = Node->Parent;
721433d6423SLionel Sambuc     }
722433d6423SLionel Sambuc 
723433d6423SLionel Sambuc     /* If we get here, there is no handler for this region */
724433d6423SLionel Sambuc 
725433d6423SLionel Sambuc     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
726433d6423SLionel Sambuc         "No handler for RegionType %s(%X) (RegionObj %p)\n",
727433d6423SLionel Sambuc         AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj));
728433d6423SLionel Sambuc 
729433d6423SLionel Sambuc     return_ACPI_STATUS (AE_NOT_EXIST);
730433d6423SLionel Sambuc }
731