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