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 #include "acinterp.h"
0015
0016 #define _COMPONENT ACPI_EVENTS
0017 ACPI_MODULE_NAME("evhandler")
0018
0019
0020 static acpi_status
0021 acpi_ev_install_handler(acpi_handle obj_handle,
0022 u32 level, void *context, void **return_value);
0023
0024
0025
0026 u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
0027 ACPI_ADR_SPACE_SYSTEM_MEMORY,
0028 ACPI_ADR_SPACE_SYSTEM_IO,
0029 ACPI_ADR_SPACE_PCI_CONFIG,
0030 ACPI_ADR_SPACE_DATA_TABLE
0031 };
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 acpi_status acpi_ev_install_region_handlers(void)
0046 {
0047 acpi_status status;
0048 u32 i;
0049
0050 ACPI_FUNCTION_TRACE(ev_install_region_handlers);
0051
0052 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0053 if (ACPI_FAILURE(status)) {
0054 return_ACPI_STATUS(status);
0055 }
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
0077 status = acpi_ev_install_space_handler(acpi_gbl_root_node,
0078 acpi_gbl_default_address_spaces
0079 [i],
0080 ACPI_DEFAULT_HANDLER,
0081 NULL, NULL);
0082 switch (status) {
0083 case AE_OK:
0084 case AE_SAME_HANDLER:
0085 case AE_ALREADY_EXISTS:
0086
0087
0088
0089 status = AE_OK;
0090 break;
0091
0092 default:
0093
0094 goto unlock_and_exit;
0095 }
0096 }
0097
0098 unlock_and_exit:
0099 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0100 return_ACPI_STATUS(status);
0101 }
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117 u8
0118 acpi_ev_has_default_handler(struct acpi_namespace_node *node,
0119 acpi_adr_space_type space_id)
0120 {
0121 union acpi_operand_object *obj_desc;
0122 union acpi_operand_object *handler_obj;
0123
0124
0125
0126 obj_desc = acpi_ns_get_attached_object(node);
0127 if (obj_desc) {
0128 handler_obj = obj_desc->common_notify.handler;
0129
0130
0131
0132 while (handler_obj) {
0133 if (handler_obj->address_space.space_id == space_id) {
0134 if (handler_obj->address_space.handler_flags &
0135 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
0136 return (TRUE);
0137 }
0138 }
0139
0140 handler_obj = handler_obj->address_space.next;
0141 }
0142 }
0143
0144 return (FALSE);
0145 }
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164 static acpi_status
0165 acpi_ev_install_handler(acpi_handle obj_handle,
0166 u32 level, void *context, void **return_value)
0167 {
0168 union acpi_operand_object *handler_obj;
0169 union acpi_operand_object *next_handler_obj;
0170 union acpi_operand_object *obj_desc;
0171 struct acpi_namespace_node *node;
0172 acpi_status status;
0173
0174 ACPI_FUNCTION_NAME(ev_install_handler);
0175
0176 handler_obj = (union acpi_operand_object *)context;
0177
0178
0179
0180 if (!handler_obj) {
0181 return (AE_OK);
0182 }
0183
0184
0185
0186 node = acpi_ns_validate_handle(obj_handle);
0187 if (!node) {
0188 return (AE_BAD_PARAMETER);
0189 }
0190
0191
0192
0193
0194
0195 if ((node->type != ACPI_TYPE_DEVICE) &&
0196 (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
0197 return (AE_OK);
0198 }
0199
0200
0201
0202 obj_desc = acpi_ns_get_attached_object(node);
0203 if (!obj_desc) {
0204
0205
0206
0207 return (AE_OK);
0208 }
0209
0210
0211
0212 if (obj_desc->common.type == ACPI_TYPE_DEVICE) {
0213
0214
0215
0216 next_handler_obj =
0217 acpi_ev_find_region_handler(handler_obj->address_space.
0218 space_id,
0219 obj_desc->common_notify.
0220 handler);
0221 if (next_handler_obj) {
0222
0223
0224
0225 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
0226 "Found handler for region [%s] in device %p(%p) handler %p\n",
0227 acpi_ut_get_region_name(handler_obj->
0228 address_space.
0229 space_id),
0230 obj_desc, next_handler_obj,
0231 handler_obj));
0232
0233
0234
0235
0236
0237
0238
0239
0240 return (AE_CTRL_DEPTH);
0241 }
0242
0243
0244
0245
0246
0247 return (AE_OK);
0248 }
0249
0250
0251
0252 if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
0253
0254
0255
0256 return (AE_OK);
0257 }
0258
0259
0260
0261
0262
0263
0264 acpi_ev_detach_region(obj_desc, FALSE);
0265
0266
0267
0268 status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE);
0269 return (status);
0270 }
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286 union acpi_operand_object *acpi_ev_find_region_handler(acpi_adr_space_type
0287 space_id,
0288 union acpi_operand_object
0289 *handler_obj)
0290 {
0291
0292
0293
0294 while (handler_obj) {
0295
0296
0297
0298 if (handler_obj->address_space.space_id == space_id) {
0299 return (handler_obj);
0300 }
0301
0302
0303
0304 handler_obj = handler_obj->address_space.next;
0305 }
0306
0307 return (NULL);
0308 }
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327 acpi_status
0328 acpi_ev_install_space_handler(struct acpi_namespace_node *node,
0329 acpi_adr_space_type space_id,
0330 acpi_adr_space_handler handler,
0331 acpi_adr_space_setup setup, void *context)
0332 {
0333 union acpi_operand_object *obj_desc;
0334 union acpi_operand_object *handler_obj;
0335 acpi_status status = AE_OK;
0336 acpi_object_type type;
0337 u8 flags = 0;
0338
0339 ACPI_FUNCTION_TRACE(ev_install_space_handler);
0340
0341
0342
0343
0344
0345 if ((node->type != ACPI_TYPE_DEVICE) &&
0346 (node->type != ACPI_TYPE_PROCESSOR) &&
0347 (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) {
0348 status = AE_BAD_PARAMETER;
0349 goto unlock_and_exit;
0350 }
0351
0352 if (handler == ACPI_DEFAULT_HANDLER) {
0353 flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
0354
0355 switch (space_id) {
0356 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
0357
0358 handler = acpi_ex_system_memory_space_handler;
0359 setup = acpi_ev_system_memory_region_setup;
0360 break;
0361
0362 case ACPI_ADR_SPACE_SYSTEM_IO:
0363
0364 handler = acpi_ex_system_io_space_handler;
0365 setup = acpi_ev_io_space_region_setup;
0366 break;
0367 #ifdef ACPI_PCI_CONFIGURED
0368 case ACPI_ADR_SPACE_PCI_CONFIG:
0369
0370 handler = acpi_ex_pci_config_space_handler;
0371 setup = acpi_ev_pci_config_region_setup;
0372 break;
0373 #endif
0374 case ACPI_ADR_SPACE_CMOS:
0375
0376 handler = acpi_ex_cmos_space_handler;
0377 setup = acpi_ev_cmos_region_setup;
0378 break;
0379 #ifdef ACPI_PCI_CONFIGURED
0380 case ACPI_ADR_SPACE_PCI_BAR_TARGET:
0381
0382 handler = acpi_ex_pci_bar_space_handler;
0383 setup = acpi_ev_pci_bar_region_setup;
0384 break;
0385 #endif
0386 case ACPI_ADR_SPACE_DATA_TABLE:
0387
0388 handler = acpi_ex_data_table_space_handler;
0389 setup = acpi_ev_data_table_region_setup;
0390 break;
0391
0392 default:
0393
0394 status = AE_BAD_PARAMETER;
0395 goto unlock_and_exit;
0396 }
0397 }
0398
0399
0400
0401 if (!setup) {
0402 setup = acpi_ev_default_region_setup;
0403 }
0404
0405
0406
0407 obj_desc = acpi_ns_get_attached_object(node);
0408 if (obj_desc) {
0409
0410
0411
0412
0413 handler_obj = acpi_ev_find_region_handler(space_id,
0414 obj_desc->
0415 common_notify.
0416 handler);
0417
0418 if (handler_obj) {
0419 if (handler_obj->address_space.handler == handler) {
0420
0421
0422
0423
0424
0425 status = AE_SAME_HANDLER;
0426 goto unlock_and_exit;
0427 } else {
0428
0429
0430 status = AE_ALREADY_EXISTS;
0431 }
0432
0433 goto unlock_and_exit;
0434 }
0435 } else {
0436 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
0437 "Creating object on Device %p while installing handler\n",
0438 node));
0439
0440
0441
0442 if (node->type == ACPI_TYPE_ANY) {
0443 type = ACPI_TYPE_DEVICE;
0444 } else {
0445 type = node->type;
0446 }
0447
0448 obj_desc = acpi_ut_create_internal_object(type);
0449 if (!obj_desc) {
0450 status = AE_NO_MEMORY;
0451 goto unlock_and_exit;
0452 }
0453
0454
0455
0456 obj_desc->common.type = (u8)type;
0457
0458
0459
0460 status = acpi_ns_attach_object(node, obj_desc, type);
0461
0462
0463
0464 acpi_ut_remove_reference(obj_desc);
0465
0466 if (ACPI_FAILURE(status)) {
0467 goto unlock_and_exit;
0468 }
0469 }
0470
0471 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
0472 "Installing address handler for region %s(%X) "
0473 "on Device %4.4s %p(%p)\n",
0474 acpi_ut_get_region_name(space_id), space_id,
0475 acpi_ut_get_node_name(node), node, obj_desc));
0476
0477
0478
0479
0480
0481
0482
0483 handler_obj =
0484 acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
0485 if (!handler_obj) {
0486 status = AE_NO_MEMORY;
0487 goto unlock_and_exit;
0488 }
0489
0490
0491
0492 status =
0493 acpi_os_create_mutex(&handler_obj->address_space.context_mutex);
0494 if (ACPI_FAILURE(status)) {
0495 acpi_ut_remove_reference(handler_obj);
0496 goto unlock_and_exit;
0497 }
0498
0499 handler_obj->address_space.space_id = (u8)space_id;
0500 handler_obj->address_space.handler_flags = flags;
0501 handler_obj->address_space.region_list = NULL;
0502 handler_obj->address_space.node = node;
0503 handler_obj->address_space.handler = handler;
0504 handler_obj->address_space.context = context;
0505 handler_obj->address_space.setup = setup;
0506
0507
0508
0509 handler_obj->address_space.next = obj_desc->common_notify.handler;
0510
0511
0512
0513
0514
0515 obj_desc->common_notify.handler = handler_obj;
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527 status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node,
0528 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
0529 acpi_ev_install_handler, NULL,
0530 handler_obj, NULL);
0531
0532 unlock_and_exit:
0533 return_ACPI_STATUS(status);
0534 }