Subversion Repositories Kolibri OS

Rev

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

  1. /******************************************************************************
  2.  *
  3.  * Module Name: evmisc - Miscellaneous event manager support functions
  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.  
  49. #define _COMPONENT          ACPI_EVENTS
  50. ACPI_MODULE_NAME("evmisc")
  51.  
  52. /* Local prototypes */
  53. static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
  54.  
  55. /*******************************************************************************
  56.  *
  57.  * FUNCTION:    acpi_ev_is_notify_object
  58.  *
  59.  * PARAMETERS:  node            - Node to check
  60.  *
  61.  * RETURN:      TRUE if notifies allowed on this object
  62.  *
  63.  * DESCRIPTION: Check type of node for a object that supports notifies.
  64.  *
  65.  *              TBD: This could be replaced by a flag bit in the node.
  66.  *
  67.  ******************************************************************************/
  68.  
  69. u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
  70. {
  71.         switch (node->type) {
  72.         case ACPI_TYPE_DEVICE:
  73.         case ACPI_TYPE_PROCESSOR:
  74.         case ACPI_TYPE_THERMAL:
  75.                 /*
  76.                  * These are the ONLY objects that can receive ACPI notifications
  77.                  */
  78.                 return (TRUE);
  79.  
  80.         default:
  81.  
  82.                 return (FALSE);
  83.         }
  84. }
  85.  
  86. /*******************************************************************************
  87.  *
  88.  * FUNCTION:    acpi_ev_queue_notify_request
  89.  *
  90.  * PARAMETERS:  node            - NS node for the notified object
  91.  *              notify_value    - Value from the Notify() request
  92.  *
  93.  * RETURN:      Status
  94.  *
  95.  * DESCRIPTION: Dispatch a device notification event to a previously
  96.  *              installed handler.
  97.  *
  98.  ******************************************************************************/
  99.  
  100. acpi_status
  101. acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
  102.                              u32 notify_value)
  103. {
  104.         union acpi_operand_object *obj_desc;
  105.         union acpi_operand_object *handler_list_head = NULL;
  106.         union acpi_generic_state *info;
  107.         u8 handler_list_id = 0;
  108.         acpi_status status = AE_OK;
  109.  
  110.         ACPI_FUNCTION_NAME(ev_queue_notify_request);
  111.  
  112.         /* Are Notifies allowed on this object? */
  113.  
  114.         if (!acpi_ev_is_notify_object(node)) {
  115.                 return (AE_TYPE);
  116.         }
  117.  
  118.         /* Get the correct notify list type (System or Device) */
  119.  
  120.         if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
  121.                 handler_list_id = ACPI_SYSTEM_HANDLER_LIST;
  122.         } else {
  123.                 handler_list_id = ACPI_DEVICE_HANDLER_LIST;
  124.         }
  125.  
  126.         /* Get the notify object attached to the namespace Node */
  127.  
  128.         obj_desc = acpi_ns_get_attached_object(node);
  129.         if (obj_desc) {
  130.  
  131.                 /* We have an attached object, Get the correct handler list */
  132.  
  133.                 handler_list_head =
  134.                     obj_desc->common_notify.notify_list[handler_list_id];
  135.         }
  136.  
  137.         /*
  138.          * If there is no notify handler (Global or Local)
  139.          * for this object, just ignore the notify
  140.          */
  141.         if (!acpi_gbl_global_notify[handler_list_id].handler
  142.             && !handler_list_head) {
  143.                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  144.                                   "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n",
  145.                                   acpi_ut_get_node_name(node), notify_value,
  146.                                   node));
  147.  
  148.                 return (AE_OK);
  149.         }
  150.  
  151.         /* Setup notify info and schedule the notify dispatcher */
  152.  
  153.         info = acpi_ut_create_generic_state();
  154.         if (!info) {
  155.                 return (AE_NO_MEMORY);
  156.         }
  157.  
  158.         info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY;
  159.  
  160.         info->notify.node = node;
  161.         info->notify.value = (u16)notify_value;
  162.         info->notify.handler_list_id = handler_list_id;
  163.         info->notify.handler_list_head = handler_list_head;
  164.         info->notify.global = &acpi_gbl_global_notify[handler_list_id];
  165.  
  166.         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  167.                           "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n",
  168.                           acpi_ut_get_node_name(node),
  169.                           acpi_ut_get_type_name(node->type), notify_value,
  170.                           acpi_ut_get_notify_name(notify_value, ACPI_TYPE_ANY),
  171.                           node));
  172.  
  173.         status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
  174.                                  info);
  175.         if (ACPI_FAILURE(status)) {
  176.                 acpi_ut_delete_generic_state(info);
  177.         }
  178.  
  179.         return (status);
  180. }
  181.  
  182. /*******************************************************************************
  183.  *
  184.  * FUNCTION:    acpi_ev_notify_dispatch
  185.  *
  186.  * PARAMETERS:  context         - To be passed to the notify handler
  187.  *
  188.  * RETURN:      None.
  189.  *
  190.  * DESCRIPTION: Dispatch a device notification event to a previously
  191.  *              installed handler.
  192.  *
  193.  ******************************************************************************/
  194.  
  195. static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
  196. {
  197.         union acpi_generic_state *info = (union acpi_generic_state *)context;
  198.         union acpi_operand_object *handler_obj;
  199.  
  200.         ACPI_FUNCTION_ENTRY();
  201.  
  202.         /* Invoke a global notify handler if installed */
  203.  
  204.         if (info->notify.global->handler) {
  205.                 info->notify.global->handler(info->notify.node,
  206.                                              info->notify.value,
  207.                                              info->notify.global->context);
  208.         }
  209.  
  210.         /* Now invoke the local notify handler(s) if any are installed */
  211.  
  212.         handler_obj = info->notify.handler_list_head;
  213.         while (handler_obj) {
  214.                 handler_obj->notify.handler(info->notify.node,
  215.                                             info->notify.value,
  216.                                             handler_obj->notify.context);
  217.  
  218.                 handler_obj =
  219.                     handler_obj->notify.next[info->notify.handler_list_id];
  220.         }
  221.  
  222.         /* All done with the info object */
  223.  
  224.         acpi_ut_delete_generic_state(info);
  225. }
  226.  
  227. #if (!ACPI_REDUCED_HARDWARE)
  228. /******************************************************************************
  229.  *
  230.  * FUNCTION:    acpi_ev_terminate
  231.  *
  232.  * PARAMETERS:  none
  233.  *
  234.  * RETURN:      none
  235.  *
  236.  * DESCRIPTION: Disable events and free memory allocated for table storage.
  237.  *
  238.  ******************************************************************************/
  239.  
  240. void acpi_ev_terminate(void)
  241. {
  242.         u32 i;
  243.         acpi_status status;
  244.  
  245.         ACPI_FUNCTION_TRACE(ev_terminate);
  246.  
  247.         if (acpi_gbl_events_initialized) {
  248.                 /*
  249.                  * Disable all event-related functionality. In all cases, on error,
  250.                  * print a message but obviously we don't abort.
  251.                  */
  252.  
  253.                 /* Disable all fixed events */
  254.  
  255.                 for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
  256.                         status = acpi_disable_event(i, 0);
  257.                         if (ACPI_FAILURE(status)) {
  258.                                 ACPI_ERROR((AE_INFO,
  259.                                             "Could not disable fixed event %u",
  260.                                             (u32) i));
  261.                         }
  262.                 }
  263.  
  264.                 /* Disable all GPEs in all GPE blocks */
  265.  
  266.                 status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
  267.  
  268.                 status = acpi_ev_remove_global_lock_handler();
  269.                 if (ACPI_FAILURE(status)) {
  270.                         ACPI_ERROR((AE_INFO,
  271.                                     "Could not remove Global Lock handler"));
  272.                 }
  273.  
  274.                 acpi_gbl_events_initialized = FALSE;
  275.         }
  276.  
  277.         /* Remove SCI handlers */
  278.  
  279.         status = acpi_ev_remove_all_sci_handlers();
  280.         if (ACPI_FAILURE(status)) {
  281.                 ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
  282.         }
  283.  
  284.         /* Deallocate all handler objects installed within GPE info structs */
  285.  
  286.         status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL);
  287.  
  288.         /* Return to original mode if necessary */
  289.  
  290.         if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
  291.                 status = acpi_disable();
  292.                 if (ACPI_FAILURE(status)) {
  293.                         ACPI_WARNING((AE_INFO, "AcpiDisable failed"));
  294.                 }
  295.         }
  296.         return_VOID;
  297. }
  298.  
  299. #endif                          /* !ACPI_REDUCED_HARDWARE */
  300.