1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Module Name: evrgnini- ACPI address_space (op_region) init
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (C) 2000 - 2020, Intel Corp.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun *****************************************************************************/
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <acpi/acpi.h>
11*4882a593Smuzhiyun #include "accommon.h"
12*4882a593Smuzhiyun #include "acevents.h"
13*4882a593Smuzhiyun #include "acnamesp.h"
14*4882a593Smuzhiyun #include "acinterp.h"
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #define _COMPONENT ACPI_EVENTS
17*4882a593Smuzhiyun ACPI_MODULE_NAME("evrgnini")
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /*******************************************************************************
20*4882a593Smuzhiyun *
21*4882a593Smuzhiyun * FUNCTION: acpi_ev_system_memory_region_setup
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * PARAMETERS: handle - Region we are interested in
24*4882a593Smuzhiyun * function - Start or stop
25*4882a593Smuzhiyun * handler_context - Address space handler context
26*4882a593Smuzhiyun * region_context - Region specific context
27*4882a593Smuzhiyun *
28*4882a593Smuzhiyun * RETURN: Status
29*4882a593Smuzhiyun *
30*4882a593Smuzhiyun * DESCRIPTION: Setup a system_memory operation region
31*4882a593Smuzhiyun *
32*4882a593Smuzhiyun ******************************************************************************/
33*4882a593Smuzhiyun acpi_status
acpi_ev_system_memory_region_setup(acpi_handle handle,u32 function,void * handler_context,void ** region_context)34*4882a593Smuzhiyun acpi_ev_system_memory_region_setup(acpi_handle handle,
35*4882a593Smuzhiyun u32 function,
36*4882a593Smuzhiyun void *handler_context, void **region_context)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun union acpi_operand_object *region_desc =
39*4882a593Smuzhiyun (union acpi_operand_object *)handle;
40*4882a593Smuzhiyun struct acpi_mem_space_context *local_region_context;
41*4882a593Smuzhiyun struct acpi_mem_mapping *mm;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ev_system_memory_region_setup);
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun if (function == ACPI_REGION_DEACTIVATE) {
46*4882a593Smuzhiyun if (*region_context) {
47*4882a593Smuzhiyun local_region_context =
48*4882a593Smuzhiyun (struct acpi_mem_space_context *)*region_context;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /* Delete memory mappings if present */
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun while (local_region_context->first_mm) {
53*4882a593Smuzhiyun mm = local_region_context->first_mm;
54*4882a593Smuzhiyun local_region_context->first_mm = mm->next_mm;
55*4882a593Smuzhiyun acpi_os_unmap_memory(mm->logical_address,
56*4882a593Smuzhiyun mm->length);
57*4882a593Smuzhiyun ACPI_FREE(mm);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun ACPI_FREE(local_region_context);
60*4882a593Smuzhiyun *region_context = NULL;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun /* Create a new context */
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun local_region_context =
68*4882a593Smuzhiyun ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context));
69*4882a593Smuzhiyun if (!(local_region_context)) {
70*4882a593Smuzhiyun return_ACPI_STATUS(AE_NO_MEMORY);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun /* Save the region length and address for use in the handler */
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun local_region_context->length = region_desc->region.length;
76*4882a593Smuzhiyun local_region_context->address = region_desc->region.address;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun *region_context = local_region_context;
79*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /*******************************************************************************
83*4882a593Smuzhiyun *
84*4882a593Smuzhiyun * FUNCTION: acpi_ev_io_space_region_setup
85*4882a593Smuzhiyun *
86*4882a593Smuzhiyun * PARAMETERS: handle - Region we are interested in
87*4882a593Smuzhiyun * function - Start or stop
88*4882a593Smuzhiyun * handler_context - Address space handler context
89*4882a593Smuzhiyun * region_context - Region specific context
90*4882a593Smuzhiyun *
91*4882a593Smuzhiyun * RETURN: Status
92*4882a593Smuzhiyun *
93*4882a593Smuzhiyun * DESCRIPTION: Setup a IO operation region
94*4882a593Smuzhiyun *
95*4882a593Smuzhiyun ******************************************************************************/
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun acpi_status
acpi_ev_io_space_region_setup(acpi_handle handle,u32 function,void * handler_context,void ** region_context)98*4882a593Smuzhiyun acpi_ev_io_space_region_setup(acpi_handle handle,
99*4882a593Smuzhiyun u32 function,
100*4882a593Smuzhiyun void *handler_context, void **region_context)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ev_io_space_region_setup);
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun if (function == ACPI_REGION_DEACTIVATE) {
105*4882a593Smuzhiyun *region_context = NULL;
106*4882a593Smuzhiyun } else {
107*4882a593Smuzhiyun *region_context = handler_context;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /*******************************************************************************
114*4882a593Smuzhiyun *
115*4882a593Smuzhiyun * FUNCTION: acpi_ev_pci_config_region_setup
116*4882a593Smuzhiyun *
117*4882a593Smuzhiyun * PARAMETERS: handle - Region we are interested in
118*4882a593Smuzhiyun * function - Start or stop
119*4882a593Smuzhiyun * handler_context - Address space handler context
120*4882a593Smuzhiyun * region_context - Region specific context
121*4882a593Smuzhiyun *
122*4882a593Smuzhiyun * RETURN: Status
123*4882a593Smuzhiyun *
124*4882a593Smuzhiyun * DESCRIPTION: Setup a PCI_Config operation region
125*4882a593Smuzhiyun *
126*4882a593Smuzhiyun * MUTEX: Assumes namespace is not locked
127*4882a593Smuzhiyun *
128*4882a593Smuzhiyun ******************************************************************************/
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun acpi_status
acpi_ev_pci_config_region_setup(acpi_handle handle,u32 function,void * handler_context,void ** region_context)131*4882a593Smuzhiyun acpi_ev_pci_config_region_setup(acpi_handle handle,
132*4882a593Smuzhiyun u32 function,
133*4882a593Smuzhiyun void *handler_context, void **region_context)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun acpi_status status = AE_OK;
136*4882a593Smuzhiyun u64 pci_value;
137*4882a593Smuzhiyun struct acpi_pci_id *pci_id = *region_context;
138*4882a593Smuzhiyun union acpi_operand_object *handler_obj;
139*4882a593Smuzhiyun struct acpi_namespace_node *parent_node;
140*4882a593Smuzhiyun struct acpi_namespace_node *pci_root_node;
141*4882a593Smuzhiyun struct acpi_namespace_node *pci_device_node;
142*4882a593Smuzhiyun union acpi_operand_object *region_obj =
143*4882a593Smuzhiyun (union acpi_operand_object *)handle;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ev_pci_config_region_setup);
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun handler_obj = region_obj->region.handler;
148*4882a593Smuzhiyun if (!handler_obj) {
149*4882a593Smuzhiyun /*
150*4882a593Smuzhiyun * No installed handler. This shouldn't happen because the dispatch
151*4882a593Smuzhiyun * routine checks before we get here, but we check again just in case.
152*4882a593Smuzhiyun */
153*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
154*4882a593Smuzhiyun "Attempting to init a region %p, with no handler\n",
155*4882a593Smuzhiyun region_obj));
156*4882a593Smuzhiyun return_ACPI_STATUS(AE_NOT_EXIST);
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun *region_context = NULL;
160*4882a593Smuzhiyun if (function == ACPI_REGION_DEACTIVATE) {
161*4882a593Smuzhiyun if (pci_id) {
162*4882a593Smuzhiyun ACPI_FREE(pci_id);
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun return_ACPI_STATUS(status);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun parent_node = region_obj->region.node->parent;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /*
170*4882a593Smuzhiyun * Get the _SEG and _BBN values from the device upon which the handler
171*4882a593Smuzhiyun * is installed.
172*4882a593Smuzhiyun *
173*4882a593Smuzhiyun * We need to get the _SEG and _BBN objects relative to the PCI BUS device.
174*4882a593Smuzhiyun * This is the device the handler has been registered to handle.
175*4882a593Smuzhiyun */
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun /*
178*4882a593Smuzhiyun * If the address_space.Node is still pointing to the root, we need
179*4882a593Smuzhiyun * to scan upward for a PCI Root bridge and re-associate the op_region
180*4882a593Smuzhiyun * handlers with that device.
181*4882a593Smuzhiyun */
182*4882a593Smuzhiyun if (handler_obj->address_space.node == acpi_gbl_root_node) {
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun /* Start search from the parent object */
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun pci_root_node = parent_node;
187*4882a593Smuzhiyun while (pci_root_node != acpi_gbl_root_node) {
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun /* Get the _HID/_CID in order to detect a root_bridge */
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun if (acpi_ev_is_pci_root_bridge(pci_root_node)) {
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /* Install a handler for this PCI root bridge */
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun status = acpi_install_address_space_handler((acpi_handle)pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
196*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
197*4882a593Smuzhiyun if (status == AE_SAME_HANDLER) {
198*4882a593Smuzhiyun /*
199*4882a593Smuzhiyun * It is OK if the handler is already installed on the
200*4882a593Smuzhiyun * root bridge. Still need to return a context object
201*4882a593Smuzhiyun * for the new PCI_Config operation region, however.
202*4882a593Smuzhiyun */
203*4882a593Smuzhiyun } else {
204*4882a593Smuzhiyun ACPI_EXCEPTION((AE_INFO, status,
205*4882a593Smuzhiyun "Could not install PciConfig handler "
206*4882a593Smuzhiyun "for Root Bridge %4.4s",
207*4882a593Smuzhiyun acpi_ut_get_node_name
208*4882a593Smuzhiyun (pci_root_node)));
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun break;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun pci_root_node = pci_root_node->parent;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /* PCI root bridge not found, use namespace root node */
218*4882a593Smuzhiyun } else {
219*4882a593Smuzhiyun pci_root_node = handler_obj->address_space.node;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun /*
223*4882a593Smuzhiyun * If this region is now initialized, we are done.
224*4882a593Smuzhiyun * (install_address_space_handler could have initialized it)
225*4882a593Smuzhiyun */
226*4882a593Smuzhiyun if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
227*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun /* Region is still not initialized. Create a new context */
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id));
233*4882a593Smuzhiyun if (!pci_id) {
234*4882a593Smuzhiyun return_ACPI_STATUS(AE_NO_MEMORY);
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun /*
238*4882a593Smuzhiyun * For PCI_Config space access, we need the segment, bus, device and
239*4882a593Smuzhiyun * function numbers. Acquire them here.
240*4882a593Smuzhiyun *
241*4882a593Smuzhiyun * Find the parent device object. (This allows the operation region to be
242*4882a593Smuzhiyun * within a subscope under the device, such as a control method.)
243*4882a593Smuzhiyun */
244*4882a593Smuzhiyun pci_device_node = region_obj->region.node;
245*4882a593Smuzhiyun while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) {
246*4882a593Smuzhiyun pci_device_node = pci_device_node->parent;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun if (!pci_device_node) {
250*4882a593Smuzhiyun ACPI_FREE(pci_id);
251*4882a593Smuzhiyun return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun /*
255*4882a593Smuzhiyun * Get the PCI device and function numbers from the _ADR object
256*4882a593Smuzhiyun * contained in the parent's scope.
257*4882a593Smuzhiyun */
258*4882a593Smuzhiyun status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
259*4882a593Smuzhiyun pci_device_node, &pci_value);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun /*
262*4882a593Smuzhiyun * The default is zero, and since the allocation above zeroed the data,
263*4882a593Smuzhiyun * just do nothing on failure.
264*4882a593Smuzhiyun */
265*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
266*4882a593Smuzhiyun pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value));
267*4882a593Smuzhiyun pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value));
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /* The PCI segment number comes from the _SEG method */
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun status = acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG,
273*4882a593Smuzhiyun pci_root_node, &pci_value);
274*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
275*4882a593Smuzhiyun pci_id->segment = ACPI_LOWORD(pci_value);
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun /* The PCI bus number comes from the _BBN method */
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun status = acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN,
281*4882a593Smuzhiyun pci_root_node, &pci_value);
282*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
283*4882a593Smuzhiyun pci_id->bus = ACPI_LOWORD(pci_value);
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun /* Complete/update the PCI ID for this device */
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun status =
289*4882a593Smuzhiyun acpi_hw_derive_pci_id(pci_id, pci_root_node,
290*4882a593Smuzhiyun region_obj->region.node);
291*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
292*4882a593Smuzhiyun ACPI_FREE(pci_id);
293*4882a593Smuzhiyun return_ACPI_STATUS(status);
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun *region_context = pci_id;
297*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun /*******************************************************************************
301*4882a593Smuzhiyun *
302*4882a593Smuzhiyun * FUNCTION: acpi_ev_is_pci_root_bridge
303*4882a593Smuzhiyun *
304*4882a593Smuzhiyun * PARAMETERS: node - Device node being examined
305*4882a593Smuzhiyun *
306*4882a593Smuzhiyun * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge
307*4882a593Smuzhiyun *
308*4882a593Smuzhiyun * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by
309*4882a593Smuzhiyun * examining the _HID and _CID for the device.
310*4882a593Smuzhiyun *
311*4882a593Smuzhiyun ******************************************************************************/
312*4882a593Smuzhiyun
acpi_ev_is_pci_root_bridge(struct acpi_namespace_node * node)313*4882a593Smuzhiyun u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun acpi_status status;
316*4882a593Smuzhiyun struct acpi_pnp_device_id *hid;
317*4882a593Smuzhiyun struct acpi_pnp_device_id_list *cid;
318*4882a593Smuzhiyun u32 i;
319*4882a593Smuzhiyun u8 match;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun /* Get the _HID and check for a PCI Root Bridge */
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun status = acpi_ut_execute_HID(node, &hid);
324*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
325*4882a593Smuzhiyun return (FALSE);
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun match = acpi_ut_is_pci_root_bridge(hid->string);
329*4882a593Smuzhiyun ACPI_FREE(hid);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun if (match) {
332*4882a593Smuzhiyun return (TRUE);
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun status = acpi_ut_execute_CID(node, &cid);
338*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
339*4882a593Smuzhiyun return (FALSE);
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun /* Check all _CIDs in the returned list */
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun for (i = 0; i < cid->count; i++) {
345*4882a593Smuzhiyun if (acpi_ut_is_pci_root_bridge(cid->ids[i].string)) {
346*4882a593Smuzhiyun ACPI_FREE(cid);
347*4882a593Smuzhiyun return (TRUE);
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun ACPI_FREE(cid);
352*4882a593Smuzhiyun return (FALSE);
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun /*******************************************************************************
356*4882a593Smuzhiyun *
357*4882a593Smuzhiyun * FUNCTION: acpi_ev_pci_bar_region_setup
358*4882a593Smuzhiyun *
359*4882a593Smuzhiyun * PARAMETERS: handle - Region we are interested in
360*4882a593Smuzhiyun * function - Start or stop
361*4882a593Smuzhiyun * handler_context - Address space handler context
362*4882a593Smuzhiyun * region_context - Region specific context
363*4882a593Smuzhiyun *
364*4882a593Smuzhiyun * RETURN: Status
365*4882a593Smuzhiyun *
366*4882a593Smuzhiyun * DESCRIPTION: Setup a pci_BAR operation region
367*4882a593Smuzhiyun *
368*4882a593Smuzhiyun * MUTEX: Assumes namespace is not locked
369*4882a593Smuzhiyun *
370*4882a593Smuzhiyun ******************************************************************************/
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun acpi_status
acpi_ev_pci_bar_region_setup(acpi_handle handle,u32 function,void * handler_context,void ** region_context)373*4882a593Smuzhiyun acpi_ev_pci_bar_region_setup(acpi_handle handle,
374*4882a593Smuzhiyun u32 function,
375*4882a593Smuzhiyun void *handler_context, void **region_context)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup);
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun /*******************************************************************************
383*4882a593Smuzhiyun *
384*4882a593Smuzhiyun * FUNCTION: acpi_ev_cmos_region_setup
385*4882a593Smuzhiyun *
386*4882a593Smuzhiyun * PARAMETERS: handle - Region we are interested in
387*4882a593Smuzhiyun * function - Start or stop
388*4882a593Smuzhiyun * handler_context - Address space handler context
389*4882a593Smuzhiyun * region_context - Region specific context
390*4882a593Smuzhiyun *
391*4882a593Smuzhiyun * RETURN: Status
392*4882a593Smuzhiyun *
393*4882a593Smuzhiyun * DESCRIPTION: Setup a CMOS operation region
394*4882a593Smuzhiyun *
395*4882a593Smuzhiyun * MUTEX: Assumes namespace is not locked
396*4882a593Smuzhiyun *
397*4882a593Smuzhiyun ******************************************************************************/
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun acpi_status
acpi_ev_cmos_region_setup(acpi_handle handle,u32 function,void * handler_context,void ** region_context)400*4882a593Smuzhiyun acpi_ev_cmos_region_setup(acpi_handle handle,
401*4882a593Smuzhiyun u32 function,
402*4882a593Smuzhiyun void *handler_context, void **region_context)
403*4882a593Smuzhiyun {
404*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ev_cmos_region_setup);
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun /*******************************************************************************
410*4882a593Smuzhiyun *
411*4882a593Smuzhiyun * FUNCTION: acpi_ev_default_region_setup
412*4882a593Smuzhiyun *
413*4882a593Smuzhiyun * PARAMETERS: handle - Region we are interested in
414*4882a593Smuzhiyun * function - Start or stop
415*4882a593Smuzhiyun * handler_context - Address space handler context
416*4882a593Smuzhiyun * region_context - Region specific context
417*4882a593Smuzhiyun *
418*4882a593Smuzhiyun * RETURN: Status
419*4882a593Smuzhiyun *
420*4882a593Smuzhiyun * DESCRIPTION: Default region initialization
421*4882a593Smuzhiyun *
422*4882a593Smuzhiyun ******************************************************************************/
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun acpi_status
acpi_ev_default_region_setup(acpi_handle handle,u32 function,void * handler_context,void ** region_context)425*4882a593Smuzhiyun acpi_ev_default_region_setup(acpi_handle handle,
426*4882a593Smuzhiyun u32 function,
427*4882a593Smuzhiyun void *handler_context, void **region_context)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ev_default_region_setup);
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun if (function == ACPI_REGION_DEACTIVATE) {
432*4882a593Smuzhiyun *region_context = NULL;
433*4882a593Smuzhiyun } else {
434*4882a593Smuzhiyun *region_context = handler_context;
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun /*******************************************************************************
441*4882a593Smuzhiyun *
442*4882a593Smuzhiyun * FUNCTION: acpi_ev_initialize_region
443*4882a593Smuzhiyun *
444*4882a593Smuzhiyun * PARAMETERS: region_obj - Region we are initializing
445*4882a593Smuzhiyun *
446*4882a593Smuzhiyun * RETURN: Status
447*4882a593Smuzhiyun *
448*4882a593Smuzhiyun * DESCRIPTION: Initializes the region, finds any _REG methods and saves them
449*4882a593Smuzhiyun * for execution at a later time
450*4882a593Smuzhiyun *
451*4882a593Smuzhiyun * Get the appropriate address space handler for a newly
452*4882a593Smuzhiyun * created region.
453*4882a593Smuzhiyun *
454*4882a593Smuzhiyun * This also performs address space specific initialization. For
455*4882a593Smuzhiyun * example, PCI regions must have an _ADR object that contains
456*4882a593Smuzhiyun * a PCI address in the scope of the definition. This address is
457*4882a593Smuzhiyun * required to perform an access to PCI config space.
458*4882a593Smuzhiyun *
459*4882a593Smuzhiyun * MUTEX: Interpreter should be unlocked, because we may run the _REG
460*4882a593Smuzhiyun * method for this region.
461*4882a593Smuzhiyun *
462*4882a593Smuzhiyun * NOTE: Possible incompliance:
463*4882a593Smuzhiyun * There is a behavior conflict in automatic _REG execution:
464*4882a593Smuzhiyun * 1. When the interpreter is evaluating a method, we can only
465*4882a593Smuzhiyun * automatically run _REG for the following case:
466*4882a593Smuzhiyun * operation_region (OPR1, 0x80, 0x1000010, 0x4)
467*4882a593Smuzhiyun * 2. When the interpreter is loading a table, we can also
468*4882a593Smuzhiyun * automatically run _REG for the following case:
469*4882a593Smuzhiyun * operation_region (OPR1, 0x80, 0x1000010, 0x4)
470*4882a593Smuzhiyun * Though this may not be compliant to the de-facto standard, the
471*4882a593Smuzhiyun * logic is kept in order not to trigger regressions. And keeping
472*4882a593Smuzhiyun * this logic should be taken care by the caller of this function.
473*4882a593Smuzhiyun *
474*4882a593Smuzhiyun ******************************************************************************/
475*4882a593Smuzhiyun
acpi_ev_initialize_region(union acpi_operand_object * region_obj)476*4882a593Smuzhiyun acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun union acpi_operand_object *handler_obj;
479*4882a593Smuzhiyun union acpi_operand_object *obj_desc;
480*4882a593Smuzhiyun acpi_adr_space_type space_id;
481*4882a593Smuzhiyun struct acpi_namespace_node *node;
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ev_initialize_region);
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun if (!region_obj) {
486*4882a593Smuzhiyun return_ACPI_STATUS(AE_BAD_PARAMETER);
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) {
490*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun node = region_obj->region.node->parent;
496*4882a593Smuzhiyun space_id = region_obj->region.space_id;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun /*
499*4882a593Smuzhiyun * The following loop depends upon the root Node having no parent
500*4882a593Smuzhiyun * ie: acpi_gbl_root_node->Parent being set to NULL
501*4882a593Smuzhiyun */
502*4882a593Smuzhiyun while (node) {
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun /* Check to see if a handler exists */
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun handler_obj = NULL;
507*4882a593Smuzhiyun obj_desc = acpi_ns_get_attached_object(node);
508*4882a593Smuzhiyun if (obj_desc) {
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun /* Can only be a handler if the object exists */
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun switch (node->type) {
513*4882a593Smuzhiyun case ACPI_TYPE_DEVICE:
514*4882a593Smuzhiyun case ACPI_TYPE_PROCESSOR:
515*4882a593Smuzhiyun case ACPI_TYPE_THERMAL:
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun handler_obj = obj_desc->common_notify.handler;
518*4882a593Smuzhiyun break;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun default:
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun /* Ignore other objects */
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun break;
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun handler_obj =
528*4882a593Smuzhiyun acpi_ev_find_region_handler(space_id, handler_obj);
529*4882a593Smuzhiyun if (handler_obj) {
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun /* Found correct handler */
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
534*4882a593Smuzhiyun "Found handler %p for region %p in obj %p\n",
535*4882a593Smuzhiyun handler_obj, region_obj,
536*4882a593Smuzhiyun obj_desc));
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun (void)acpi_ev_attach_region(handler_obj,
539*4882a593Smuzhiyun region_obj, FALSE);
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun /*
542*4882a593Smuzhiyun * Tell all users that this region is usable by
543*4882a593Smuzhiyun * running the _REG method
544*4882a593Smuzhiyun */
545*4882a593Smuzhiyun acpi_ex_exit_interpreter();
546*4882a593Smuzhiyun (void)acpi_ev_execute_reg_method(region_obj,
547*4882a593Smuzhiyun ACPI_REG_CONNECT);
548*4882a593Smuzhiyun acpi_ex_enter_interpreter();
549*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun /* This node does not have the handler we need; Pop up one level */
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun node = node->parent;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun /*
559*4882a593Smuzhiyun * If we get here, there is no handler for this region. This is not
560*4882a593Smuzhiyun * fatal because many regions get created before a handler is installed
561*4882a593Smuzhiyun * for said region.
562*4882a593Smuzhiyun */
563*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
564*4882a593Smuzhiyun "No handler for RegionType %s(%X) (RegionObj %p)\n",
565*4882a593Smuzhiyun acpi_ut_get_region_name(space_id), space_id,
566*4882a593Smuzhiyun region_obj));
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
569*4882a593Smuzhiyun }
570