Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
  4.  *                         Address Spaces.
  5.  *
  6.  *****************************************************************************/
  7.  
  8. /*
  9.  * Copyright (C) 2000 - 2015, Intel Corp.
  10.  * All rights reserved.
  11.  *
  12.  * Redistribution and use in source and binary forms, with or without
  13.  * modification, are permitted provided that the following conditions
  14.  * are met:
  15.  * 1. Redistributions of source code must retain the above copyright
  16.  *    notice, this list of conditions, and the following disclaimer,
  17.  *    without modification.
  18.  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  19.  *    substantially similar to the "NO WARRANTY" disclaimer below
  20.  *    ("Disclaimer") and any redistribution must be conditioned upon
  21.  *    including a substantially similar Disclaimer requirement for further
  22.  *    binary redistribution.
  23.  * 3. Neither the names of the above-listed copyright holders nor the names
  24.  *    of any contributors may be used to endorse or promote products derived
  25.  *    from this software without specific prior written permission.
  26.  *
  27.  * Alternatively, this software may be distributed under the terms of the
  28.  * GNU General Public License ("GPL") version 2 as published by the Free
  29.  * Software Foundation.
  30.  *
  31.  * NO WARRANTY
  32.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  33.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  34.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  35.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  36.  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  38.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  41.  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  42.  * POSSIBILITY OF SUCH DAMAGES.
  43.  */
  44.  
  45. #define EXPORT_ACPI_INTERFACES
  46.  
  47. #include <acpi/acpi.h>
  48. #include "accommon.h"
  49. #include "acnamesp.h"
  50. #include "acevents.h"
  51.  
  52. #define _COMPONENT          ACPI_EVENTS
  53. ACPI_MODULE_NAME("evxfregn")
  54.  
  55. /*******************************************************************************
  56.  *
  57.  * FUNCTION:    acpi_install_address_space_handler
  58.  *
  59.  * PARAMETERS:  device          - Handle for the device
  60.  *              space_id        - The address space ID
  61.  *              handler         - Address of the handler
  62.  *              setup           - Address of the setup function
  63.  *              context         - Value passed to the handler on each access
  64.  *
  65.  * RETURN:      Status
  66.  *
  67.  * DESCRIPTION: Install a handler for all op_regions of a given space_id.
  68.  *
  69.  * NOTE: This function should only be called after acpi_enable_subsystem has
  70.  * been called. This is because any _REG methods associated with the Space ID
  71.  * are executed here, and these methods can only be safely executed after
  72.  * the default handlers have been installed and the hardware has been
  73.  * initialized (via acpi_enable_subsystem.)
  74.  *
  75.  ******************************************************************************/
  76. acpi_status
  77. acpi_install_address_space_handler(acpi_handle device,
  78.                                    acpi_adr_space_type space_id,
  79.                                    acpi_adr_space_handler handler,
  80.                                    acpi_adr_space_setup setup, void *context)
  81. {
  82.         struct acpi_namespace_node *node;
  83.         acpi_status status;
  84.  
  85.         ACPI_FUNCTION_TRACE(acpi_install_address_space_handler);
  86.  
  87.         /* Parameter validation */
  88.  
  89.         if (!device) {
  90.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  91.         }
  92.  
  93.         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  94.         if (ACPI_FAILURE(status)) {
  95.                 return_ACPI_STATUS(status);
  96.         }
  97.  
  98.         /* Convert and validate the device handle */
  99.  
  100.         node = acpi_ns_validate_handle(device);
  101.         if (!node) {
  102.                 status = AE_BAD_PARAMETER;
  103.                 goto unlock_and_exit;
  104.         }
  105.  
  106.         /* Install the handler for all Regions for this Space ID */
  107.  
  108.         status =
  109.             acpi_ev_install_space_handler(node, space_id, handler, setup,
  110.                                           context);
  111.         if (ACPI_FAILURE(status)) {
  112.                 goto unlock_and_exit;
  113.         }
  114.  
  115.         /*
  116.          * For the default space_IDs, (the IDs for which there are default region handlers
  117.          * installed) Only execute the _REG methods if the global initialization _REG
  118.          * methods have already been run (via acpi_initialize_objects). In other words,
  119.          * we will defer the execution of the _REG methods for these space_IDs until
  120.          * execution of acpi_initialize_objects. This is done because we need the handlers
  121.          * for the default spaces (mem/io/pci/table) to be installed before we can run
  122.          * any control methods (or _REG methods). There is known BIOS code that depends
  123.          * on this.
  124.          *
  125.          * For all other space_IDs, we can safely execute the _REG methods immediately.
  126.          * This means that for IDs like embedded_controller, this function should be called
  127.          * only after acpi_enable_subsystem has been called.
  128.          */
  129.         switch (space_id) {
  130.         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
  131.         case ACPI_ADR_SPACE_SYSTEM_IO:
  132.         case ACPI_ADR_SPACE_PCI_CONFIG:
  133.         case ACPI_ADR_SPACE_DATA_TABLE:
  134.  
  135.                 if (!acpi_gbl_reg_methods_executed) {
  136.  
  137.                         /* We will defer execution of the _REG methods for this space */
  138.                         goto unlock_and_exit;
  139.                 }
  140.                 break;
  141.  
  142.         default:
  143.  
  144.                 break;
  145.         }
  146.  
  147.         /* Run all _REG methods for this address space */
  148.  
  149.         status = acpi_ev_execute_reg_methods(node, space_id);
  150.  
  151. unlock_and_exit:
  152.         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  153.         return_ACPI_STATUS(status);
  154. }
  155.  
  156. ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
  157.  
  158. /*******************************************************************************
  159.  *
  160.  * FUNCTION:    acpi_remove_address_space_handler
  161.  *
  162.  * PARAMETERS:  device          - Handle for the device
  163.  *              space_id        - The address space ID
  164.  *              handler         - Address of the handler
  165.  *
  166.  * RETURN:      Status
  167.  *
  168.  * DESCRIPTION: Remove a previously installed handler.
  169.  *
  170.  ******************************************************************************/
  171. acpi_status
  172. acpi_remove_address_space_handler(acpi_handle device,
  173.                                   acpi_adr_space_type space_id,
  174.                                   acpi_adr_space_handler handler)
  175. {
  176.         union acpi_operand_object *obj_desc;
  177.         union acpi_operand_object *handler_obj;
  178.         union acpi_operand_object *region_obj;
  179.         union acpi_operand_object **last_obj_ptr;
  180.         struct acpi_namespace_node *node;
  181.         acpi_status status;
  182.  
  183.         ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler);
  184.  
  185.         /* Parameter validation */
  186.  
  187.         if (!device) {
  188.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  189.         }
  190.  
  191.         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  192.         if (ACPI_FAILURE(status)) {
  193.                 return_ACPI_STATUS(status);
  194.         }
  195.  
  196.         /* Convert and validate the device handle */
  197.  
  198.         node = acpi_ns_validate_handle(device);
  199.         if (!node ||
  200.             ((node->type != ACPI_TYPE_DEVICE) &&
  201.              (node->type != ACPI_TYPE_PROCESSOR) &&
  202.              (node->type != ACPI_TYPE_THERMAL) &&
  203.              (node != acpi_gbl_root_node))) {
  204.                 status = AE_BAD_PARAMETER;
  205.                 goto unlock_and_exit;
  206.         }
  207.  
  208.         /* Make sure the internal object exists */
  209.  
  210.         obj_desc = acpi_ns_get_attached_object(node);
  211.         if (!obj_desc) {
  212.                 status = AE_NOT_EXIST;
  213.                 goto unlock_and_exit;
  214.         }
  215.  
  216.         /* Find the address handler the user requested */
  217.  
  218.         handler_obj = obj_desc->device.handler;
  219.         last_obj_ptr = &obj_desc->device.handler;
  220.         while (handler_obj) {
  221.  
  222.                 /* We have a handler, see if user requested this one */
  223.  
  224.                 if (handler_obj->address_space.space_id == space_id) {
  225.  
  226.                         /* Handler must be the same as the installed handler */
  227.  
  228.                         if (handler_obj->address_space.handler != handler) {
  229.                                 status = AE_BAD_PARAMETER;
  230.                                 goto unlock_and_exit;
  231.                         }
  232.  
  233.                         /* Matched space_id, first dereference this in the Regions */
  234.  
  235.                         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
  236.                                           "Removing address handler %p(%p) for region %s "
  237.                                           "on Device %p(%p)\n",
  238.                                           handler_obj, handler,
  239.                                           acpi_ut_get_region_name(space_id),
  240.                                           node, obj_desc));
  241.  
  242.                         region_obj = handler_obj->address_space.region_list;
  243.  
  244.                         /* Walk the handler's region list */
  245.  
  246.                         while (region_obj) {
  247.                                 /*
  248.                                  * First disassociate the handler from the region.
  249.                                  *
  250.                                  * NOTE: this doesn't mean that the region goes away
  251.                                  * The region is just inaccessible as indicated to
  252.                                  * the _REG method
  253.                                  */
  254.                                 acpi_ev_detach_region(region_obj, TRUE);
  255.  
  256.                                 /*
  257.                                  * Walk the list: Just grab the head because the
  258.                                  * detach_region removed the previous head.
  259.                                  */
  260.                                 region_obj =
  261.                                     handler_obj->address_space.region_list;
  262.  
  263.                         }
  264.  
  265.                         /* Remove this Handler object from the list */
  266.  
  267.                         *last_obj_ptr = handler_obj->address_space.next;
  268.  
  269.                         /* Now we can delete the handler object */
  270.  
  271.                         acpi_ut_remove_reference(handler_obj);
  272.                         goto unlock_and_exit;
  273.                 }
  274.  
  275.                 /* Walk the linked list of handlers */
  276.  
  277.                 last_obj_ptr = &handler_obj->address_space.next;
  278.                 handler_obj = handler_obj->address_space.next;
  279.         }
  280.  
  281.         /* The handler does not exist */
  282.  
  283.         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
  284.                           "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
  285.                           handler, acpi_ut_get_region_name(space_id), space_id,
  286.                           node, obj_desc));
  287.  
  288.         status = AE_NOT_EXIST;
  289.  
  290. unlock_and_exit:
  291.         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  292.         return_ACPI_STATUS(status);
  293. }
  294.  
  295. ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)
  296.