0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acinterp.h"
0013
0014 #define _COMPONENT ACPI_EXECUTER
0015 ACPI_MODULE_NAME("exregion")
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 acpi_status
0035 acpi_ex_system_memory_space_handler(u32 function,
0036 acpi_physical_address address,
0037 u32 bit_width,
0038 u64 *value,
0039 void *handler_context, void *region_context)
0040 {
0041 acpi_status status = AE_OK;
0042 void *logical_addr_ptr = NULL;
0043 struct acpi_mem_space_context *mem_info = region_context;
0044 struct acpi_mem_mapping *mm = mem_info->cur_mm;
0045 u32 length;
0046 acpi_size map_length;
0047 acpi_size page_boundary_map_length;
0048 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
0049 u32 remainder;
0050 #endif
0051
0052 ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
0053
0054
0055
0056 switch (bit_width) {
0057 case 8:
0058
0059 length = 1;
0060 break;
0061
0062 case 16:
0063
0064 length = 2;
0065 break;
0066
0067 case 32:
0068
0069 length = 4;
0070 break;
0071
0072 case 64:
0073
0074 length = 8;
0075 break;
0076
0077 default:
0078
0079 ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u",
0080 bit_width));
0081 return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
0082 }
0083
0084 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
0085
0086
0087
0088
0089 (void)acpi_ut_short_divide((u64) address, length, NULL, &remainder);
0090 if (remainder != 0) {
0091 return_ACPI_STATUS(AE_AML_ALIGNMENT);
0092 }
0093 #endif
0094
0095
0096
0097
0098
0099
0100 if (!mm || (address < mm->physical_address) ||
0101 ((u64) address + length > (u64) mm->physical_address + mm->length)) {
0102
0103
0104
0105
0106
0107
0108
0109 for (mm = mem_info->first_mm; mm; mm = mm->next_mm) {
0110 if (mm == mem_info->cur_mm)
0111 continue;
0112
0113 if (address < mm->physical_address)
0114 continue;
0115
0116 if ((u64) address + length >
0117 (u64) mm->physical_address + mm->length)
0118 continue;
0119
0120 mem_info->cur_mm = mm;
0121 goto access;
0122 }
0123
0124
0125 mm = ACPI_ALLOCATE_ZEROED(sizeof(*mm));
0126 if (!mm) {
0127 ACPI_ERROR((AE_INFO,
0128 "Unable to save memory mapping at 0x%8.8X%8.8X, size %u",
0129 ACPI_FORMAT_UINT64(address), length));
0130 return_ACPI_STATUS(AE_NO_MEMORY);
0131 }
0132
0133
0134
0135
0136
0137
0138 map_length = (acpi_size)
0139 ((mem_info->address + mem_info->length) - address);
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152 page_boundary_map_length = (acpi_size)
0153 (ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address);
0154 if (page_boundary_map_length == 0) {
0155 page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE;
0156 }
0157
0158 if (map_length > page_boundary_map_length) {
0159 map_length = page_boundary_map_length;
0160 }
0161
0162
0163
0164 logical_addr_ptr = acpi_os_map_memory(address, map_length);
0165 if (!logical_addr_ptr) {
0166 ACPI_ERROR((AE_INFO,
0167 "Could not map memory at 0x%8.8X%8.8X, size %u",
0168 ACPI_FORMAT_UINT64(address),
0169 (u32)map_length));
0170 ACPI_FREE(mm);
0171 return_ACPI_STATUS(AE_NO_MEMORY);
0172 }
0173
0174
0175
0176 mm->logical_address = logical_addr_ptr;
0177 mm->physical_address = address;
0178 mm->length = map_length;
0179
0180
0181
0182
0183
0184 mm->next_mm = mem_info->first_mm;
0185 mem_info->first_mm = mm;
0186
0187 mem_info->cur_mm = mm;
0188 }
0189
0190 access:
0191
0192
0193
0194
0195 logical_addr_ptr = mm->logical_address +
0196 ((u64) address - (u64) mm->physical_address);
0197
0198 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0199 "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
0200 bit_width, function, ACPI_FORMAT_UINT64(address)));
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 switch (function) {
0211 case ACPI_READ:
0212
0213 *value = 0;
0214 switch (bit_width) {
0215 case 8:
0216
0217 *value = (u64)ACPI_GET8(logical_addr_ptr);
0218 break;
0219
0220 case 16:
0221
0222 *value = (u64)ACPI_GET16(logical_addr_ptr);
0223 break;
0224
0225 case 32:
0226
0227 *value = (u64)ACPI_GET32(logical_addr_ptr);
0228 break;
0229
0230 case 64:
0231
0232 *value = (u64)ACPI_GET64(logical_addr_ptr);
0233 break;
0234
0235 default:
0236
0237
0238
0239 break;
0240 }
0241 break;
0242
0243 case ACPI_WRITE:
0244
0245 switch (bit_width) {
0246 case 8:
0247
0248 ACPI_SET8(logical_addr_ptr, *value);
0249 break;
0250
0251 case 16:
0252
0253 ACPI_SET16(logical_addr_ptr, *value);
0254 break;
0255
0256 case 32:
0257
0258 ACPI_SET32(logical_addr_ptr, *value);
0259 break;
0260
0261 case 64:
0262
0263 ACPI_SET64(logical_addr_ptr, *value);
0264 break;
0265
0266 default:
0267
0268
0269
0270 break;
0271 }
0272 break;
0273
0274 default:
0275
0276 status = AE_BAD_PARAMETER;
0277 break;
0278 }
0279
0280 return_ACPI_STATUS(status);
0281 }
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301 acpi_status
0302 acpi_ex_system_io_space_handler(u32 function,
0303 acpi_physical_address address,
0304 u32 bit_width,
0305 u64 *value,
0306 void *handler_context, void *region_context)
0307 {
0308 acpi_status status = AE_OK;
0309 u32 value32;
0310
0311 ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
0312
0313 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0314 "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
0315 bit_width, function, ACPI_FORMAT_UINT64(address)));
0316
0317
0318
0319 switch (function) {
0320 case ACPI_READ:
0321
0322 status = acpi_hw_read_port((acpi_io_address)address,
0323 &value32, bit_width);
0324 *value = value32;
0325 break;
0326
0327 case ACPI_WRITE:
0328
0329 status = acpi_hw_write_port((acpi_io_address)address,
0330 (u32)*value, bit_width);
0331 break;
0332
0333 default:
0334
0335 status = AE_BAD_PARAMETER;
0336 break;
0337 }
0338
0339 return_ACPI_STATUS(status);
0340 }
0341
0342 #ifdef ACPI_PCI_CONFIGURED
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361 acpi_status
0362 acpi_ex_pci_config_space_handler(u32 function,
0363 acpi_physical_address address,
0364 u32 bit_width,
0365 u64 *value,
0366 void *handler_context, void *region_context)
0367 {
0368 acpi_status status = AE_OK;
0369 struct acpi_pci_id *pci_id;
0370 u16 pci_register;
0371
0372 ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386 pci_id = (struct acpi_pci_id *)region_context;
0387 pci_register = (u16) (u32) address;
0388
0389 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0390 "Pci-Config %u (%u) Seg(%04x) Bus(%04x) "
0391 "Dev(%04x) Func(%04x) Reg(%04x)\n",
0392 function, bit_width, pci_id->segment, pci_id->bus,
0393 pci_id->device, pci_id->function, pci_register));
0394
0395 switch (function) {
0396 case ACPI_READ:
0397
0398 *value = 0;
0399 status =
0400 acpi_os_read_pci_configuration(pci_id, pci_register, value,
0401 bit_width);
0402 break;
0403
0404 case ACPI_WRITE:
0405
0406 status =
0407 acpi_os_write_pci_configuration(pci_id, pci_register,
0408 *value, bit_width);
0409 break;
0410
0411 default:
0412
0413 status = AE_BAD_PARAMETER;
0414 break;
0415 }
0416
0417 return_ACPI_STATUS(status);
0418 }
0419 #endif
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439 acpi_status
0440 acpi_ex_cmos_space_handler(u32 function,
0441 acpi_physical_address address,
0442 u32 bit_width,
0443 u64 *value,
0444 void *handler_context, void *region_context)
0445 {
0446 acpi_status status = AE_OK;
0447
0448 ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
0449
0450 return_ACPI_STATUS(status);
0451 }
0452
0453 #ifdef ACPI_PCI_CONFIGURED
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472 acpi_status
0473 acpi_ex_pci_bar_space_handler(u32 function,
0474 acpi_physical_address address,
0475 u32 bit_width,
0476 u64 *value,
0477 void *handler_context, void *region_context)
0478 {
0479 acpi_status status = AE_OK;
0480
0481 ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
0482
0483 return_ACPI_STATUS(status);
0484 }
0485 #endif
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505 acpi_status
0506 acpi_ex_data_table_space_handler(u32 function,
0507 acpi_physical_address address,
0508 u32 bit_width,
0509 u64 *value,
0510 void *handler_context, void *region_context)
0511 {
0512 struct acpi_data_table_space_context *mapping;
0513 char *pointer;
0514
0515 ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
0516
0517 mapping = (struct acpi_data_table_space_context *) region_context;
0518 pointer = ACPI_CAST_PTR(char, mapping->pointer) +
0519 (address - ACPI_PTR_TO_PHYSADDR(mapping->pointer));
0520
0521
0522
0523
0524
0525 switch (function) {
0526 case ACPI_READ:
0527
0528 memcpy(ACPI_CAST_PTR(char, value), pointer,
0529 ACPI_DIV_8(bit_width));
0530 break;
0531
0532 case ACPI_WRITE:
0533
0534 memcpy(pointer, ACPI_CAST_PTR(char, value),
0535 ACPI_DIV_8(bit_width));
0536 break;
0537
0538 default:
0539
0540 return_ACPI_STATUS(AE_BAD_PARAMETER);
0541 }
0542
0543 return_ACPI_STATUS(AE_OK);
0544 }