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("evrgnini")
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 acpi_status
0034 acpi_ev_system_memory_region_setup(acpi_handle handle,
0035 u32 function,
0036 void *handler_context, void **region_context)
0037 {
0038 union acpi_operand_object *region_desc =
0039 (union acpi_operand_object *)handle;
0040 struct acpi_mem_space_context *local_region_context;
0041 struct acpi_mem_mapping *mm;
0042
0043 ACPI_FUNCTION_TRACE(ev_system_memory_region_setup);
0044
0045 if (function == ACPI_REGION_DEACTIVATE) {
0046 if (*region_context) {
0047 local_region_context =
0048 (struct acpi_mem_space_context *)*region_context;
0049
0050
0051
0052 while (local_region_context->first_mm) {
0053 mm = local_region_context->first_mm;
0054 local_region_context->first_mm = mm->next_mm;
0055 acpi_os_unmap_memory(mm->logical_address,
0056 mm->length);
0057 ACPI_FREE(mm);
0058 }
0059 ACPI_FREE(local_region_context);
0060 *region_context = NULL;
0061 }
0062 return_ACPI_STATUS(AE_OK);
0063 }
0064
0065
0066
0067 local_region_context =
0068 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context));
0069 if (!(local_region_context)) {
0070 return_ACPI_STATUS(AE_NO_MEMORY);
0071 }
0072
0073
0074
0075 local_region_context->length = region_desc->region.length;
0076 local_region_context->address = region_desc->region.address;
0077
0078 *region_context = local_region_context;
0079 return_ACPI_STATUS(AE_OK);
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 acpi_status
0098 acpi_ev_io_space_region_setup(acpi_handle handle,
0099 u32 function,
0100 void *handler_context, void **region_context)
0101 {
0102 ACPI_FUNCTION_TRACE(ev_io_space_region_setup);
0103
0104 if (function == ACPI_REGION_DEACTIVATE) {
0105 *region_context = NULL;
0106 } else {
0107 *region_context = handler_context;
0108 }
0109
0110 return_ACPI_STATUS(AE_OK);
0111 }
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 acpi_status
0131 acpi_ev_pci_config_region_setup(acpi_handle handle,
0132 u32 function,
0133 void *handler_context, void **region_context)
0134 {
0135 acpi_status status = AE_OK;
0136 u64 pci_value;
0137 struct acpi_pci_id *pci_id = *region_context;
0138 union acpi_operand_object *handler_obj;
0139 struct acpi_namespace_node *parent_node;
0140 struct acpi_namespace_node *pci_root_node;
0141 struct acpi_namespace_node *pci_device_node;
0142 union acpi_operand_object *region_obj =
0143 (union acpi_operand_object *)handle;
0144
0145 ACPI_FUNCTION_TRACE(ev_pci_config_region_setup);
0146
0147 handler_obj = region_obj->region.handler;
0148 if (!handler_obj) {
0149
0150
0151
0152
0153 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
0154 "Attempting to init a region %p, with no handler\n",
0155 region_obj));
0156 return_ACPI_STATUS(AE_NOT_EXIST);
0157 }
0158
0159 *region_context = NULL;
0160 if (function == ACPI_REGION_DEACTIVATE) {
0161 if (pci_id) {
0162 ACPI_FREE(pci_id);
0163 }
0164 return_ACPI_STATUS(status);
0165 }
0166
0167 parent_node = region_obj->region.node->parent;
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182 if (handler_obj->address_space.node == acpi_gbl_root_node) {
0183
0184
0185
0186 pci_root_node = parent_node;
0187 while (pci_root_node != acpi_gbl_root_node) {
0188
0189
0190
0191 if (acpi_ev_is_pci_root_bridge(pci_root_node)) {
0192
0193
0194
0195 status = acpi_install_address_space_handler((acpi_handle)pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
0196 if (ACPI_FAILURE(status)) {
0197 if (status == AE_SAME_HANDLER) {
0198
0199
0200
0201
0202
0203 } else {
0204 ACPI_EXCEPTION((AE_INFO, status,
0205 "Could not install PciConfig handler "
0206 "for Root Bridge %4.4s",
0207 acpi_ut_get_node_name
0208 (pci_root_node)));
0209 }
0210 }
0211 break;
0212 }
0213
0214 pci_root_node = pci_root_node->parent;
0215 }
0216
0217
0218 } else {
0219 pci_root_node = handler_obj->address_space.node;
0220 }
0221
0222
0223
0224
0225
0226 if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
0227 return_ACPI_STATUS(AE_OK);
0228 }
0229
0230
0231
0232 pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id));
0233 if (!pci_id) {
0234 return_ACPI_STATUS(AE_NO_MEMORY);
0235 }
0236
0237
0238
0239
0240
0241
0242
0243
0244 pci_device_node = region_obj->region.node;
0245 while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) {
0246 pci_device_node = pci_device_node->parent;
0247 }
0248
0249 if (!pci_device_node) {
0250 ACPI_FREE(pci_id);
0251 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0252 }
0253
0254
0255
0256
0257
0258 status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
0259 pci_device_node, &pci_value);
0260
0261
0262
0263
0264
0265 if (ACPI_SUCCESS(status)) {
0266 pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value));
0267 pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value));
0268 }
0269
0270
0271
0272 status = acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG,
0273 pci_root_node, &pci_value);
0274 if (ACPI_SUCCESS(status)) {
0275 pci_id->segment = ACPI_LOWORD(pci_value);
0276 }
0277
0278
0279
0280 status = acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN,
0281 pci_root_node, &pci_value);
0282 if (ACPI_SUCCESS(status)) {
0283 pci_id->bus = ACPI_LOWORD(pci_value);
0284 }
0285
0286
0287
0288 status =
0289 acpi_hw_derive_pci_id(pci_id, pci_root_node,
0290 region_obj->region.node);
0291 if (ACPI_FAILURE(status)) {
0292 ACPI_FREE(pci_id);
0293 return_ACPI_STATUS(status);
0294 }
0295
0296 *region_context = pci_id;
0297 return_ACPI_STATUS(AE_OK);
0298 }
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313 u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
0314 {
0315 acpi_status status;
0316 struct acpi_pnp_device_id *hid;
0317 struct acpi_pnp_device_id_list *cid;
0318 u32 i;
0319 u8 match;
0320
0321
0322
0323 status = acpi_ut_execute_HID(node, &hid);
0324 if (ACPI_FAILURE(status)) {
0325 return (FALSE);
0326 }
0327
0328 match = acpi_ut_is_pci_root_bridge(hid->string);
0329 ACPI_FREE(hid);
0330
0331 if (match) {
0332 return (TRUE);
0333 }
0334
0335
0336
0337 status = acpi_ut_execute_CID(node, &cid);
0338 if (ACPI_FAILURE(status)) {
0339 return (FALSE);
0340 }
0341
0342
0343
0344 for (i = 0; i < cid->count; i++) {
0345 if (acpi_ut_is_pci_root_bridge(cid->ids[i].string)) {
0346 ACPI_FREE(cid);
0347 return (TRUE);
0348 }
0349 }
0350
0351 ACPI_FREE(cid);
0352 return (FALSE);
0353 }
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372 acpi_status
0373 acpi_ev_pci_bar_region_setup(acpi_handle handle,
0374 u32 function,
0375 void *handler_context, void **region_context)
0376 {
0377 ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup);
0378
0379 return_ACPI_STATUS(AE_OK);
0380 }
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399 acpi_status
0400 acpi_ev_cmos_region_setup(acpi_handle handle,
0401 u32 function,
0402 void *handler_context, void **region_context)
0403 {
0404 ACPI_FUNCTION_TRACE(ev_cmos_region_setup);
0405
0406 return_ACPI_STATUS(AE_OK);
0407 }
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426 acpi_status
0427 acpi_ev_data_table_region_setup(acpi_handle handle,
0428 u32 function,
0429 void *handler_context, void **region_context)
0430 {
0431 union acpi_operand_object *region_desc =
0432 (union acpi_operand_object *)handle;
0433 struct acpi_data_table_space_context *local_region_context;
0434
0435 ACPI_FUNCTION_TRACE(ev_data_table_region_setup);
0436
0437 if (function == ACPI_REGION_DEACTIVATE) {
0438 if (*region_context) {
0439 ACPI_FREE(*region_context);
0440 *region_context = NULL;
0441 }
0442 return_ACPI_STATUS(AE_OK);
0443 }
0444
0445
0446
0447 local_region_context =
0448 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_data_table_space_context));
0449 if (!(local_region_context)) {
0450 return_ACPI_STATUS(AE_NO_MEMORY);
0451 }
0452
0453
0454
0455 local_region_context->pointer = region_desc->region.pointer;
0456
0457 *region_context = local_region_context;
0458 return_ACPI_STATUS(AE_OK);
0459 }
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476 acpi_status
0477 acpi_ev_default_region_setup(acpi_handle handle,
0478 u32 function,
0479 void *handler_context, void **region_context)
0480 {
0481 ACPI_FUNCTION_TRACE(ev_default_region_setup);
0482
0483 if (function == ACPI_REGION_DEACTIVATE) {
0484 *region_context = NULL;
0485 } else {
0486 *region_context = handler_context;
0487 }
0488
0489 return_ACPI_STATUS(AE_OK);
0490 }
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528 acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj)
0529 {
0530 union acpi_operand_object *handler_obj;
0531 union acpi_operand_object *obj_desc;
0532 acpi_adr_space_type space_id;
0533 struct acpi_namespace_node *node;
0534
0535 ACPI_FUNCTION_TRACE(ev_initialize_region);
0536
0537 if (!region_obj) {
0538 return_ACPI_STATUS(AE_BAD_PARAMETER);
0539 }
0540
0541 if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) {
0542 return_ACPI_STATUS(AE_OK);
0543 }
0544
0545 region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;
0546
0547 node = region_obj->region.node->parent;
0548 space_id = region_obj->region.space_id;
0549
0550
0551
0552
0553
0554 while (node) {
0555
0556
0557
0558 handler_obj = NULL;
0559 obj_desc = acpi_ns_get_attached_object(node);
0560 if (obj_desc) {
0561
0562
0563
0564 switch (node->type) {
0565 case ACPI_TYPE_DEVICE:
0566 case ACPI_TYPE_PROCESSOR:
0567 case ACPI_TYPE_THERMAL:
0568
0569 handler_obj = obj_desc->common_notify.handler;
0570 break;
0571
0572 default:
0573
0574
0575
0576 break;
0577 }
0578
0579 handler_obj =
0580 acpi_ev_find_region_handler(space_id, handler_obj);
0581 if (handler_obj) {
0582
0583
0584
0585 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
0586 "Found handler %p for region %p in obj %p\n",
0587 handler_obj, region_obj,
0588 obj_desc));
0589
0590 (void)acpi_ev_attach_region(handler_obj,
0591 region_obj, FALSE);
0592
0593
0594
0595
0596
0597 acpi_ex_exit_interpreter();
0598 (void)acpi_ev_execute_reg_method(region_obj,
0599 ACPI_REG_CONNECT);
0600 acpi_ex_enter_interpreter();
0601 return_ACPI_STATUS(AE_OK);
0602 }
0603 }
0604
0605
0606
0607 node = node->parent;
0608 }
0609
0610
0611
0612
0613
0614
0615 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
0616 "No handler for RegionType %s(%X) (RegionObj %p)\n",
0617 acpi_ut_get_region_name(space_id), space_id,
0618 region_obj));
0619
0620 return_ACPI_STATUS(AE_OK);
0621 }