1 /******************************************************************************
2  *
3  * Module Name: evregion - ACPI address_space (op_region) handler dispatch
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2004, R. Byron Moore
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 
45 #include <acpi/acpi.h>
46 #include <acpi/acevents.h>
47 #include <acpi/acnamesp.h>
48 #include <acpi/acinterp.h>
49 
50 #define _COMPONENT          ACPI_EVENTS
51 	 ACPI_MODULE_NAME    ("evregion")
52 
53 #define ACPI_NUM_DEFAULT_SPACES     4
54 
55 static u8                   acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
56 			 ACPI_ADR_SPACE_SYSTEM_MEMORY,
57 			 ACPI_ADR_SPACE_SYSTEM_IO,
58 			 ACPI_ADR_SPACE_PCI_CONFIG,
59 			 ACPI_ADR_SPACE_DATA_TABLE};
60 
61 
62 /*******************************************************************************
63  *
64  * FUNCTION:    acpi_ev_init_address_spaces
65  *
66  * PARAMETERS:  None
67  *
68  * RETURN:      Status
69  *
70  * DESCRIPTION: Installs the core subsystem default address space handlers.
71  *
72  ******************************************************************************/
73 
74 acpi_status
acpi_ev_init_address_spaces(void)75 acpi_ev_init_address_spaces (
76 	void) {
77 	acpi_status                     status;
78 	acpi_native_uint                i;
79 
80 
81 	ACPI_FUNCTION_TRACE ("ev_init_address_spaces");
82 
83 
84 	/*
85 	 * All address spaces (PCI Config, EC, SMBus) are scope dependent
86 	 * and registration must occur for a specific device.
87 	 *
88 	 * In the case of the system memory and IO address spaces there is currently
89 	 * no device associated with the address space.  For these we use the root.
90 	 *
91 	 * We install the default PCI config space handler at the root so
92 	 * that this space is immediately available even though the we have
93 	 * not enumerated all the PCI Root Buses yet.  This is to conform
94 	 * to the ACPI specification which states that the PCI config
95 	 * space must be always available -- even though we are nowhere
96 	 * near ready to find the PCI root buses at this point.
97 	 *
98 	 * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
99 	 * has already been installed (via acpi_install_address_space_handler).
100 	 * Similar for AE_SAME_HANDLER.
101 	 */
102 
103 	for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
104 		status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node,
105 				  acpi_gbl_default_address_spaces[i],
106 				  ACPI_DEFAULT_HANDLER, NULL, NULL);
107 		switch (status) {
108 		case AE_OK:
109 		case AE_SAME_HANDLER:
110 		case AE_ALREADY_EXISTS:
111 
112 			/* These exceptions are all OK */
113 
114 			break;
115 
116 		default:
117 
118 			return_ACPI_STATUS (status);
119 		}
120 	}
121 
122 	return_ACPI_STATUS (AE_OK);
123 }
124 
125 
126 /*******************************************************************************
127  *
128  * FUNCTION:    acpi_ev_execute_reg_method
129  *
130  * PARAMETERS:  region_obj          - Object structure
131  *              Function            - On (1) or Off (0)
132  *
133  * RETURN:      Status
134  *
135  * DESCRIPTION: Execute _REG method for a region
136  *
137  ******************************************************************************/
138 
139 acpi_status
acpi_ev_execute_reg_method(union acpi_operand_object * region_obj,u32 function)140 acpi_ev_execute_reg_method (
141 	union acpi_operand_object      *region_obj,
142 	u32                             function)
143 {
144 	union acpi_operand_object      *params[3];
145 	union acpi_operand_object      *region_obj2;
146 	acpi_status                     status;
147 
148 
149 	ACPI_FUNCTION_TRACE ("ev_execute_reg_method");
150 
151 
152 	region_obj2 = acpi_ns_get_secondary_object (region_obj);
153 	if (!region_obj2) {
154 		return_ACPI_STATUS (AE_NOT_EXIST);
155 	}
156 
157 	if (region_obj2->extra.method_REG == NULL) {
158 		return_ACPI_STATUS (AE_OK);
159 	}
160 
161 	/*
162 	 * _REG method has two arguments
163 	 * Arg0:   Integer: Operation region space ID
164 	 *          Same value as region_obj->Region.space_id
165 	 * Arg1:   Integer: connection status
166 	 *          1 for connecting the handler,
167 	 *          0 for disconnecting the handler
168 	 *          Passed as a parameter
169 	 */
170 	params[0] = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
171 	if (!params[0]) {
172 		return_ACPI_STATUS (AE_NO_MEMORY);
173 	}
174 
175 	params[1] = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
176 	if (!params[1]) {
177 		status = AE_NO_MEMORY;
178 		goto cleanup;
179 	}
180 
181 	/* Set up the parameter objects */
182 
183 	params[0]->integer.value = region_obj->region.space_id;
184 	params[1]->integer.value = function;
185 	params[2] = NULL;
186 
187 	/* Execute the method, no return value */
188 
189 	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, region_obj2->extra.method_REG, NULL));
190 	status = acpi_ns_evaluate_by_handle (region_obj2->extra.method_REG, params, NULL);
191 
192 	acpi_ut_remove_reference (params[1]);
193 
194 cleanup:
195 	acpi_ut_remove_reference (params[0]);
196 
197 	return_ACPI_STATUS (status);
198 }
199 
200 
201 /*******************************************************************************
202  *
203  * FUNCTION:    acpi_ev_address_space_dispatch
204  *
205  * PARAMETERS:  region_obj          - Internal region object
206  *              space_id            - ID of the address space (0-255)
207  *              Function            - Read or Write operation
208  *              Address             - Where in the space to read or write
209  *              bit_width           - Field width in bits (8, 16, 32, or 64)
210  *              Value               - Pointer to in or out value
211  *
212  * RETURN:      Status
213  *
214  * DESCRIPTION: Dispatch an address space or operation region access to
215  *              a previously installed handler.
216  *
217  ******************************************************************************/
218 
219 acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object * region_obj,u32 function,acpi_physical_address address,u32 bit_width,void * value)220 acpi_ev_address_space_dispatch (
221 	union acpi_operand_object       *region_obj,
222 	u32                             function,
223 	acpi_physical_address           address,
224 	u32                             bit_width,
225 	void                            *value)
226 {
227 	acpi_status                     status;
228 	acpi_status                     status2;
229 	acpi_adr_space_handler          handler;
230 	acpi_adr_space_setup            region_setup;
231 	union acpi_operand_object       *handler_desc;
232 	union acpi_operand_object       *region_obj2;
233 	void                            *region_context = NULL;
234 
235 
236 	ACPI_FUNCTION_TRACE ("ev_address_space_dispatch");
237 
238 
239 	region_obj2 = acpi_ns_get_secondary_object (region_obj);
240 	if (!region_obj2) {
241 		return_ACPI_STATUS (AE_NOT_EXIST);
242 	}
243 
244 	/* Ensure that there is a handler associated with this region */
245 
246 	handler_desc = region_obj->region.handler;
247 	if (!handler_desc) {
248 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
249 			"No handler for Region [%4.4s] (%p) [%s]\n",
250 			acpi_ut_get_node_name (region_obj->region.node),
251 			region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
252 
253 		return_ACPI_STATUS (AE_NOT_EXIST);
254 	}
255 
256 	/*
257 	 * It may be the case that the region has never been initialized
258 	 * Some types of regions require special init code
259 	 */
260 	if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
261 		/*
262 		 * This region has not been initialized yet, do it
263 		 */
264 		region_setup = handler_desc->address_space.setup;
265 		if (!region_setup) {
266 			/* No initialization routine, exit with error */
267 
268 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n",
269 				region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
270 			return_ACPI_STATUS (AE_NOT_EXIST);
271 		}
272 
273 		/*
274 		 * We must exit the interpreter because the region setup will potentially
275 		 * execute control methods (e.g., _REG method for this region)
276 		 */
277 		acpi_ex_exit_interpreter ();
278 
279 		status = region_setup (region_obj, ACPI_REGION_ACTIVATE,
280 				  handler_desc->address_space.context, &region_context);
281 
282 		/* Re-enter the interpreter */
283 
284 		status2 = acpi_ex_enter_interpreter ();
285 		if (ACPI_FAILURE (status2)) {
286 			return_ACPI_STATUS (status2);
287 		}
288 
289 		/* Check for failure of the Region Setup */
290 
291 		if (ACPI_FAILURE (status)) {
292 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n",
293 				acpi_format_exception (status),
294 				acpi_ut_get_region_name (region_obj->region.space_id)));
295 			return_ACPI_STATUS (status);
296 		}
297 
298 		/*
299 		 * Region initialization may have been completed by region_setup
300 		 */
301 		if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
302 			region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
303 
304 			if (region_obj2->extra.region_context) {
305 				/* The handler for this region was already installed */
306 
307 				ACPI_MEM_FREE (region_context);
308 			}
309 			else {
310 				/*
311 				 * Save the returned context for use in all accesses to
312 				 * this particular region
313 				 */
314 				region_obj2->extra.region_context = region_context;
315 			}
316 		}
317 	}
318 
319 	/* We have everything we need, we can invoke the address space handler */
320 
321 	handler = handler_desc->address_space.handler;
322 
323 	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
324 		"Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
325 		&region_obj->region.handler->address_space, handler,
326 		ACPI_FORMAT_UINT64 (address),
327 		acpi_ut_get_region_name (region_obj->region.space_id)));
328 
329 	if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
330 		/*
331 		 * For handlers other than the default (supplied) handlers, we must
332 		 * exit the interpreter because the handler *might* block -- we don't
333 		 * know what it will do, so we can't hold the lock on the intepreter.
334 		 */
335 		acpi_ex_exit_interpreter();
336 	}
337 
338 	/* Call the handler */
339 
340 	status = handler (function, address, bit_width, value,
341 			 handler_desc->address_space.context,
342 			 region_obj2->extra.region_context);
343 
344 	if (ACPI_FAILURE (status)) {
345 		ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n",
346 			acpi_ut_get_region_name (region_obj->region.space_id),
347 			acpi_format_exception (status)));
348 	}
349 
350 	if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
351 		/*
352 		 * We just returned from a non-default handler, we must re-enter the
353 		 * interpreter
354 		 */
355 		status2 = acpi_ex_enter_interpreter ();
356 		if (ACPI_FAILURE (status2)) {
357 			return_ACPI_STATUS (status2);
358 		}
359 	}
360 
361 	return_ACPI_STATUS (status);
362 }
363 
364 
365 /*******************************************************************************
366  *
367  * FUNCTION:    acpi_ev_detach_region
368  *
369  * PARAMETERS:  region_obj      - Region Object
370  *              acpi_ns_is_locked - Namespace Region Already Locked?
371  *
372  * RETURN:      None
373  *
374  * DESCRIPTION: Break the association between the handler and the region
375  *              this is a two way association.
376  *
377  ******************************************************************************/
378 
379 void
acpi_ev_detach_region(union acpi_operand_object * region_obj,u8 acpi_ns_is_locked)380 acpi_ev_detach_region(
381 	union acpi_operand_object       *region_obj,
382 	u8                              acpi_ns_is_locked)
383 {
384 	union acpi_operand_object       *handler_obj;
385 	union acpi_operand_object       *obj_desc;
386 	union acpi_operand_object       **last_obj_ptr;
387 	acpi_adr_space_setup            region_setup;
388 	void                            **region_context;
389 	union acpi_operand_object       *region_obj2;
390 	acpi_status                     status;
391 
392 
393 	ACPI_FUNCTION_TRACE ("ev_detach_region");
394 
395 
396 	region_obj2 = acpi_ns_get_secondary_object (region_obj);
397 	if (!region_obj2) {
398 		return_VOID;
399 	}
400 	region_context = &region_obj2->extra.region_context;
401 
402 	/* Get the address handler from the region object */
403 
404 	handler_obj = region_obj->region.handler;
405 	if (!handler_obj) {
406 		/* This region has no handler, all done */
407 
408 		return_VOID;
409 	}
410 
411 	/* Find this region in the handler's list */
412 
413 	obj_desc = handler_obj->address_space.region_list;
414 	last_obj_ptr = &handler_obj->address_space.region_list;
415 
416 	while (obj_desc) {
417 		/* Is this the correct Region? */
418 
419 		if (obj_desc == region_obj) {
420 			ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
421 				"Removing Region %p from address handler %p\n",
422 				region_obj, handler_obj));
423 
424 			/* This is it, remove it from the handler's list */
425 
426 			*last_obj_ptr = obj_desc->region.next;
427 			obj_desc->region.next = NULL;           /* Must clear field */
428 
429 			if (acpi_ns_is_locked) {
430 				status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
431 				if (ACPI_FAILURE (status)) {
432 					return_VOID;
433 				}
434 			}
435 
436 			/* Now stop region accesses by executing the _REG method */
437 
438 			status = acpi_ev_execute_reg_method (region_obj, 0);
439 			if (ACPI_FAILURE (status)) {
440 				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n",
441 					acpi_format_exception (status),
442 					acpi_ut_get_region_name (region_obj->region.space_id)));
443 			}
444 
445 			if (acpi_ns_is_locked) {
446 				status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
447 				if (ACPI_FAILURE (status)) {
448 					return_VOID;
449 				}
450 			}
451 
452 			/* Call the setup handler with the deactivate notification */
453 
454 			region_setup = handler_obj->address_space.setup;
455 			status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
456 					  handler_obj->address_space.context, region_context);
457 
458 			/* Init routine may fail, Just ignore errors */
459 
460 			if (ACPI_FAILURE (status)) {
461 				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n",
462 					acpi_format_exception (status),
463 					acpi_ut_get_region_name (region_obj->region.space_id)));
464 			}
465 
466 			region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);
467 
468 			/*
469 			 * Remove handler reference in the region
470 			 *
471 			 * NOTE: this doesn't mean that the region goes away
472 			 * The region is just inaccessible as indicated to
473 			 * the _REG method
474 			 *
475 			 * If the region is on the handler's list
476 			 * this better be the region's handler
477 			 */
478 			region_obj->region.handler = NULL;
479 			acpi_ut_remove_reference (handler_obj);
480 
481 			return_VOID;
482 		}
483 
484 		/* Walk the linked list of handlers */
485 
486 		last_obj_ptr = &obj_desc->region.next;
487 		obj_desc = obj_desc->region.next;
488 	}
489 
490 	/* If we get here, the region was not in the handler's region list */
491 
492 	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
493 		"Cannot remove region %p from address handler %p\n",
494 		region_obj, handler_obj));
495 
496 	return_VOID;
497 }
498 
499 
500 /*******************************************************************************
501  *
502  * FUNCTION:    acpi_ev_attach_region
503  *
504  * PARAMETERS:  handler_obj     - Handler Object
505  *              region_obj      - Region Object
506  *              acpi_ns_is_locked - Namespace Region Already Locked?
507  *
508  * RETURN:      None
509  *
510  * DESCRIPTION: Create the association between the handler and the region
511  *              this is a two way association.
512  *
513  ******************************************************************************/
514 
515 acpi_status
acpi_ev_attach_region(union acpi_operand_object * handler_obj,union acpi_operand_object * region_obj,u8 acpi_ns_is_locked)516 acpi_ev_attach_region (
517 	union acpi_operand_object       *handler_obj,
518 	union acpi_operand_object       *region_obj,
519 	u8                              acpi_ns_is_locked)
520 {
521 
522 	ACPI_FUNCTION_TRACE ("ev_attach_region");
523 
524 
525 	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
526 		"Adding Region [%4.4s] %p to address handler %p [%s]\n",
527 		acpi_ut_get_node_name (region_obj->region.node),
528 		region_obj, handler_obj,
529 		acpi_ut_get_region_name (region_obj->region.space_id)));
530 
531 	/* Link this region to the front of the handler's list */
532 
533 	region_obj->region.next = handler_obj->address_space.region_list;
534 	handler_obj->address_space.region_list = region_obj;
535 
536 	/* Install the region's handler */
537 
538 	if (region_obj->region.handler) {
539 		return_ACPI_STATUS (AE_ALREADY_EXISTS);
540 	}
541 
542 	region_obj->region.handler = handler_obj;
543 	acpi_ut_add_reference (handler_obj);
544 
545 	return_ACPI_STATUS (AE_OK);
546 }
547 
548 
549 /*******************************************************************************
550  *
551  * FUNCTION:    acpi_ev_install_handler
552  *
553  * PARAMETERS:  walk_namespace callback
554  *
555  * DESCRIPTION: This routine installs an address handler into objects that are
556  *              of type Region or Device.
557  *
558  *              If the Object is a Device, and the device has a handler of
559  *              the same type then the search is terminated in that branch.
560  *
561  *              This is because the existing handler is closer in proximity
562  *              to any more regions than the one we are trying to install.
563  *
564  ******************************************************************************/
565 
566 acpi_status
acpi_ev_install_handler(acpi_handle obj_handle,u32 level,void * context,void ** return_value)567 acpi_ev_install_handler (
568 	acpi_handle                     obj_handle,
569 	u32                             level,
570 	void                            *context,
571 	void                            **return_value)
572 {
573 	union acpi_operand_object       *handler_obj;
574 	union acpi_operand_object       *next_handler_obj;
575 	union acpi_operand_object       *obj_desc;
576 	struct acpi_namespace_node      *node;
577 	acpi_status                     status;
578 
579 
580 	ACPI_FUNCTION_NAME ("ev_install_handler");
581 
582 
583 	handler_obj = (union acpi_operand_object   *) context;
584 
585 	/* Parameter validation */
586 
587 	if (!handler_obj) {
588 		return (AE_OK);
589 	}
590 
591 	/* Convert and validate the device handle */
592 
593 	node = acpi_ns_map_handle_to_node (obj_handle);
594 	if (!node) {
595 		return (AE_BAD_PARAMETER);
596 	}
597 
598 	/*
599 	 * We only care about regions.and objects
600 	 * that are allowed to have address space handlers
601 	 */
602 	if ((node->type != ACPI_TYPE_DEVICE) &&
603 		(node->type != ACPI_TYPE_REGION) &&
604 		(node != acpi_gbl_root_node)) {
605 		return (AE_OK);
606 	}
607 
608 	/* Check for an existing internal object */
609 
610 	obj_desc = acpi_ns_get_attached_object (node);
611 	if (!obj_desc) {
612 		/* No object, just exit */
613 
614 		return (AE_OK);
615 	}
616 
617 	/* Devices are handled different than regions */
618 
619 	if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_DEVICE) {
620 		/* Check if this Device already has a handler for this address space */
621 
622 		next_handler_obj = obj_desc->device.handler;
623 		while (next_handler_obj) {
624 			/* Found a handler, is it for the same address space? */
625 
626 			if (next_handler_obj->address_space.space_id == handler_obj->address_space.space_id) {
627 				ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
628 					"Found handler for region [%s] in device %p(%p) handler %p\n",
629 					acpi_ut_get_region_name (handler_obj->address_space.space_id),
630 					obj_desc, next_handler_obj, handler_obj));
631 
632 				/*
633 				 * Since the object we found it on was a device, then it
634 				 * means that someone has already installed a handler for
635 				 * the branch of the namespace from this device on.  Just
636 				 * bail out telling the walk routine to not traverse this
637 				 * branch.  This preserves the scoping rule for handlers.
638 				 */
639 				return (AE_CTRL_DEPTH);
640 			}
641 
642 			/* Walk the linked list of handlers attached to this device */
643 
644 			next_handler_obj = next_handler_obj->address_space.next;
645 		}
646 
647 		/*
648 		 * As long as the device didn't have a handler for this
649 		 * space we don't care about it.  We just ignore it and
650 		 * proceed.
651 		 */
652 		return (AE_OK);
653 	}
654 
655 	/* Object is a Region */
656 
657 	if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
658 		/*
659 		 * This region is for a different address space
660 		 * -- just ignore it
661 		 */
662 		return (AE_OK);
663 	}
664 
665 	/*
666 	 * Now we have a region and it is for the handler's address
667 	 * space type.
668 	 *
669 	 * First disconnect region for any previous handler (if any)
670 	 */
671 	acpi_ev_detach_region (obj_desc, FALSE);
672 
673 	/* Connect the region to the new handler */
674 
675 	status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE);
676 	return (status);
677 }
678 
679 /*******************************************************************************
680  *
681  * FUNCTION:    acpi_ev_reg_run
682  *
683  * PARAMETERS:  walk_namespace callback
684  *
685  * DESCRIPTION: Run _REg method for region objects of the requested space_iD
686  *
687  ******************************************************************************/
688 
689 acpi_status
acpi_ev_reg_run(acpi_handle obj_handle,u32 level,void * context,void ** return_value)690 acpi_ev_reg_run (
691 	acpi_handle                     obj_handle,
692 	u32                             level,
693 	void                            *context,
694 	void                            **return_value)
695 {
696 	union acpi_operand_object       *handler_obj;
697 	union acpi_operand_object       *obj_desc;
698 	struct acpi_namespace_node      *node;
699 	acpi_status                     status;
700 
701 
702 	handler_obj = (union acpi_operand_object   *) context;
703 
704 	/* Parameter validation */
705 
706 	if (!handler_obj) {
707 		return (AE_OK);
708 	}
709 
710 	/* Convert and validate the device handle */
711 
712 	node = acpi_ns_map_handle_to_node (obj_handle);
713 	if (!node) {
714 		return (AE_BAD_PARAMETER);
715 	}
716 
717 	/*
718 	 * We only care about regions.and objects
719 	 * that are allowed to have address space handlers
720 	 */
721 	if ((node->type != ACPI_TYPE_REGION) &&
722 		(node != acpi_gbl_root_node)) {
723 		return (AE_OK);
724 	}
725 
726 	/* Check for an existing internal object */
727 
728 	obj_desc = acpi_ns_get_attached_object (node);
729 	if (!obj_desc) {
730 		/* No object, just exit */
731 
732 		return (AE_OK);
733 	}
734 
735 
736 	/* Object is a Region */
737 
738 	if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
739 		/*
740 		 * This region is for a different address space
741 		 * -- just ignore it
742 		 */
743 		return (AE_OK);
744 	}
745 
746 	status = acpi_ev_execute_reg_method (obj_desc, 1);
747 	return (status);
748 }
749 
750