1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: exregion - ACPI default op_region (address space) handlers 5 * 6 * Copyright (C) 2000 - 2023, Intel Corp. 7 * 8 *****************************************************************************/ 9 10 #include <acpi/acpi.h> 11 #include "accommon.h" 12 #include "acinterp.h" 13 14 #define _COMPONENT ACPI_EXECUTER 15 ACPI_MODULE_NAME("exregion") 16 17 /******************************************************************************* 18 * 19 * FUNCTION: acpi_ex_system_memory_space_handler 20 * 21 * PARAMETERS: function - Read or Write operation 22 * address - Where in the space to read or write 23 * bit_width - Field width in bits (8, 16, or 32) 24 * value - Pointer to in or out value 25 * handler_context - Pointer to Handler's context 26 * region_context - Pointer to context specific to the 27 * accessed region 28 * 29 * RETURN: Status 30 * 31 * DESCRIPTION: Handler for the System Memory address space (Op Region) 32 * 33 ******************************************************************************/ 34 acpi_status 35 acpi_ex_system_memory_space_handler(u32 function, 36 acpi_physical_address address, 37 u32 bit_width, 38 u64 *value, 39 void *handler_context, void *region_context) 40 { 41 acpi_status status = AE_OK; 42 void *logical_addr_ptr = NULL; 43 struct acpi_mem_space_context *mem_info = region_context; 44 struct acpi_mem_mapping *mm = mem_info->cur_mm; 45 u32 length; 46 acpi_size map_length; 47 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED 48 u32 remainder; 49 #endif 50 51 ACPI_FUNCTION_TRACE(ex_system_memory_space_handler); 52 53 /* Validate and translate the bit width */ 54 55 switch (bit_width) { 56 case 8: 57 58 length = 1; 59 break; 60 61 case 16: 62 63 length = 2; 64 break; 65 66 case 32: 67 68 length = 4; 69 break; 70 71 case 64: 72 73 length = 8; 74 break; 75 76 default: 77 78 ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u", 79 bit_width)); 80 return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 81 } 82 83 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED 84 /* 85 * Hardware does not support non-aligned data transfers, we must verify 86 * the request. 87 */ 88 (void)acpi_ut_short_divide((u64) address, length, NULL, &remainder); 89 if (remainder != 0) { 90 return_ACPI_STATUS(AE_AML_ALIGNMENT); 91 } 92 #endif 93 94 /* 95 * Does the request fit into the cached memory mapping? 96 * Is 1) Address below the current mapping? OR 97 * 2) Address beyond the current mapping? 98 */ 99 if (!mm || (address < mm->physical_address) || 100 ((u64) address + length > (u64) mm->physical_address + mm->length)) { 101 /* 102 * The request cannot be resolved by the current memory mapping. 103 * 104 * Look for an existing saved mapping covering the address range 105 * at hand. If found, save it as the current one and carry out 106 * the access. 107 */ 108 for (mm = mem_info->first_mm; mm; mm = mm->next_mm) { 109 if (mm == mem_info->cur_mm) 110 continue; 111 112 if (address < mm->physical_address) 113 continue; 114 115 if ((u64) address + length > 116 (u64) mm->physical_address + mm->length) 117 continue; 118 119 mem_info->cur_mm = mm; 120 goto access; 121 } 122 123 /* Create a new mappings list entry */ 124 mm = ACPI_ALLOCATE_ZEROED(sizeof(*mm)); 125 if (!mm) { 126 ACPI_ERROR((AE_INFO, 127 "Unable to save memory mapping at 0x%8.8X%8.8X, size %u", 128 ACPI_FORMAT_UINT64(address), length)); 129 return_ACPI_STATUS(AE_NO_MEMORY); 130 } 131 132 /* 133 * October 2009: Attempt to map from the requested address to the 134 * end of the region. However, we will never map more than one 135 * page, nor will we cross a page boundary. 136 */ 137 map_length = (acpi_size) 138 ((mem_info->address + mem_info->length) - address); 139 140 if (map_length > ACPI_DEFAULT_PAGE_SIZE) 141 map_length = ACPI_DEFAULT_PAGE_SIZE; 142 143 /* Create a new mapping starting at the address given */ 144 145 logical_addr_ptr = acpi_os_map_memory(address, map_length); 146 if (!logical_addr_ptr) { 147 ACPI_ERROR((AE_INFO, 148 "Could not map memory at 0x%8.8X%8.8X, size %u", 149 ACPI_FORMAT_UINT64(address), 150 (u32)map_length)); 151 ACPI_FREE(mm); 152 return_ACPI_STATUS(AE_NO_MEMORY); 153 } 154 155 /* Save the physical address and mapping size */ 156 157 mm->logical_address = logical_addr_ptr; 158 mm->physical_address = address; 159 mm->length = map_length; 160 161 /* 162 * Add the new entry to the mappigs list and save it as the 163 * current mapping. 164 */ 165 mm->next_mm = mem_info->first_mm; 166 mem_info->first_mm = mm; 167 168 mem_info->cur_mm = mm; 169 } 170 171 access: 172 /* 173 * Generate a logical pointer corresponding to the address we want to 174 * access 175 */ 176 logical_addr_ptr = mm->logical_address + 177 ((u64) address - (u64) mm->physical_address); 178 179 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 180 "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", 181 bit_width, function, ACPI_FORMAT_UINT64(address))); 182 183 /* 184 * Perform the memory read or write 185 * 186 * Note: For machines that do not support non-aligned transfers, the target 187 * address was checked for alignment above. We do not attempt to break the 188 * transfer up into smaller (byte-size) chunks because the AML specifically 189 * asked for a transfer width that the hardware may require. 190 */ 191 switch (function) { 192 case ACPI_READ: 193 194 *value = 0; 195 switch (bit_width) { 196 case 8: 197 198 *value = (u64)ACPI_GET8(logical_addr_ptr); 199 break; 200 201 case 16: 202 203 *value = (u64)ACPI_GET16(logical_addr_ptr); 204 break; 205 206 case 32: 207 208 *value = (u64)ACPI_GET32(logical_addr_ptr); 209 break; 210 211 case 64: 212 213 *value = (u64)ACPI_GET64(logical_addr_ptr); 214 break; 215 216 default: 217 218 /* bit_width was already validated */ 219 220 break; 221 } 222 break; 223 224 case ACPI_WRITE: 225 226 switch (bit_width) { 227 case 8: 228 229 ACPI_SET8(logical_addr_ptr, *value); 230 break; 231 232 case 16: 233 234 ACPI_SET16(logical_addr_ptr, *value); 235 break; 236 237 case 32: 238 239 ACPI_SET32(logical_addr_ptr, *value); 240 break; 241 242 case 64: 243 244 ACPI_SET64(logical_addr_ptr, *value); 245 break; 246 247 default: 248 249 /* bit_width was already validated */ 250 251 break; 252 } 253 break; 254 255 default: 256 257 status = AE_BAD_PARAMETER; 258 break; 259 } 260 261 return_ACPI_STATUS(status); 262 } 263 264 /******************************************************************************* 265 * 266 * FUNCTION: acpi_ex_system_io_space_handler 267 * 268 * PARAMETERS: function - Read or Write operation 269 * address - Where in the space to read or write 270 * bit_width - Field width in bits (8, 16, or 32) 271 * value - Pointer to in or out value 272 * handler_context - Pointer to Handler's context 273 * region_context - Pointer to context specific to the 274 * accessed region 275 * 276 * RETURN: Status 277 * 278 * DESCRIPTION: Handler for the System IO address space (Op Region) 279 * 280 ******************************************************************************/ 281 282 acpi_status 283 acpi_ex_system_io_space_handler(u32 function, 284 acpi_physical_address address, 285 u32 bit_width, 286 u64 *value, 287 void *handler_context, void *region_context) 288 { 289 acpi_status status = AE_OK; 290 u32 value32; 291 292 ACPI_FUNCTION_TRACE(ex_system_io_space_handler); 293 294 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 295 "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n", 296 bit_width, function, ACPI_FORMAT_UINT64(address))); 297 298 /* Decode the function parameter */ 299 300 switch (function) { 301 case ACPI_READ: 302 303 status = acpi_hw_read_port((acpi_io_address)address, 304 &value32, bit_width); 305 *value = value32; 306 break; 307 308 case ACPI_WRITE: 309 310 status = acpi_hw_write_port((acpi_io_address)address, 311 (u32)*value, bit_width); 312 break; 313 314 default: 315 316 status = AE_BAD_PARAMETER; 317 break; 318 } 319 320 return_ACPI_STATUS(status); 321 } 322 323 #ifdef ACPI_PCI_CONFIGURED 324 /******************************************************************************* 325 * 326 * FUNCTION: acpi_ex_pci_config_space_handler 327 * 328 * PARAMETERS: function - Read or Write operation 329 * address - Where in the space to read or write 330 * bit_width - Field width in bits (8, 16, or 32) 331 * value - Pointer to in or out value 332 * handler_context - Pointer to Handler's context 333 * region_context - Pointer to context specific to the 334 * accessed region 335 * 336 * RETURN: Status 337 * 338 * DESCRIPTION: Handler for the PCI Config address space (Op Region) 339 * 340 ******************************************************************************/ 341 342 acpi_status 343 acpi_ex_pci_config_space_handler(u32 function, 344 acpi_physical_address address, 345 u32 bit_width, 346 u64 *value, 347 void *handler_context, void *region_context) 348 { 349 acpi_status status = AE_OK; 350 struct acpi_pci_id *pci_id; 351 u16 pci_register; 352 353 ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); 354 355 /* 356 * The arguments to acpi_os(Read|Write)pci_configuration are: 357 * 358 * pci_segment is the PCI bus segment range 0-31 359 * pci_bus is the PCI bus number range 0-255 360 * pci_device is the PCI device number range 0-31 361 * pci_function is the PCI device function number 362 * pci_register is the Config space register range 0-255 bytes 363 * 364 * value - input value for write, output address for read 365 * 366 */ 367 pci_id = (struct acpi_pci_id *)region_context; 368 pci_register = (u16) (u32) address; 369 370 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 371 "Pci-Config %u (%u) Seg(%04x) Bus(%04x) " 372 "Dev(%04x) Func(%04x) Reg(%04x)\n", 373 function, bit_width, pci_id->segment, pci_id->bus, 374 pci_id->device, pci_id->function, pci_register)); 375 376 switch (function) { 377 case ACPI_READ: 378 379 *value = 0; 380 status = 381 acpi_os_read_pci_configuration(pci_id, pci_register, value, 382 bit_width); 383 break; 384 385 case ACPI_WRITE: 386 387 status = 388 acpi_os_write_pci_configuration(pci_id, pci_register, 389 *value, bit_width); 390 break; 391 392 default: 393 394 status = AE_BAD_PARAMETER; 395 break; 396 } 397 398 return_ACPI_STATUS(status); 399 } 400 #endif 401 402 /******************************************************************************* 403 * 404 * FUNCTION: acpi_ex_cmos_space_handler 405 * 406 * PARAMETERS: function - Read or Write operation 407 * address - Where in the space to read or write 408 * bit_width - Field width in bits (8, 16, or 32) 409 * value - Pointer to in or out value 410 * handler_context - Pointer to Handler's context 411 * region_context - Pointer to context specific to the 412 * accessed region 413 * 414 * RETURN: Status 415 * 416 * DESCRIPTION: Handler for the CMOS address space (Op Region) 417 * 418 ******************************************************************************/ 419 420 acpi_status 421 acpi_ex_cmos_space_handler(u32 function, 422 acpi_physical_address address, 423 u32 bit_width, 424 u64 *value, 425 void *handler_context, void *region_context) 426 { 427 acpi_status status = AE_OK; 428 429 ACPI_FUNCTION_TRACE(ex_cmos_space_handler); 430 431 return_ACPI_STATUS(status); 432 } 433 434 #ifdef ACPI_PCI_CONFIGURED 435 /******************************************************************************* 436 * 437 * FUNCTION: acpi_ex_pci_bar_space_handler 438 * 439 * PARAMETERS: function - Read or Write operation 440 * address - Where in the space to read or write 441 * bit_width - Field width in bits (8, 16, or 32) 442 * value - Pointer to in or out value 443 * handler_context - Pointer to Handler's context 444 * region_context - Pointer to context specific to the 445 * accessed region 446 * 447 * RETURN: Status 448 * 449 * DESCRIPTION: Handler for the PCI bar_target address space (Op Region) 450 * 451 ******************************************************************************/ 452 453 acpi_status 454 acpi_ex_pci_bar_space_handler(u32 function, 455 acpi_physical_address address, 456 u32 bit_width, 457 u64 *value, 458 void *handler_context, void *region_context) 459 { 460 acpi_status status = AE_OK; 461 462 ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler); 463 464 return_ACPI_STATUS(status); 465 } 466 #endif 467 468 /******************************************************************************* 469 * 470 * FUNCTION: acpi_ex_data_table_space_handler 471 * 472 * PARAMETERS: function - Read or Write operation 473 * address - Where in the space to read or write 474 * bit_width - Field width in bits (8, 16, or 32) 475 * value - Pointer to in or out value 476 * handler_context - Pointer to Handler's context 477 * region_context - Pointer to context specific to the 478 * accessed region 479 * 480 * RETURN: Status 481 * 482 * DESCRIPTION: Handler for the Data Table address space (Op Region) 483 * 484 ******************************************************************************/ 485 486 acpi_status 487 acpi_ex_data_table_space_handler(u32 function, 488 acpi_physical_address address, 489 u32 bit_width, 490 u64 *value, 491 void *handler_context, void *region_context) 492 { 493 struct acpi_data_table_mapping *mapping; 494 char *pointer; 495 496 ACPI_FUNCTION_TRACE(ex_data_table_space_handler); 497 498 mapping = (struct acpi_data_table_mapping *) region_context; 499 pointer = ACPI_CAST_PTR(char, mapping->pointer) + 500 (address - ACPI_PTR_TO_PHYSADDR(mapping->pointer)); 501 502 /* 503 * Perform the memory read or write. The bit_width was already 504 * validated. 505 */ 506 switch (function) { 507 case ACPI_READ: 508 509 memcpy(ACPI_CAST_PTR(char, value), pointer, 510 ACPI_DIV_8(bit_width)); 511 break; 512 513 case ACPI_WRITE: 514 515 memcpy(pointer, ACPI_CAST_PTR(char, value), 516 ACPI_DIV_8(bit_width)); 517 break; 518 519 default: 520 521 return_ACPI_STATUS(AE_BAD_PARAMETER); 522 } 523 524 return_ACPI_STATUS(AE_OK); 525 } 526