Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Module Name: evregion - Operation Region support
  4.  *
  5.  *****************************************************************************/
  6.  
  7. /*
  8.  * Copyright (C) 2000 - 2015, Intel Corp.
  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. #include <acpi/acpi.h>
  45. #include "accommon.h"
  46. #include "acevents.h"
  47. #include "acnamesp.h"
  48. #include "acinterp.h"
  49.  
  50. #define _COMPONENT          ACPI_EVENTS
  51. ACPI_MODULE_NAME("evregion")
  52.  
  53. extern u8 acpi_gbl_default_address_spaces[];
  54.  
  55. /* Local prototypes */
  56.  
  57. static void
  58. acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node);
  59.  
  60. static acpi_status
  61. acpi_ev_reg_run(acpi_handle obj_handle,
  62.                 u32 level, void *context, void **return_value);
  63.  
  64. /*******************************************************************************
  65.  *
  66.  * FUNCTION:    acpi_ev_initialize_op_regions
  67.  *
  68.  * PARAMETERS:  None
  69.  *
  70.  * RETURN:      Status
  71.  *
  72.  * DESCRIPTION: Execute _REG methods for all Operation Regions that have
  73.  *              an installed default region handler.
  74.  *
  75.  ******************************************************************************/
  76.  
  77. acpi_status acpi_ev_initialize_op_regions(void)
  78. {
  79.         acpi_status status;
  80.         u32 i;
  81.  
  82.         ACPI_FUNCTION_TRACE(ev_initialize_op_regions);
  83.  
  84.         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  85.         if (ACPI_FAILURE(status)) {
  86.                 return_ACPI_STATUS(status);
  87.         }
  88.  
  89.         /* Run the _REG methods for op_regions in each default address space */
  90.  
  91.         for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
  92.                 /*
  93.                  * Make sure the installed handler is the DEFAULT handler. If not the
  94.                  * default, the _REG methods will have already been run (when the
  95.                  * handler was installed)
  96.                  */
  97.                 if (acpi_ev_has_default_handler(acpi_gbl_root_node,
  98.                                                 acpi_gbl_default_address_spaces
  99.                                                 [i])) {
  100.                         status =
  101.                             acpi_ev_execute_reg_methods(acpi_gbl_root_node,
  102.                                                         acpi_gbl_default_address_spaces
  103.                                                         [i]);
  104.                 }
  105.         }
  106.  
  107.         acpi_gbl_reg_methods_executed = TRUE;
  108.  
  109.         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  110.         return_ACPI_STATUS(status);
  111. }
  112.  
  113. /*******************************************************************************
  114.  *
  115.  * FUNCTION:    acpi_ev_address_space_dispatch
  116.  *
  117.  * PARAMETERS:  region_obj          - Internal region object
  118.  *              field_obj           - Corresponding field. Can be NULL.
  119.  *              function            - Read or Write operation
  120.  *              region_offset       - Where in the region to read or write
  121.  *              bit_width           - Field width in bits (8, 16, 32, or 64)
  122.  *              value               - Pointer to in or out value, must be
  123.  *                                    a full 64-bit integer
  124.  *
  125.  * RETURN:      Status
  126.  *
  127.  * DESCRIPTION: Dispatch an address space or operation region access to
  128.  *              a previously installed handler.
  129.  *
  130.  ******************************************************************************/
  131.  
  132. acpi_status
  133. acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
  134.                                union acpi_operand_object *field_obj,
  135.                                u32 function,
  136.                                u32 region_offset, u32 bit_width, u64 *value)
  137. {
  138.         acpi_status status;
  139.         acpi_adr_space_handler handler;
  140.         acpi_adr_space_setup region_setup;
  141.         union acpi_operand_object *handler_desc;
  142.         union acpi_operand_object *region_obj2;
  143.         void *region_context = NULL;
  144.         struct acpi_connection_info *context;
  145.         acpi_physical_address address;
  146.  
  147.         ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
  148.  
  149.         region_obj2 = acpi_ns_get_secondary_object(region_obj);
  150.         if (!region_obj2) {
  151.                 return_ACPI_STATUS(AE_NOT_EXIST);
  152.         }
  153.  
  154.         /* Ensure that there is a handler associated with this region */
  155.  
  156.         handler_desc = region_obj->region.handler;
  157.         if (!handler_desc) {
  158.                 ACPI_ERROR((AE_INFO,
  159.                             "No handler for Region [%4.4s] (%p) [%s]",
  160.                             acpi_ut_get_node_name(region_obj->region.node),
  161.                             region_obj,
  162.                             acpi_ut_get_region_name(region_obj->region.
  163.                                                     space_id)));
  164.  
  165.                 return_ACPI_STATUS(AE_NOT_EXIST);
  166.         }
  167.  
  168.         context = handler_desc->address_space.context;
  169.  
  170.         /*
  171.          * It may be the case that the region has never been initialized.
  172.          * Some types of regions require special init code
  173.          */
  174.         if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
  175.  
  176.                 /* This region has not been initialized yet, do it */
  177.  
  178.                 region_setup = handler_desc->address_space.setup;
  179.                 if (!region_setup) {
  180.  
  181.                         /* No initialization routine, exit with error */
  182.  
  183.                         ACPI_ERROR((AE_INFO,
  184.                                     "No init routine for region(%p) [%s]",
  185.                                     region_obj,
  186.                                     acpi_ut_get_region_name(region_obj->region.
  187.                                                             space_id)));
  188.                         return_ACPI_STATUS(AE_NOT_EXIST);
  189.                 }
  190.  
  191.                 /*
  192.                  * We must exit the interpreter because the region setup will
  193.                  * potentially execute control methods (for example, the _REG method
  194.                  * for this region)
  195.                  */
  196.                 acpi_ex_exit_interpreter();
  197.  
  198.                 status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
  199.                                       context, &region_context);
  200.  
  201.                 /* Re-enter the interpreter */
  202.  
  203.                 acpi_ex_enter_interpreter();
  204.  
  205.                 /* Check for failure of the Region Setup */
  206.  
  207.                 if (ACPI_FAILURE(status)) {
  208.                         ACPI_EXCEPTION((AE_INFO, status,
  209.                                         "During region initialization: [%s]",
  210.                                         acpi_ut_get_region_name(region_obj->
  211.                                                                 region.
  212.                                                                 space_id)));
  213.                         return_ACPI_STATUS(status);
  214.                 }
  215.  
  216.                 /* Region initialization may have been completed by region_setup */
  217.  
  218.                 if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
  219.                         region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
  220.  
  221.                         /*
  222.                          * Save the returned context for use in all accesses to
  223.                          * the handler for this particular region
  224.                          */
  225.                         if (!(region_obj2->extra.region_context)) {
  226.                                 region_obj2->extra.region_context =
  227.                                     region_context;
  228.                         }
  229.                 }
  230.         }
  231.  
  232.         /* We have everything we need, we can invoke the address space handler */
  233.  
  234.         handler = handler_desc->address_space.handler;
  235.         address = (region_obj->region.address + region_offset);
  236.  
  237.         /*
  238.          * Special handling for generic_serial_bus and general_purpose_io:
  239.          * There are three extra parameters that must be passed to the
  240.          * handler via the context:
  241.          *   1) Connection buffer, a resource template from Connection() op
  242.          *   2) Length of the above buffer
  243.          *   3) Actual access length from the access_as() op
  244.          *
  245.          * In addition, for general_purpose_io, the Address and bit_width fields
  246.          * are defined as follows:
  247.          *   1) Address is the pin number index of the field (bit offset from
  248.          *      the previous Connection)
  249.          *   2) bit_width is the actual bit length of the field (number of pins)
  250.          */
  251.         if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
  252.             context && field_obj) {
  253.  
  254.                 /* Get the Connection (resource_template) buffer */
  255.  
  256.                 context->connection = field_obj->field.resource_buffer;
  257.                 context->length = field_obj->field.resource_length;
  258.                 context->access_length = field_obj->field.access_length;
  259.         }
  260.         if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
  261.             context && field_obj) {
  262.  
  263.                 /* Get the Connection (resource_template) buffer */
  264.  
  265.                 context->connection = field_obj->field.resource_buffer;
  266.                 context->length = field_obj->field.resource_length;
  267.                 context->access_length = field_obj->field.access_length;
  268.                 address = field_obj->field.pin_number_index;
  269.                 bit_width = field_obj->field.bit_length;
  270.         }
  271.  
  272.         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
  273.                           "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
  274.                           &region_obj->region.handler->address_space, handler,
  275.                           ACPI_FORMAT_UINT64(address),
  276.                           acpi_ut_get_region_name(region_obj->region.
  277.                                                   space_id)));
  278.  
  279.         if (!(handler_desc->address_space.handler_flags &
  280.               ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
  281.                 /*
  282.                  * For handlers other than the default (supplied) handlers, we must
  283.                  * exit the interpreter because the handler *might* block -- we don't
  284.                  * know what it will do, so we can't hold the lock on the intepreter.
  285.                  */
  286.                 acpi_ex_exit_interpreter();
  287.         }
  288.  
  289.         /* Call the handler */
  290.  
  291.         status = handler(function, address, bit_width, value, context,
  292.                          region_obj2->extra.region_context);
  293.  
  294.         if (ACPI_FAILURE(status)) {
  295.                 ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
  296.                                 acpi_ut_get_region_name(region_obj->region.
  297.                                                         space_id)));
  298.         }
  299.  
  300.         if (!(handler_desc->address_space.handler_flags &
  301.               ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
  302.                 /*
  303.                  * We just returned from a non-default handler, we must re-enter the
  304.                  * interpreter
  305.                  */
  306.                 acpi_ex_enter_interpreter();
  307.         }
  308.  
  309.         return_ACPI_STATUS(status);
  310. }
  311.  
  312. /*******************************************************************************
  313.  *
  314.  * FUNCTION:    acpi_ev_detach_region
  315.  *
  316.  * PARAMETERS:  region_obj          - Region Object
  317.  *              acpi_ns_is_locked   - Namespace Region Already Locked?
  318.  *
  319.  * RETURN:      None
  320.  *
  321.  * DESCRIPTION: Break the association between the handler and the region
  322.  *              this is a two way association.
  323.  *
  324.  ******************************************************************************/
  325.  
  326. void
  327. acpi_ev_detach_region(union acpi_operand_object *region_obj,
  328.                       u8 acpi_ns_is_locked)
  329. {
  330.         union acpi_operand_object *handler_obj;
  331.         union acpi_operand_object *obj_desc;
  332.         union acpi_operand_object *start_desc;
  333.         union acpi_operand_object **last_obj_ptr;
  334.         acpi_adr_space_setup region_setup;
  335.         void **region_context;
  336.         union acpi_operand_object *region_obj2;
  337.         acpi_status status;
  338.  
  339.         ACPI_FUNCTION_TRACE(ev_detach_region);
  340.  
  341.         region_obj2 = acpi_ns_get_secondary_object(region_obj);
  342.         if (!region_obj2) {
  343.                 return_VOID;
  344.         }
  345.         region_context = &region_obj2->extra.region_context;
  346.  
  347.         /* Get the address handler from the region object */
  348.  
  349.         handler_obj = region_obj->region.handler;
  350.         if (!handler_obj) {
  351.  
  352.                 /* This region has no handler, all done */
  353.  
  354.                 return_VOID;
  355.         }
  356.  
  357.         /* Find this region in the handler's list */
  358.  
  359.         obj_desc = handler_obj->address_space.region_list;
  360.         start_desc = obj_desc;
  361.         last_obj_ptr = &handler_obj->address_space.region_list;
  362.  
  363.         while (obj_desc) {
  364.  
  365.                 /* Is this the correct Region? */
  366.  
  367.                 if (obj_desc == region_obj) {
  368.                         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
  369.                                           "Removing Region %p from address handler %p\n",
  370.                                           region_obj, handler_obj));
  371.  
  372.                         /* This is it, remove it from the handler's list */
  373.  
  374.                         *last_obj_ptr = obj_desc->region.next;
  375.                         obj_desc->region.next = NULL;   /* Must clear field */
  376.  
  377.                         if (acpi_ns_is_locked) {
  378.                                 status =
  379.                                     acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  380.                                 if (ACPI_FAILURE(status)) {
  381.                                         return_VOID;
  382.                                 }
  383.                         }
  384.  
  385.                         /* Now stop region accesses by executing the _REG method */
  386.  
  387.                         status =
  388.                             acpi_ev_execute_reg_method(region_obj,
  389.                                                        ACPI_REG_DISCONNECT);
  390.                         if (ACPI_FAILURE(status)) {
  391.                                 ACPI_EXCEPTION((AE_INFO, status,
  392.                                                 "from region _REG, [%s]",
  393.                                                 acpi_ut_get_region_name
  394.                                                 (region_obj->region.space_id)));
  395.                         }
  396.  
  397.                         if (acpi_ns_is_locked) {
  398.                                 status =
  399.                                     acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  400.                                 if (ACPI_FAILURE(status)) {
  401.                                         return_VOID;
  402.                                 }
  403.                         }
  404.  
  405.                         /*
  406.                          * If the region has been activated, call the setup handler with
  407.                          * the deactivate notification
  408.                          */
  409.                         if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
  410.                                 region_setup = handler_obj->address_space.setup;
  411.                                 status =
  412.                                     region_setup(region_obj,
  413.                                                  ACPI_REGION_DEACTIVATE,
  414.                                                  handler_obj->address_space.
  415.                                                  context, region_context);
  416.  
  417.                                 /*
  418.                                  * region_context should have been released by the deactivate
  419.                                  * operation. We don't need access to it anymore here.
  420.                                  */
  421.                                 if (region_context) {
  422.                                         *region_context = NULL;
  423.                                 }
  424.  
  425.                                 /* Init routine may fail, Just ignore errors */
  426.  
  427.                                 if (ACPI_FAILURE(status)) {
  428.                                         ACPI_EXCEPTION((AE_INFO, status,
  429.                                                         "from region handler - deactivate, [%s]",
  430.                                                         acpi_ut_get_region_name
  431.                                                         (region_obj->region.
  432.                                                          space_id)));
  433.                                 }
  434.  
  435.                                 region_obj->region.flags &=
  436.                                     ~(AOPOBJ_SETUP_COMPLETE);
  437.                         }
  438.  
  439.                         /*
  440.                          * Remove handler reference in the region
  441.                          *
  442.                          * NOTE: this doesn't mean that the region goes away, the region
  443.                          * is just inaccessible as indicated to the _REG method
  444.                          *
  445.                          * If the region is on the handler's list, this must be the
  446.                          * region's handler
  447.                          */
  448.                         region_obj->region.handler = NULL;
  449.                         acpi_ut_remove_reference(handler_obj);
  450.  
  451.                         return_VOID;
  452.                 }
  453.  
  454.                 /* Walk the linked list of handlers */
  455.  
  456.                 last_obj_ptr = &obj_desc->region.next;
  457.                 obj_desc = obj_desc->region.next;
  458.  
  459.                 /* Prevent infinite loop if list is corrupted */
  460.  
  461.                 if (obj_desc == start_desc) {
  462.                         ACPI_ERROR((AE_INFO,
  463.                                     "Circular handler list in region object %p",
  464.                                     region_obj));
  465.                         return_VOID;
  466.                 }
  467.         }
  468.  
  469.         /* If we get here, the region was not in the handler's region list */
  470.  
  471.         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
  472.                           "Cannot remove region %p from address handler %p\n",
  473.                           region_obj, handler_obj));
  474.  
  475.         return_VOID;
  476. }
  477.  
  478. /*******************************************************************************
  479.  *
  480.  * FUNCTION:    acpi_ev_attach_region
  481.  *
  482.  * PARAMETERS:  handler_obj         - Handler Object
  483.  *              region_obj          - Region Object
  484.  *              acpi_ns_is_locked   - Namespace Region Already Locked?
  485.  *
  486.  * RETURN:      None
  487.  *
  488.  * DESCRIPTION: Create the association between the handler and the region
  489.  *              this is a two way association.
  490.  *
  491.  ******************************************************************************/
  492.  
  493. acpi_status
  494. acpi_ev_attach_region(union acpi_operand_object *handler_obj,
  495.                       union acpi_operand_object *region_obj,
  496.                       u8 acpi_ns_is_locked)
  497. {
  498.  
  499.         ACPI_FUNCTION_TRACE(ev_attach_region);
  500.  
  501.         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
  502.                           "Adding Region [%4.4s] %p to address handler %p [%s]\n",
  503.                           acpi_ut_get_node_name(region_obj->region.node),
  504.                           region_obj, handler_obj,
  505.                           acpi_ut_get_region_name(region_obj->region.
  506.                                                   space_id)));
  507.  
  508.         /* Link this region to the front of the handler's list */
  509.  
  510.         region_obj->region.next = handler_obj->address_space.region_list;
  511.         handler_obj->address_space.region_list = region_obj;
  512.  
  513.         /* Install the region's handler */
  514.  
  515.         if (region_obj->region.handler) {
  516.                 return_ACPI_STATUS(AE_ALREADY_EXISTS);
  517.         }
  518.  
  519.         region_obj->region.handler = handler_obj;
  520.         acpi_ut_add_reference(handler_obj);
  521.  
  522.         return_ACPI_STATUS(AE_OK);
  523. }
  524.  
  525. /*******************************************************************************
  526.  *
  527.  * FUNCTION:    acpi_ev_execute_reg_method
  528.  *
  529.  * PARAMETERS:  region_obj          - Region object
  530.  *              function            - Passed to _REG: On (1) or Off (0)
  531.  *
  532.  * RETURN:      Status
  533.  *
  534.  * DESCRIPTION: Execute _REG method for a region
  535.  *
  536.  ******************************************************************************/
  537.  
  538. acpi_status
  539. acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
  540. {
  541.         struct acpi_evaluate_info *info;
  542.         union acpi_operand_object *args[3];
  543.         union acpi_operand_object *region_obj2;
  544.         acpi_status status;
  545.  
  546.         ACPI_FUNCTION_TRACE(ev_execute_reg_method);
  547.  
  548.         region_obj2 = acpi_ns_get_secondary_object(region_obj);
  549.         if (!region_obj2) {
  550.                 return_ACPI_STATUS(AE_NOT_EXIST);
  551.         }
  552.  
  553.         if (region_obj2->extra.method_REG == NULL) {
  554.                 return_ACPI_STATUS(AE_OK);
  555.         }
  556.  
  557.         /* Allocate and initialize the evaluation information block */
  558.  
  559.         info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
  560.         if (!info) {
  561.                 return_ACPI_STATUS(AE_NO_MEMORY);
  562.         }
  563.  
  564.         info->prefix_node = region_obj2->extra.method_REG;
  565.         info->relative_pathname = NULL;
  566.         info->parameters = args;
  567.         info->flags = ACPI_IGNORE_RETURN_VALUE;
  568.  
  569.         /*
  570.          * The _REG method has two arguments:
  571.          *
  572.          * arg0 - Integer:
  573.          *  Operation region space ID Same value as region_obj->Region.space_id
  574.          *
  575.          * arg1 - Integer:
  576.          *  connection status 1 for connecting the handler, 0 for disconnecting
  577.          *  the handler (Passed as a parameter)
  578.          */
  579.         args[0] =
  580.             acpi_ut_create_integer_object((u64)region_obj->region.space_id);
  581.         if (!args[0]) {
  582.                 status = AE_NO_MEMORY;
  583.                 goto cleanup1;
  584.         }
  585.  
  586.         args[1] = acpi_ut_create_integer_object((u64)function);
  587.         if (!args[1]) {
  588.                 status = AE_NO_MEMORY;
  589.                 goto cleanup2;
  590.         }
  591.  
  592.         args[2] = NULL;         /* Terminate list */
  593.  
  594.         /* Execute the method, no return value */
  595.  
  596.         ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
  597.                         (ACPI_TYPE_METHOD, info->prefix_node, NULL));
  598.  
  599.         status = acpi_ns_evaluate(info);
  600.         acpi_ut_remove_reference(args[1]);
  601.  
  602. cleanup2:
  603.         acpi_ut_remove_reference(args[0]);
  604.  
  605. cleanup1:
  606.         ACPI_FREE(info);
  607.         return_ACPI_STATUS(status);
  608. }
  609.  
  610. /*******************************************************************************
  611.  *
  612.  * FUNCTION:    acpi_ev_execute_reg_methods
  613.  *
  614.  * PARAMETERS:  node            - Namespace node for the device
  615.  *              space_id        - The address space ID
  616.  *
  617.  * RETURN:      Status
  618.  *
  619.  * DESCRIPTION: Run all _REG methods for the input Space ID;
  620.  *              Note: assumes namespace is locked, or system init time.
  621.  *
  622.  ******************************************************************************/
  623.  
  624. acpi_status
  625. acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
  626.                             acpi_adr_space_type space_id)
  627. {
  628.         acpi_status status;
  629.         struct acpi_reg_walk_info info;
  630.  
  631.         ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
  632.  
  633.         info.space_id = space_id;
  634.         info.reg_run_count = 0;
  635.  
  636.         ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
  637.                               "    Running _REG methods for SpaceId %s\n",
  638.                               acpi_ut_get_region_name(info.space_id)));
  639.  
  640.         /*
  641.          * Run all _REG methods for all Operation Regions for this space ID. This
  642.          * is a separate walk in order to handle any interdependencies between
  643.          * regions and _REG methods. (i.e. handlers must be installed for all
  644.          * regions of this Space ID before we can run any _REG methods)
  645.          */
  646.         status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
  647.                                         ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
  648.                                         NULL, &info, NULL);
  649.  
  650.         /* Special case for EC: handle "orphan" _REG methods with no region */
  651.  
  652.         if (space_id == ACPI_ADR_SPACE_EC) {
  653.                 acpi_ev_orphan_ec_reg_method(node);
  654.         }
  655.  
  656.         ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
  657.                               "    Executed %u _REG methods for SpaceId %s\n",
  658.                               info.reg_run_count,
  659.                               acpi_ut_get_region_name(info.space_id)));
  660.  
  661.         return_ACPI_STATUS(status);
  662. }
  663.  
  664. /*******************************************************************************
  665.  *
  666.  * FUNCTION:    acpi_ev_reg_run
  667.  *
  668.  * PARAMETERS:  walk_namespace callback
  669.  *
  670.  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
  671.  *
  672.  ******************************************************************************/
  673.  
  674. static acpi_status
  675. acpi_ev_reg_run(acpi_handle obj_handle,
  676.                 u32 level, void *context, void **return_value)
  677. {
  678.         union acpi_operand_object *obj_desc;
  679.         struct acpi_namespace_node *node;
  680.         acpi_status status;
  681.         struct acpi_reg_walk_info *info;
  682.  
  683.         info = ACPI_CAST_PTR(struct acpi_reg_walk_info, context);
  684.  
  685.         /* Convert and validate the device handle */
  686.  
  687.         node = acpi_ns_validate_handle(obj_handle);
  688.         if (!node) {
  689.                 return (AE_BAD_PARAMETER);
  690.         }
  691.  
  692.         /*
  693.          * We only care about regions.and objects that are allowed to have address
  694.          * space handlers
  695.          */
  696.         if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
  697.                 return (AE_OK);
  698.         }
  699.  
  700.         /* Check for an existing internal object */
  701.  
  702.         obj_desc = acpi_ns_get_attached_object(node);
  703.         if (!obj_desc) {
  704.  
  705.                 /* No object, just exit */
  706.  
  707.                 return (AE_OK);
  708.         }
  709.  
  710.         /* Object is a Region */
  711.  
  712.         if (obj_desc->region.space_id != info->space_id) {
  713.  
  714.                 /* This region is for a different address space, just ignore it */
  715.  
  716.                 return (AE_OK);
  717.         }
  718.  
  719.         info->reg_run_count++;
  720.         status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT);
  721.         return (status);
  722. }
  723.  
  724. /*******************************************************************************
  725.  *
  726.  * FUNCTION:    acpi_ev_orphan_ec_reg_method
  727.  *
  728.  * PARAMETERS:  ec_device_node      - Namespace node for an EC device
  729.  *
  730.  * RETURN:      None
  731.  *
  732.  * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC
  733.  *              device. This is a _REG method that has no corresponding region
  734.  *              within the EC device scope. The orphan _REG method appears to
  735.  *              have been enabled by the description of the ECDT in the ACPI
  736.  *              specification: "The availability of the region space can be
  737.  *              detected by providing a _REG method object underneath the
  738.  *              Embedded Controller device."
  739.  *
  740.  *              To quickly access the EC device, we use the ec_device_node used
  741.  *              during EC handler installation. Otherwise, we would need to
  742.  *              perform a time consuming namespace walk, executing _HID
  743.  *              methods to find the EC device.
  744.  *
  745.  *  MUTEX:      Assumes the namespace is locked
  746.  *
  747.  ******************************************************************************/
  748.  
  749. static void
  750. acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node)
  751. {
  752.         acpi_handle reg_method;
  753.         struct acpi_namespace_node *next_node;
  754.         acpi_status status;
  755.         struct acpi_object_list args;
  756.         union acpi_object objects[2];
  757.  
  758.         ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method);
  759.  
  760.         if (!ec_device_node) {
  761.                 return_VOID;
  762.         }
  763.  
  764.         /* Namespace is currently locked, must release */
  765.  
  766.         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  767.  
  768.         /* Get a handle to a _REG method immediately under the EC device */
  769.  
  770.         status = acpi_get_handle(ec_device_node, METHOD_NAME__REG, &reg_method);
  771.         if (ACPI_FAILURE(status)) {
  772.                 goto exit;      /* There is no _REG method present */
  773.         }
  774.  
  775.         /*
  776.          * Execute the _REG method only if there is no Operation Region in
  777.          * this scope with the Embedded Controller space ID. Otherwise, it
  778.          * will already have been executed. Note, this allows for Regions
  779.          * with other space IDs to be present; but the code below will then
  780.          * execute the _REG method with the embedded_control space_ID argument.
  781.          */
  782.         next_node = acpi_ns_get_next_node(ec_device_node, NULL);
  783.         while (next_node) {
  784.                 if ((next_node->type == ACPI_TYPE_REGION) &&
  785.                     (next_node->object) &&
  786.                     (next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) {
  787.                         goto exit;      /* Do not execute the _REG */
  788.                 }
  789.  
  790.                 next_node = acpi_ns_get_next_node(ec_device_node, next_node);
  791.         }
  792.  
  793.         /* Evaluate the _REG(embedded_control,Connect) method */
  794.  
  795.         args.count = 2;
  796.         args.pointer = objects;
  797.         objects[0].type = ACPI_TYPE_INTEGER;
  798.         objects[0].integer.value = ACPI_ADR_SPACE_EC;
  799.         objects[1].type = ACPI_TYPE_INTEGER;
  800.         objects[1].integer.value = ACPI_REG_CONNECT;
  801.  
  802.         status = acpi_evaluate_object(reg_method, NULL, &args, NULL);
  803.  
  804. exit:
  805.         /* We ignore all errors from above, don't care */
  806.  
  807.         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  808.         return_VOID;
  809. }
  810.