xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/evrgnini.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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