Subversion Repositories Kolibri OS

Rev

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

  1. /******************************************************************************
  2.  *
  3.  * Module Name: evxface - External interfaces for ACPI events
  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. #define EXPORT_ACPI_INTERFACES
  45.  
  46. #include <acpi/acpi.h>
  47. #include "accommon.h"
  48. #include "acnamesp.h"
  49. #include "acevents.h"
  50. #include "acinterp.h"
  51.  
  52. #define _COMPONENT          ACPI_EVENTS
  53. ACPI_MODULE_NAME("evxface")
  54. #if (!ACPI_REDUCED_HARDWARE)
  55. /* Local prototypes */
  56. static acpi_status
  57. acpi_ev_install_gpe_handler(acpi_handle gpe_device,
  58.                             u32 gpe_number,
  59.                             u32 type,
  60.                             u8 is_raw_handler,
  61.                             acpi_gpe_handler address, void *context);
  62.  
  63. #endif
  64.  
  65.  
  66. /*******************************************************************************
  67.  *
  68.  * FUNCTION:    acpi_install_notify_handler
  69.  *
  70.  * PARAMETERS:  device          - The device for which notifies will be handled
  71.  *              handler_type    - The type of handler:
  72.  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
  73.  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
  74.  *                                  ACPI_ALL_NOTIFY:    Both System and Device
  75.  *              handler         - Address of the handler
  76.  *              context         - Value passed to the handler on each GPE
  77.  *
  78.  * RETURN:      Status
  79.  *
  80.  * DESCRIPTION: Install a handler for notifications on an ACPI Device,
  81.  *              thermal_zone, or Processor object.
  82.  *
  83.  * NOTES:       The Root namespace object may have only one handler for each
  84.  *              type of notify (System/Device). Device/Thermal/Processor objects
  85.  *              may have one device notify handler, and multiple system notify
  86.  *              handlers.
  87.  *
  88.  ******************************************************************************/
  89.  
  90. acpi_status
  91. acpi_install_notify_handler(acpi_handle device,
  92.                             u32 handler_type,
  93.                             acpi_notify_handler handler, void *context)
  94. {
  95.         struct acpi_namespace_node *node =
  96.             ACPI_CAST_PTR(struct acpi_namespace_node, device);
  97.         union acpi_operand_object *obj_desc;
  98.         union acpi_operand_object *handler_obj;
  99.         acpi_status status;
  100.         u32 i;
  101.  
  102.         ACPI_FUNCTION_TRACE(acpi_install_notify_handler);
  103.  
  104.         /* Parameter validation */
  105.  
  106.         if ((!device) || (!handler) || (!handler_type) ||
  107.             (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
  108.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  109.         }
  110.  
  111.         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  112.         if (ACPI_FAILURE(status)) {
  113.                 return_ACPI_STATUS(status);
  114.         }
  115.  
  116.         /*
  117.          * Root Object:
  118.          * Registering a notify handler on the root object indicates that the
  119.          * caller wishes to receive notifications for all objects. Note that
  120.          * only one global handler can be registered per notify type.
  121.          * Ensure that a handler is not already installed.
  122.          */
  123.         if (device == ACPI_ROOT_OBJECT) {
  124.                 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
  125.                         if (handler_type & (i + 1)) {
  126.                                 if (acpi_gbl_global_notify[i].handler) {
  127.                                         status = AE_ALREADY_EXISTS;
  128.                                         goto unlock_and_exit;
  129.                                 }
  130.  
  131.                                 acpi_gbl_global_notify[i].handler = handler;
  132.                                 acpi_gbl_global_notify[i].context = context;
  133.                         }
  134.                 }
  135.  
  136.                 goto unlock_and_exit;   /* Global notify handler installed, all done */
  137.         }
  138.  
  139.         /*
  140.          * All Other Objects:
  141.          * Caller will only receive notifications specific to the target
  142.          * object. Note that only certain object types are allowed to
  143.          * receive notifications.
  144.          */
  145.  
  146.         /* Are Notifies allowed on this object? */
  147.  
  148.         if (!acpi_ev_is_notify_object(node)) {
  149.                 status = AE_TYPE;
  150.                 goto unlock_and_exit;
  151.         }
  152.  
  153.         /* Check for an existing internal object, might not exist */
  154.  
  155.         obj_desc = acpi_ns_get_attached_object(node);
  156.         if (!obj_desc) {
  157.  
  158.                 /* Create a new object */
  159.  
  160.                 obj_desc = acpi_ut_create_internal_object(node->type);
  161.                 if (!obj_desc) {
  162.                         status = AE_NO_MEMORY;
  163.                         goto unlock_and_exit;
  164.                 }
  165.  
  166.                 /* Attach new object to the Node, remove local reference */
  167.  
  168.                 status = acpi_ns_attach_object(device, obj_desc, node->type);
  169.                 acpi_ut_remove_reference(obj_desc);
  170.                 if (ACPI_FAILURE(status)) {
  171.                         goto unlock_and_exit;
  172.                 }
  173.         }
  174.  
  175.         /* Ensure that the handler is not already installed in the lists */
  176.  
  177.         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
  178.                 if (handler_type & (i + 1)) {
  179.                         handler_obj = obj_desc->common_notify.notify_list[i];
  180.                         while (handler_obj) {
  181.                                 if (handler_obj->notify.handler == handler) {
  182.                                         status = AE_ALREADY_EXISTS;
  183.                                         goto unlock_and_exit;
  184.                                 }
  185.  
  186.                                 handler_obj = handler_obj->notify.next[i];
  187.                         }
  188.                 }
  189.         }
  190.  
  191.         /* Create and populate a new notify handler object */
  192.  
  193.         handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
  194.         if (!handler_obj) {
  195.                 status = AE_NO_MEMORY;
  196.                 goto unlock_and_exit;
  197.         }
  198.  
  199.         handler_obj->notify.node = node;
  200.         handler_obj->notify.handler_type = handler_type;
  201.         handler_obj->notify.handler = handler;
  202.         handler_obj->notify.context = context;
  203.  
  204.         /* Install the handler at the list head(s) */
  205.  
  206.         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
  207.                 if (handler_type & (i + 1)) {
  208.                         handler_obj->notify.next[i] =
  209.                             obj_desc->common_notify.notify_list[i];
  210.  
  211.                         obj_desc->common_notify.notify_list[i] = handler_obj;
  212.                 }
  213.         }
  214.  
  215.         /* Add an extra reference if handler was installed in both lists */
  216.  
  217.         if (handler_type == ACPI_ALL_NOTIFY) {
  218.                 acpi_ut_add_reference(handler_obj);
  219.         }
  220.  
  221. unlock_and_exit:
  222.         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  223.         return_ACPI_STATUS(status);
  224. }
  225.  
  226. ACPI_EXPORT_SYMBOL(acpi_install_notify_handler)
  227.  
  228. /*******************************************************************************
  229.  *
  230.  * FUNCTION:    acpi_remove_notify_handler
  231.  *
  232.  * PARAMETERS:  device          - The device for which the handler is installed
  233.  *              handler_type    - The type of handler:
  234.  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
  235.  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
  236.  *                                  ACPI_ALL_NOTIFY:    Both System and Device
  237.  *              handler         - Address of the handler
  238.  *
  239.  * RETURN:      Status
  240.  *
  241.  * DESCRIPTION: Remove a handler for notifies on an ACPI device
  242.  *
  243.  ******************************************************************************/
  244. acpi_status
  245. acpi_remove_notify_handler(acpi_handle device,
  246.                            u32 handler_type, acpi_notify_handler handler)
  247. {
  248.         struct acpi_namespace_node *node =
  249.             ACPI_CAST_PTR(struct acpi_namespace_node, device);
  250.         union acpi_operand_object *obj_desc;
  251.         union acpi_operand_object *handler_obj;
  252.         union acpi_operand_object *previous_handler_obj;
  253.         acpi_status status = AE_OK;
  254.         u32 i;
  255.  
  256.         ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);
  257.  
  258.         /* Parameter validation */
  259.  
  260.         if ((!device) || (!handler) || (!handler_type) ||
  261.             (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
  262.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  263.         }
  264.  
  265.         /* Root Object. Global handlers are removed here */
  266.  
  267.         if (device == ACPI_ROOT_OBJECT) {
  268.                 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
  269.                         if (handler_type & (i + 1)) {
  270.                                 status =
  271.                                     acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  272.                                 if (ACPI_FAILURE(status)) {
  273.                                         return_ACPI_STATUS(status);
  274.                                 }
  275.  
  276.                                 if (!acpi_gbl_global_notify[i].handler ||
  277.                                     (acpi_gbl_global_notify[i].handler !=
  278.                                      handler)) {
  279.                                         status = AE_NOT_EXIST;
  280.                                         goto unlock_and_exit;
  281.                                 }
  282.  
  283.                                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  284.                                                   "Removing global notify handler\n"));
  285.  
  286.                                 acpi_gbl_global_notify[i].handler = NULL;
  287.                                 acpi_gbl_global_notify[i].context = NULL;
  288.  
  289.                                 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  290.  
  291.                                 /* Make sure all deferred notify tasks are completed */
  292.  
  293.                                 acpi_os_wait_events_complete();
  294.                         }
  295.                 }
  296.  
  297.                 return_ACPI_STATUS(AE_OK);
  298.         }
  299.  
  300.         /* All other objects: Are Notifies allowed on this object? */
  301.  
  302.         if (!acpi_ev_is_notify_object(node)) {
  303.                 return_ACPI_STATUS(AE_TYPE);
  304.         }
  305.  
  306.         /* Must have an existing internal object */
  307.  
  308.         obj_desc = acpi_ns_get_attached_object(node);
  309.         if (!obj_desc) {
  310.                 return_ACPI_STATUS(AE_NOT_EXIST);
  311.         }
  312.  
  313.         /* Internal object exists. Find the handler and remove it */
  314.  
  315.         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
  316.                 if (handler_type & (i + 1)) {
  317.                         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  318.                         if (ACPI_FAILURE(status)) {
  319.                                 return_ACPI_STATUS(status);
  320.                         }
  321.  
  322.                         handler_obj = obj_desc->common_notify.notify_list[i];
  323.                         previous_handler_obj = NULL;
  324.  
  325.                         /* Attempt to find the handler in the handler list */
  326.  
  327.                         while (handler_obj &&
  328.                                (handler_obj->notify.handler != handler)) {
  329.                                 previous_handler_obj = handler_obj;
  330.                                 handler_obj = handler_obj->notify.next[i];
  331.                         }
  332.  
  333.                         if (!handler_obj) {
  334.                                 status = AE_NOT_EXIST;
  335.                                 goto unlock_and_exit;
  336.                         }
  337.  
  338.                         /* Remove the handler object from the list */
  339.  
  340.                         if (previous_handler_obj) {     /* Handler is not at the list head */
  341.                                 previous_handler_obj->notify.next[i] =
  342.                                     handler_obj->notify.next[i];
  343.                         } else {        /* Handler is at the list head */
  344.  
  345.                                 obj_desc->common_notify.notify_list[i] =
  346.                                     handler_obj->notify.next[i];
  347.                         }
  348.  
  349.                         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  350.  
  351.                         /* Make sure all deferred notify tasks are completed */
  352.  
  353.                         acpi_os_wait_events_complete();
  354.                         acpi_ut_remove_reference(handler_obj);
  355.                 }
  356.         }
  357.  
  358.         return_ACPI_STATUS(status);
  359.  
  360. unlock_and_exit:
  361.         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  362.         return_ACPI_STATUS(status);
  363. }
  364.  
  365. ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler)
  366.  
  367. /*******************************************************************************
  368.  *
  369.  * FUNCTION:    acpi_install_exception_handler
  370.  *
  371.  * PARAMETERS:  handler         - Pointer to the handler function for the
  372.  *                                event
  373.  *
  374.  * RETURN:      Status
  375.  *
  376.  * DESCRIPTION: Saves the pointer to the handler function
  377.  *
  378.  ******************************************************************************/
  379. #ifdef ACPI_FUTURE_USAGE
  380. acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
  381. {
  382.         acpi_status status;
  383.  
  384.         ACPI_FUNCTION_TRACE(acpi_install_exception_handler);
  385.  
  386.         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  387.         if (ACPI_FAILURE(status)) {
  388.                 return_ACPI_STATUS(status);
  389.         }
  390.  
  391.         /* Don't allow two handlers. */
  392.  
  393.         if (acpi_gbl_exception_handler) {
  394.                 status = AE_ALREADY_EXISTS;
  395.                 goto cleanup;
  396.         }
  397.  
  398.         /* Install the handler */
  399.  
  400.         acpi_gbl_exception_handler = handler;
  401.  
  402. cleanup:
  403.         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  404.         return_ACPI_STATUS(status);
  405. }
  406.  
  407. ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
  408. #endif
  409.  
  410. #if (!ACPI_REDUCED_HARDWARE)
  411. /*******************************************************************************
  412.  *
  413.  * FUNCTION:    acpi_install_sci_handler
  414.  *
  415.  * PARAMETERS:  address             - Address of the handler
  416.  *              context             - Value passed to the handler on each SCI
  417.  *
  418.  * RETURN:      Status
  419.  *
  420.  * DESCRIPTION: Install a handler for a System Control Interrupt.
  421.  *
  422.  ******************************************************************************/
  423. acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)
  424. {
  425.         struct acpi_sci_handler_info *new_sci_handler;
  426.         struct acpi_sci_handler_info *sci_handler;
  427.         acpi_cpu_flags flags;
  428.         acpi_status status;
  429.  
  430.         ACPI_FUNCTION_TRACE(acpi_install_sci_handler);
  431.  
  432.         if (!address) {
  433.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  434.         }
  435.  
  436.         /* Allocate and init a handler object */
  437.  
  438.         new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info));
  439.         if (!new_sci_handler) {
  440.                 return_ACPI_STATUS(AE_NO_MEMORY);
  441.         }
  442.  
  443.         new_sci_handler->address = address;
  444.         new_sci_handler->context = context;
  445.  
  446.         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  447.         if (ACPI_FAILURE(status)) {
  448.                 goto exit;
  449.         }
  450.  
  451.         /* Lock list during installation */
  452.  
  453.         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
  454.         sci_handler = acpi_gbl_sci_handler_list;
  455.  
  456.         /* Ensure handler does not already exist */
  457.  
  458.         while (sci_handler) {
  459.                 if (address == sci_handler->address) {
  460.                         status = AE_ALREADY_EXISTS;
  461.                         goto unlock_and_exit;
  462.                 }
  463.  
  464.                 sci_handler = sci_handler->next;
  465.         }
  466.  
  467.         /* Install the new handler into the global list (at head) */
  468.  
  469.         new_sci_handler->next = acpi_gbl_sci_handler_list;
  470.         acpi_gbl_sci_handler_list = new_sci_handler;
  471.  
  472. unlock_and_exit:
  473.  
  474.         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  475.         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  476.  
  477. exit:
  478.         if (ACPI_FAILURE(status)) {
  479.                 ACPI_FREE(new_sci_handler);
  480.         }
  481.         return_ACPI_STATUS(status);
  482. }
  483.  
  484. ACPI_EXPORT_SYMBOL(acpi_install_sci_handler)
  485.  
  486. /*******************************************************************************
  487.  *
  488.  * FUNCTION:    acpi_remove_sci_handler
  489.  *
  490.  * PARAMETERS:  address             - Address of the handler
  491.  *
  492.  * RETURN:      Status
  493.  *
  494.  * DESCRIPTION: Remove a handler for a System Control Interrupt.
  495.  *
  496.  ******************************************************************************/
  497. acpi_status acpi_remove_sci_handler(acpi_sci_handler address)
  498. {
  499.         struct acpi_sci_handler_info *prev_sci_handler;
  500.         struct acpi_sci_handler_info *next_sci_handler;
  501.         acpi_cpu_flags flags;
  502.         acpi_status status;
  503.  
  504.         ACPI_FUNCTION_TRACE(acpi_remove_sci_handler);
  505.  
  506.         if (!address) {
  507.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  508.         }
  509.  
  510.         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  511.         if (ACPI_FAILURE(status)) {
  512.                 return_ACPI_STATUS(status);
  513.         }
  514.  
  515.         /* Remove the SCI handler with lock */
  516.  
  517.         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
  518.  
  519.         prev_sci_handler = NULL;
  520.         next_sci_handler = acpi_gbl_sci_handler_list;
  521.         while (next_sci_handler) {
  522.                 if (next_sci_handler->address == address) {
  523.  
  524.                         /* Unlink and free the SCI handler info block */
  525.  
  526.                         if (prev_sci_handler) {
  527.                                 prev_sci_handler->next = next_sci_handler->next;
  528.                         } else {
  529.                                 acpi_gbl_sci_handler_list =
  530.                                     next_sci_handler->next;
  531.                         }
  532.  
  533.                         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  534.                         ACPI_FREE(next_sci_handler);
  535.                         goto unlock_and_exit;
  536.                 }
  537.  
  538.                 prev_sci_handler = next_sci_handler;
  539.                 next_sci_handler = next_sci_handler->next;
  540.         }
  541.  
  542.         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  543.         status = AE_NOT_EXIST;
  544.  
  545. unlock_and_exit:
  546.         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  547.         return_ACPI_STATUS(status);
  548. }
  549.  
  550. ACPI_EXPORT_SYMBOL(acpi_remove_sci_handler)
  551.  
  552. /*******************************************************************************
  553.  *
  554.  * FUNCTION:    acpi_install_global_event_handler
  555.  *
  556.  * PARAMETERS:  handler         - Pointer to the global event handler function
  557.  *              context         - Value passed to the handler on each event
  558.  *
  559.  * RETURN:      Status
  560.  *
  561.  * DESCRIPTION: Saves the pointer to the handler function. The global handler
  562.  *              is invoked upon each incoming GPE and Fixed Event. It is
  563.  *              invoked at interrupt level at the time of the event dispatch.
  564.  *              Can be used to update event counters, etc.
  565.  *
  566.  ******************************************************************************/
  567. acpi_status
  568. acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
  569. {
  570.         acpi_status status;
  571.  
  572.         ACPI_FUNCTION_TRACE(acpi_install_global_event_handler);
  573.  
  574.         /* Parameter validation */
  575.  
  576.         if (!handler) {
  577.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  578.         }
  579.  
  580.         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  581.         if (ACPI_FAILURE(status)) {
  582.                 return_ACPI_STATUS(status);
  583.         }
  584.  
  585.         /* Don't allow two handlers. */
  586.  
  587.         if (acpi_gbl_global_event_handler) {
  588.                 status = AE_ALREADY_EXISTS;
  589.                 goto cleanup;
  590.         }
  591.  
  592.         acpi_gbl_global_event_handler = handler;
  593.         acpi_gbl_global_event_handler_context = context;
  594.  
  595. cleanup:
  596.         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  597.         return_ACPI_STATUS(status);
  598. }
  599.  
  600. ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler)
  601.  
  602. /*******************************************************************************
  603.  *
  604.  * FUNCTION:    acpi_install_fixed_event_handler
  605.  *
  606.  * PARAMETERS:  event           - Event type to enable.
  607.  *              handler         - Pointer to the handler function for the
  608.  *                                event
  609.  *              context         - Value passed to the handler on each GPE
  610.  *
  611.  * RETURN:      Status
  612.  *
  613.  * DESCRIPTION: Saves the pointer to the handler function and then enables the
  614.  *              event.
  615.  *
  616.  ******************************************************************************/
  617. acpi_status
  618. acpi_install_fixed_event_handler(u32 event,
  619.                                  acpi_event_handler handler, void *context)
  620. {
  621.         acpi_status status;
  622.  
  623.         ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);
  624.  
  625.         /* Parameter validation */
  626.  
  627.         if (event > ACPI_EVENT_MAX) {
  628.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  629.         }
  630.  
  631.         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  632.         if (ACPI_FAILURE(status)) {
  633.                 return_ACPI_STATUS(status);
  634.         }
  635.  
  636.         /* Do not allow multiple handlers */
  637.  
  638.         if (acpi_gbl_fixed_event_handlers[event].handler) {
  639.                 status = AE_ALREADY_EXISTS;
  640.                 goto cleanup;
  641.         }
  642.  
  643.         /* Install the handler before enabling the event */
  644.  
  645.         acpi_gbl_fixed_event_handlers[event].handler = handler;
  646.         acpi_gbl_fixed_event_handlers[event].context = context;
  647.  
  648.         status = acpi_clear_event(event);
  649.         if (ACPI_SUCCESS(status))
  650.                 status = acpi_enable_event(event, 0);
  651.         if (ACPI_FAILURE(status)) {
  652.                 ACPI_WARNING((AE_INFO,
  653.                               "Could not enable fixed event - %s (%u)",
  654.                               acpi_ut_get_event_name(event), event));
  655.  
  656.                 /* Remove the handler */
  657.  
  658.                 acpi_gbl_fixed_event_handlers[event].handler = NULL;
  659.                 acpi_gbl_fixed_event_handlers[event].context = NULL;
  660.         } else {
  661.                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  662.                                   "Enabled fixed event %s (%X), Handler=%p\n",
  663.                                   acpi_ut_get_event_name(event), event,
  664.                                   handler));
  665.         }
  666.  
  667. cleanup:
  668.         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  669.         return_ACPI_STATUS(status);
  670. }
  671.  
  672. ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)
  673.  
  674. /*******************************************************************************
  675.  *
  676.  * FUNCTION:    acpi_remove_fixed_event_handler
  677.  *
  678.  * PARAMETERS:  event           - Event type to disable.
  679.  *              handler         - Address of the handler
  680.  *
  681.  * RETURN:      Status
  682.  *
  683.  * DESCRIPTION: Disables the event and unregisters the event handler.
  684.  *
  685.  ******************************************************************************/
  686. acpi_status
  687. acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
  688. {
  689.         acpi_status status = AE_OK;
  690.  
  691.         ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);
  692.  
  693.         /* Parameter validation */
  694.  
  695.         if (event > ACPI_EVENT_MAX) {
  696.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  697.         }
  698.  
  699.         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  700.         if (ACPI_FAILURE(status)) {
  701.                 return_ACPI_STATUS(status);
  702.         }
  703.  
  704.         /* Disable the event before removing the handler */
  705.  
  706.         status = acpi_disable_event(event, 0);
  707.  
  708.         /* Always Remove the handler */
  709.  
  710.         acpi_gbl_fixed_event_handlers[event].handler = NULL;
  711.         acpi_gbl_fixed_event_handlers[event].context = NULL;
  712.  
  713.         if (ACPI_FAILURE(status)) {
  714.                 ACPI_WARNING((AE_INFO,
  715.                               "Could not disable fixed event - %s (%u)",
  716.                               acpi_ut_get_event_name(event), event));
  717.         } else {
  718.                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  719.                                   "Disabled fixed event - %s (%X)\n",
  720.                                   acpi_ut_get_event_name(event), event));
  721.         }
  722.  
  723.         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  724.         return_ACPI_STATUS(status);
  725. }
  726.  
  727. ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)
  728.  
  729. /*******************************************************************************
  730.  *
  731.  * FUNCTION:    acpi_ev_install_gpe_handler
  732.  *
  733.  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
  734.  *                                defined GPEs)
  735.  *              gpe_number      - The GPE number within the GPE block
  736.  *              type            - Whether this GPE should be treated as an
  737.  *                                edge- or level-triggered interrupt.
  738.  *              is_raw_handler  - Whether this GPE should be handled using
  739.  *                                the special GPE handler mode.
  740.  *              address         - Address of the handler
  741.  *              context         - Value passed to the handler on each GPE
  742.  *
  743.  * RETURN:      Status
  744.  *
  745.  * DESCRIPTION: Internal function to install a handler for a General Purpose
  746.  *              Event.
  747.  *
  748.  ******************************************************************************/
  749. static acpi_status
  750. acpi_ev_install_gpe_handler(acpi_handle gpe_device,
  751.                             u32 gpe_number,
  752.                             u32 type,
  753.                             u8 is_raw_handler,
  754.                             acpi_gpe_handler address, void *context)
  755. {
  756.         struct acpi_gpe_event_info *gpe_event_info;
  757.         struct acpi_gpe_handler_info *handler;
  758.         acpi_status status;
  759.         acpi_cpu_flags flags;
  760.  
  761.         ACPI_FUNCTION_TRACE(ev_install_gpe_handler);
  762.  
  763.         /* Parameter validation */
  764.  
  765.         if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) {
  766.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  767.         }
  768.  
  769.         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  770.         if (ACPI_FAILURE(status)) {
  771.                 return_ACPI_STATUS(status);
  772.         }
  773.  
  774.         /* Allocate and init handler object (before lock) */
  775.  
  776.         handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info));
  777.         if (!handler) {
  778.                 status = AE_NO_MEMORY;
  779.                 goto unlock_and_exit;
  780.         }
  781.  
  782.         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
  783.  
  784.         /* Ensure that we have a valid GPE number */
  785.  
  786.         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
  787.         if (!gpe_event_info) {
  788.                 status = AE_BAD_PARAMETER;
  789.                 goto free_and_exit;
  790.         }
  791.  
  792.         /* Make sure that there isn't a handler there already */
  793.  
  794.         if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
  795.              ACPI_GPE_DISPATCH_HANDLER) ||
  796.             (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
  797.              ACPI_GPE_DISPATCH_RAW_HANDLER)) {
  798.                 status = AE_ALREADY_EXISTS;
  799.                 goto free_and_exit;
  800.         }
  801.  
  802.         handler->address = address;
  803.         handler->context = context;
  804.         handler->method_node = gpe_event_info->dispatch.method_node;
  805.         handler->original_flags = (u8)(gpe_event_info->flags &
  806.                                        (ACPI_GPE_XRUPT_TYPE_MASK |
  807.                                         ACPI_GPE_DISPATCH_MASK));
  808.  
  809.         /*
  810.          * If the GPE is associated with a method, it may have been enabled
  811.          * automatically during initialization, in which case it has to be
  812.          * disabled now to avoid spurious execution of the handler.
  813.          */
  814.         if (((ACPI_GPE_DISPATCH_TYPE(handler->original_flags) ==
  815.               ACPI_GPE_DISPATCH_METHOD) ||
  816.              (ACPI_GPE_DISPATCH_TYPE(handler->original_flags) ==
  817.               ACPI_GPE_DISPATCH_NOTIFY)) && gpe_event_info->runtime_count) {
  818.                 handler->originally_enabled = TRUE;
  819.                 (void)acpi_ev_remove_gpe_reference(gpe_event_info);
  820.  
  821.                 /* Sanity check of original type against new type */
  822.  
  823.                 if (type !=
  824.                     (u32)(gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK)) {
  825.                         ACPI_WARNING((AE_INFO,
  826.                                       "GPE type mismatch (level/edge)"));
  827.                 }
  828.         }
  829.  
  830.         /* Install the handler */
  831.  
  832.         gpe_event_info->dispatch.handler = handler;
  833.  
  834.         /* Setup up dispatch flags to indicate handler (vs. method/notify) */
  835.  
  836.         gpe_event_info->flags &=
  837.             ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
  838.         gpe_event_info->flags |=
  839.             (u8)(type |
  840.                  (is_raw_handler ? ACPI_GPE_DISPATCH_RAW_HANDLER :
  841.                   ACPI_GPE_DISPATCH_HANDLER));
  842.  
  843.         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  844.  
  845. unlock_and_exit:
  846.         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  847.         return_ACPI_STATUS(status);
  848.  
  849. free_and_exit:
  850.         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  851.         ACPI_FREE(handler);
  852.         goto unlock_and_exit;
  853. }
  854.  
  855. /*******************************************************************************
  856.  *
  857.  * FUNCTION:    acpi_install_gpe_handler
  858.  *
  859.  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
  860.  *                                defined GPEs)
  861.  *              gpe_number      - The GPE number within the GPE block
  862.  *              type            - Whether this GPE should be treated as an
  863.  *                                edge- or level-triggered interrupt.
  864.  *              address         - Address of the handler
  865.  *              context         - Value passed to the handler on each GPE
  866.  *
  867.  * RETURN:      Status
  868.  *
  869.  * DESCRIPTION: Install a handler for a General Purpose Event.
  870.  *
  871.  ******************************************************************************/
  872.  
  873. acpi_status
  874. acpi_install_gpe_handler(acpi_handle gpe_device,
  875.                          u32 gpe_number,
  876.                          u32 type, acpi_gpe_handler address, void *context)
  877. {
  878.         acpi_status status;
  879.  
  880.         ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);
  881.  
  882.         status =
  883.             acpi_ev_install_gpe_handler(gpe_device, gpe_number, type, FALSE,
  884.                                         address, context);
  885.  
  886.         return_ACPI_STATUS(status);
  887. }
  888.  
  889. ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)
  890.  
  891. /*******************************************************************************
  892.  *
  893.  * FUNCTION:    acpi_install_gpe_raw_handler
  894.  *
  895.  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
  896.  *                                defined GPEs)
  897.  *              gpe_number      - The GPE number within the GPE block
  898.  *              type            - Whether this GPE should be treated as an
  899.  *                                edge- or level-triggered interrupt.
  900.  *              address         - Address of the handler
  901.  *              context         - Value passed to the handler on each GPE
  902.  *
  903.  * RETURN:      Status
  904.  *
  905.  * DESCRIPTION: Install a handler for a General Purpose Event.
  906.  *
  907.  ******************************************************************************/
  908. acpi_status
  909. acpi_install_gpe_raw_handler(acpi_handle gpe_device,
  910.                              u32 gpe_number,
  911.                              u32 type, acpi_gpe_handler address, void *context)
  912. {
  913.         acpi_status status;
  914.  
  915.         ACPI_FUNCTION_TRACE(acpi_install_gpe_raw_handler);
  916.  
  917.         status = acpi_ev_install_gpe_handler(gpe_device, gpe_number, type, TRUE,
  918.                                              address, context);
  919.  
  920.         return_ACPI_STATUS(status);
  921. }
  922.  
  923. ACPI_EXPORT_SYMBOL(acpi_install_gpe_raw_handler)
  924.  
  925. /*******************************************************************************
  926.  *
  927.  * FUNCTION:    acpi_remove_gpe_handler
  928.  *
  929.  * PARAMETERS:  gpe_device      - Namespace node for the GPE (NULL for FADT
  930.  *                                defined GPEs)
  931.  *              gpe_number      - The event to remove a handler
  932.  *              address         - Address of the handler
  933.  *
  934.  * RETURN:      Status
  935.  *
  936.  * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
  937.  *
  938.  ******************************************************************************/
  939. acpi_status
  940. acpi_remove_gpe_handler(acpi_handle gpe_device,
  941.                         u32 gpe_number, acpi_gpe_handler address)
  942. {
  943.         struct acpi_gpe_event_info *gpe_event_info;
  944.         struct acpi_gpe_handler_info *handler;
  945.         acpi_status status;
  946.         acpi_cpu_flags flags;
  947.  
  948.         ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler);
  949.  
  950.         /* Parameter validation */
  951.  
  952.         if (!address) {
  953.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  954.         }
  955.  
  956.         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  957.         if (ACPI_FAILURE(status)) {
  958.                 return_ACPI_STATUS(status);
  959.         }
  960.  
  961.         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
  962.  
  963.         /* Ensure that we have a valid GPE number */
  964.  
  965.         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
  966.         if (!gpe_event_info) {
  967.                 status = AE_BAD_PARAMETER;
  968.                 goto unlock_and_exit;
  969.         }
  970.  
  971.         /* Make sure that a handler is indeed installed */
  972.  
  973.         if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
  974.              ACPI_GPE_DISPATCH_HANDLER) &&
  975.             (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
  976.              ACPI_GPE_DISPATCH_RAW_HANDLER)) {
  977.                 status = AE_NOT_EXIST;
  978.                 goto unlock_and_exit;
  979.         }
  980.  
  981.         /* Make sure that the installed handler is the same */
  982.  
  983.         if (gpe_event_info->dispatch.handler->address != address) {
  984.                 status = AE_BAD_PARAMETER;
  985.                 goto unlock_and_exit;
  986.         }
  987.  
  988.         /* Remove the handler */
  989.  
  990.         handler = gpe_event_info->dispatch.handler;
  991.         gpe_event_info->dispatch.handler = NULL;
  992.  
  993.         /* Restore Method node (if any), set dispatch flags */
  994.  
  995.         gpe_event_info->dispatch.method_node = handler->method_node;
  996.         gpe_event_info->flags &=
  997.             ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
  998.         gpe_event_info->flags |= handler->original_flags;
  999.  
  1000.         /*
  1001.          * If the GPE was previously associated with a method and it was
  1002.          * enabled, it should be enabled at this point to restore the
  1003.          * post-initialization configuration.
  1004.          */
  1005.         if (((ACPI_GPE_DISPATCH_TYPE(handler->original_flags) ==
  1006.               ACPI_GPE_DISPATCH_METHOD) ||
  1007.              (ACPI_GPE_DISPATCH_TYPE(handler->original_flags) ==
  1008.               ACPI_GPE_DISPATCH_NOTIFY)) && handler->originally_enabled) {
  1009.                 (void)acpi_ev_add_gpe_reference(gpe_event_info);
  1010.         }
  1011.  
  1012.         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  1013.         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  1014.  
  1015.         /* Make sure all deferred GPE tasks are completed */
  1016.  
  1017.         acpi_os_wait_events_complete();
  1018.  
  1019.         /* Now we can free the handler object */
  1020.  
  1021.         ACPI_FREE(handler);
  1022.         return_ACPI_STATUS(status);
  1023.  
  1024. unlock_and_exit:
  1025.         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  1026.  
  1027.         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  1028.         return_ACPI_STATUS(status);
  1029. }
  1030.  
  1031. ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
  1032.  
  1033. /*******************************************************************************
  1034.  *
  1035.  * FUNCTION:    acpi_acquire_global_lock
  1036.  *
  1037.  * PARAMETERS:  timeout         - How long the caller is willing to wait
  1038.  *              handle          - Where the handle to the lock is returned
  1039.  *                                (if acquired)
  1040.  *
  1041.  * RETURN:      Status
  1042.  *
  1043.  * DESCRIPTION: Acquire the ACPI Global Lock
  1044.  *
  1045.  * Note: Allows callers with the same thread ID to acquire the global lock
  1046.  * multiple times. In other words, externally, the behavior of the global lock
  1047.  * is identical to an AML mutex. On the first acquire, a new handle is
  1048.  * returned. On any subsequent calls to acquire by the same thread, the same
  1049.  * handle is returned.
  1050.  *
  1051.  ******************************************************************************/
  1052. acpi_status acpi_acquire_global_lock(u16 timeout, u32 *handle)
  1053. {
  1054.         acpi_status status;
  1055.  
  1056.         if (!handle) {
  1057.                 return (AE_BAD_PARAMETER);
  1058.         }
  1059.  
  1060.         /* Must lock interpreter to prevent race conditions */
  1061.  
  1062.         acpi_ex_enter_interpreter();
  1063.  
  1064.         status = acpi_ex_acquire_mutex_object(timeout,
  1065.                                               acpi_gbl_global_lock_mutex,
  1066.                                               acpi_os_get_thread_id());
  1067.  
  1068.         if (ACPI_SUCCESS(status)) {
  1069.  
  1070.                 /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */
  1071.  
  1072.                 *handle = acpi_gbl_global_lock_handle;
  1073.         }
  1074.  
  1075.         acpi_ex_exit_interpreter();
  1076.         return (status);
  1077. }
  1078.  
  1079. ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock)
  1080.  
  1081. /*******************************************************************************
  1082.  *
  1083.  * FUNCTION:    acpi_release_global_lock
  1084.  *
  1085.  * PARAMETERS:  handle      - Returned from acpi_acquire_global_lock
  1086.  *
  1087.  * RETURN:      Status
  1088.  *
  1089.  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
  1090.  *
  1091.  ******************************************************************************/
  1092. acpi_status acpi_release_global_lock(u32 handle)
  1093. {
  1094.         acpi_status status;
  1095.  
  1096.         if (!handle || (handle != acpi_gbl_global_lock_handle)) {
  1097.                 return (AE_NOT_ACQUIRED);
  1098.         }
  1099.  
  1100.         status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
  1101.         return (status);
  1102. }
  1103.  
  1104. ACPI_EXPORT_SYMBOL(acpi_release_global_lock)
  1105. #endif                          /* !ACPI_REDUCED_HARDWARE */
  1106.