0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acevents.h"
0013 #include "acnamesp.h"
0014
0015 #define _COMPONENT ACPI_EVENTS
0016 ACPI_MODULE_NAME("evmisc")
0017
0018
0019 static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
0036 {
0037
0038 switch (node->type) {
0039 case ACPI_TYPE_DEVICE:
0040 case ACPI_TYPE_PROCESSOR:
0041 case ACPI_TYPE_THERMAL:
0042
0043
0044
0045 return (TRUE);
0046
0047 default:
0048
0049 return (FALSE);
0050 }
0051 }
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 acpi_status
0068 acpi_ev_queue_notify_request(struct acpi_namespace_node *node, u32 notify_value)
0069 {
0070 union acpi_operand_object *obj_desc;
0071 union acpi_operand_object *handler_list_head = NULL;
0072 union acpi_generic_state *info;
0073 u8 handler_list_id = 0;
0074 acpi_status status = AE_OK;
0075
0076 ACPI_FUNCTION_NAME(ev_queue_notify_request);
0077
0078
0079
0080 if (!acpi_ev_is_notify_object(node)) {
0081 return (AE_TYPE);
0082 }
0083
0084
0085
0086 if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
0087 handler_list_id = ACPI_SYSTEM_HANDLER_LIST;
0088 } else {
0089 handler_list_id = ACPI_DEVICE_HANDLER_LIST;
0090 }
0091
0092
0093
0094 obj_desc = acpi_ns_get_attached_object(node);
0095 if (obj_desc) {
0096
0097
0098
0099 handler_list_head =
0100 obj_desc->common_notify.notify_list[handler_list_id];
0101 }
0102
0103
0104
0105
0106
0107 if (!acpi_gbl_global_notify[handler_list_id].handler
0108 && !handler_list_head) {
0109 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0110 "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n",
0111 acpi_ut_get_node_name(node), notify_value,
0112 node));
0113
0114 return (AE_OK);
0115 }
0116
0117
0118
0119 info = acpi_ut_create_generic_state();
0120 if (!info) {
0121 return (AE_NO_MEMORY);
0122 }
0123
0124 info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY;
0125
0126 info->notify.node = node;
0127 info->notify.value = (u16)notify_value;
0128 info->notify.handler_list_id = handler_list_id;
0129 info->notify.handler_list_head = handler_list_head;
0130 info->notify.global = &acpi_gbl_global_notify[handler_list_id];
0131
0132 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0133 "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n",
0134 acpi_ut_get_node_name(node),
0135 acpi_ut_get_type_name(node->type), notify_value,
0136 acpi_ut_get_notify_name(notify_value, ACPI_TYPE_ANY),
0137 node));
0138
0139 status = acpi_os_execute(OSL_NOTIFY_HANDLER,
0140 acpi_ev_notify_dispatch, info);
0141 if (ACPI_FAILURE(status)) {
0142 acpi_ut_delete_generic_state(info);
0143 }
0144
0145 return (status);
0146 }
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
0162 {
0163 union acpi_generic_state *info = (union acpi_generic_state *)context;
0164 union acpi_operand_object *handler_obj;
0165
0166 ACPI_FUNCTION_ENTRY();
0167
0168
0169
0170 if (info->notify.global->handler) {
0171 info->notify.global->handler(info->notify.node,
0172 info->notify.value,
0173 info->notify.global->context);
0174 }
0175
0176
0177
0178 handler_obj = info->notify.handler_list_head;
0179 while (handler_obj) {
0180 handler_obj->notify.handler(info->notify.node,
0181 info->notify.value,
0182 handler_obj->notify.context);
0183
0184 handler_obj =
0185 handler_obj->notify.next[info->notify.handler_list_id];
0186 }
0187
0188
0189
0190 acpi_ut_delete_generic_state(info);
0191 }
0192
0193 #if (!ACPI_REDUCED_HARDWARE)
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 void acpi_ev_terminate(void)
0207 {
0208 u32 i;
0209 acpi_status status;
0210
0211 ACPI_FUNCTION_TRACE(ev_terminate);
0212
0213 if (acpi_gbl_events_initialized) {
0214
0215
0216
0217
0218
0219
0220
0221 for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
0222 status = acpi_disable_event(i, 0);
0223 if (ACPI_FAILURE(status)) {
0224 ACPI_ERROR((AE_INFO,
0225 "Could not disable fixed event %u",
0226 (u32) i));
0227 }
0228 }
0229
0230
0231
0232 status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
0233 if (ACPI_FAILURE(status)) {
0234 ACPI_EXCEPTION((AE_INFO, status,
0235 "Could not disable GPEs in GPE block"));
0236 }
0237
0238 status = acpi_ev_remove_global_lock_handler();
0239 if (ACPI_FAILURE(status)) {
0240 ACPI_EXCEPTION((AE_INFO, status,
0241 "Could not remove Global Lock handler"));
0242 }
0243
0244 acpi_gbl_events_initialized = FALSE;
0245 }
0246
0247
0248
0249 status = acpi_ev_remove_all_sci_handlers();
0250 if (ACPI_FAILURE(status)) {
0251 ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
0252 }
0253
0254
0255
0256 status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL);
0257 if (ACPI_FAILURE(status)) {
0258 ACPI_EXCEPTION((AE_INFO, status,
0259 "Could not delete GPE handlers"));
0260 }
0261
0262
0263
0264 if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
0265 status = acpi_disable();
0266 if (ACPI_FAILURE(status)) {
0267 ACPI_WARNING((AE_INFO, "AcpiDisable failed"));
0268 }
0269 }
0270 return_VOID;
0271 }
0272
0273 #endif