1 /****************************************************************************** 2 * 3 * Module Name: exregion - ACPI default op_region (address space) handlers 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <acpi/acpi.h> 45 #include "accommon.h" 46 #include "acinterp.h" 47 48 #define _COMPONENT ACPI_EXECUTER 49 ACPI_MODULE_NAME("exregion") 50 51 /******************************************************************************* 52 * 53 * FUNCTION: acpi_ex_system_memory_space_handler 54 * 55 * PARAMETERS: function - Read or Write operation 56 * address - Where in the space to read or write 57 * bit_width - Field width in bits (8, 16, or 32) 58 * value - Pointer to in or out value 59 * handler_context - Pointer to Handler's context 60 * region_context - Pointer to context specific to the 61 * accessed region 62 * 63 * RETURN: Status 64 * 65 * DESCRIPTION: Handler for the System Memory address space (Op Region) 66 * 67 ******************************************************************************/ 68 acpi_status 69 acpi_ex_system_memory_space_handler(u32 function, 70 acpi_physical_address address, 71 u32 bit_width, 72 u64 *value, 73 void *handler_context, void *region_context) 74 { 75 acpi_status status = AE_OK; 76 void *logical_addr_ptr = NULL; 77 struct acpi_mem_space_context *mem_info = region_context; 78 u32 length; 79 acpi_size map_length; 80 acpi_size page_boundary_map_length; 81 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED 82 u32 remainder; 83 #endif 84 85 ACPI_FUNCTION_TRACE(ex_system_memory_space_handler); 86 87 /* Validate and translate the bit width */ 88 89 switch (bit_width) { 90 case 8: 91 92 length = 1; 93 break; 94 95 case 16: 96 97 length = 2; 98 break; 99 100 case 32: 101 102 length = 4; 103 break; 104 105 case 64: 106 107 length = 8; 108 break; 109 110 default: 111 112 ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u", 113 bit_width)); 114 return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 115 } 116 117 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED 118 /* 119 * Hardware does not support non-aligned data transfers, we must verify 120 * the request. 121 */ 122 (void)acpi_ut_short_divide((u64) address, length, NULL, &remainder); 123 if (remainder != 0) { 124 return_ACPI_STATUS(AE_AML_ALIGNMENT); 125 } 126 #endif 127 128 /* 129 * Does the request fit into the cached memory mapping? 130 * Is 1) Address below the current mapping? OR 131 * 2) Address beyond the current mapping? 132 */ 133 if ((address < mem_info->mapped_physical_address) || 134 (((u64) address + length) > ((u64) 135 mem_info->mapped_physical_address + 136 mem_info->mapped_length))) { 137 /* 138 * The request cannot be resolved by the current memory mapping; 139 * Delete the existing mapping and create a new one. 140 */ 141 if (mem_info->mapped_length) { 142 143 /* Valid mapping, delete it */ 144 145 acpi_os_unmap_memory(mem_info->mapped_logical_address, 146 mem_info->mapped_length); 147 } 148 149 /* 150 * October 2009: Attempt to map from the requested address to the 151 * end of the region. However, we will never map more than one 152 * page, nor will we cross a page boundary. 153 */ 154 map_length = (acpi_size) 155 ((mem_info->address + mem_info->length) - address); 156 157 /* 158 * If mapping the entire remaining portion of the region will cross 159 * a page boundary, just map up to the page boundary, do not cross. 160 * On some systems, crossing a page boundary while mapping regions 161 * can cause warnings if the pages have different attributes 162 * due to resource management. 163 * 164 * This has the added benefit of constraining a single mapping to 165 * one page, which is similar to the original code that used a 4k 166 * maximum window. 167 */ 168 page_boundary_map_length = (acpi_size) 169 (ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address); 170 if (page_boundary_map_length == 0) { 171 page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE; 172 } 173 174 if (map_length > page_boundary_map_length) { 175 map_length = page_boundary_map_length; 176 } 177 178 /* Create a new mapping starting at the address given */ 179 180 mem_info->mapped_logical_address = 181 acpi_os_map_memory(address, map_length); 182 if (!mem_info->mapped_logical_address) { 183 ACPI_ERROR((AE_INFO, 184 "Could not map memory at 0x%8.8X%8.8X, size %u", 185 ACPI_FORMAT_UINT64(address), 186 (u32)map_length)); 187 mem_info->mapped_length = 0; 188 return_ACPI_STATUS(AE_NO_MEMORY); 189 } 190 191 /* Save the physical address and mapping size */ 192 193 mem_info->mapped_physical_address = address; 194 mem_info->mapped_length = map_length; 195 } 196 197 /* 198 * Generate a logical pointer corresponding to the address we want to 199 * access 200 */ 201 logical_addr_ptr = mem_info->mapped_logical_address + 202 ((u64) address - (u64) mem_info->mapped_physical_address); 203 204 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 205 "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", 206 bit_width, function, ACPI_FORMAT_UINT64(address))); 207 208 /* 209 * Perform the memory read or write 210 * 211 * Note: For machines that do not support non-aligned transfers, the target 212 * address was checked for alignment above. We do not attempt to break the 213 * transfer up into smaller (byte-size) chunks because the AML specifically 214 * asked for a transfer width that the hardware may require. 215 */ 216 switch (function) { 217 case ACPI_READ: 218 219 *value = 0; 220 switch (bit_width) { 221 case 8: 222 223 *value = (u64)ACPI_GET8(logical_addr_ptr); 224 break; 225 226 case 16: 227 228 *value = (u64)ACPI_GET16(logical_addr_ptr); 229 break; 230 231 case 32: 232 233 *value = (u64)ACPI_GET32(logical_addr_ptr); 234 break; 235 236 case 64: 237 238 *value = (u64)ACPI_GET64(logical_addr_ptr); 239 break; 240 241 default: 242 243 /* bit_width was already validated */ 244 245 break; 246 } 247 break; 248 249 case ACPI_WRITE: 250 251 switch (bit_width) { 252 case 8: 253 254 ACPI_SET8(logical_addr_ptr, *value); 255 break; 256 257 case 16: 258 259 ACPI_SET16(logical_addr_ptr, *value); 260 break; 261 262 case 32: 263 264 ACPI_SET32(logical_addr_ptr, *value); 265 break; 266 267 case 64: 268 269 ACPI_SET64(logical_addr_ptr, *value); 270 break; 271 272 default: 273 274 /* bit_width was already validated */ 275 276 break; 277 } 278 break; 279 280 default: 281 282 status = AE_BAD_PARAMETER; 283 break; 284 } 285 286 return_ACPI_STATUS(status); 287 } 288 289 /******************************************************************************* 290 * 291 * FUNCTION: acpi_ex_system_io_space_handler 292 * 293 * PARAMETERS: function - Read or Write operation 294 * address - Where in the space to read or write 295 * bit_width - Field width in bits (8, 16, or 32) 296 * value - Pointer to in or out value 297 * handler_context - Pointer to Handler's context 298 * region_context - Pointer to context specific to the 299 * accessed region 300 * 301 * RETURN: Status 302 * 303 * DESCRIPTION: Handler for the System IO address space (Op Region) 304 * 305 ******************************************************************************/ 306 307 acpi_status 308 acpi_ex_system_io_space_handler(u32 function, 309 acpi_physical_address address, 310 u32 bit_width, 311 u64 *value, 312 void *handler_context, void *region_context) 313 { 314 acpi_status status = AE_OK; 315 u32 value32; 316 317 ACPI_FUNCTION_TRACE(ex_system_io_space_handler); 318 319 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 320 "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n", 321 bit_width, function, ACPI_FORMAT_UINT64(address))); 322 323 /* Decode the function parameter */ 324 325 switch (function) { 326 case ACPI_READ: 327 328 status = acpi_hw_read_port((acpi_io_address) address, 329 &value32, bit_width); 330 *value = value32; 331 break; 332 333 case ACPI_WRITE: 334 335 status = acpi_hw_write_port((acpi_io_address) address, 336 (u32) * value, bit_width); 337 break; 338 339 default: 340 341 status = AE_BAD_PARAMETER; 342 break; 343 } 344 345 return_ACPI_STATUS(status); 346 } 347 348 /******************************************************************************* 349 * 350 * FUNCTION: acpi_ex_pci_config_space_handler 351 * 352 * PARAMETERS: function - Read or Write operation 353 * address - Where in the space to read or write 354 * bit_width - Field width in bits (8, 16, or 32) 355 * value - Pointer to in or out value 356 * handler_context - Pointer to Handler's context 357 * region_context - Pointer to context specific to the 358 * accessed region 359 * 360 * RETURN: Status 361 * 362 * DESCRIPTION: Handler for the PCI Config address space (Op Region) 363 * 364 ******************************************************************************/ 365 366 acpi_status 367 acpi_ex_pci_config_space_handler(u32 function, 368 acpi_physical_address address, 369 u32 bit_width, 370 u64 *value, 371 void *handler_context, void *region_context) 372 { 373 acpi_status status = AE_OK; 374 struct acpi_pci_id *pci_id; 375 u16 pci_register; 376 377 ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); 378 379 /* 380 * The arguments to acpi_os(Read|Write)pci_configuration are: 381 * 382 * pci_segment is the PCI bus segment range 0-31 383 * pci_bus is the PCI bus number range 0-255 384 * pci_device is the PCI device number range 0-31 385 * pci_function is the PCI device function number 386 * pci_register is the Config space register range 0-255 bytes 387 * 388 * value - input value for write, output address for read 389 * 390 */ 391 pci_id = (struct acpi_pci_id *)region_context; 392 pci_register = (u16) (u32) address; 393 394 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 395 "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", 396 function, bit_width, pci_id->segment, pci_id->bus, 397 pci_id->device, pci_id->function, pci_register)); 398 399 switch (function) { 400 case ACPI_READ: 401 402 *value = 0; 403 status = acpi_os_read_pci_configuration(pci_id, pci_register, 404 value, bit_width); 405 break; 406 407 case ACPI_WRITE: 408 409 status = acpi_os_write_pci_configuration(pci_id, pci_register, 410 *value, bit_width); 411 break; 412 413 default: 414 415 status = AE_BAD_PARAMETER; 416 break; 417 } 418 419 return_ACPI_STATUS(status); 420 } 421 422 /******************************************************************************* 423 * 424 * FUNCTION: acpi_ex_cmos_space_handler 425 * 426 * PARAMETERS: function - Read or Write operation 427 * address - Where in the space to read or write 428 * bit_width - Field width in bits (8, 16, or 32) 429 * value - Pointer to in or out value 430 * handler_context - Pointer to Handler's context 431 * region_context - Pointer to context specific to the 432 * accessed region 433 * 434 * RETURN: Status 435 * 436 * DESCRIPTION: Handler for the CMOS address space (Op Region) 437 * 438 ******************************************************************************/ 439 440 acpi_status 441 acpi_ex_cmos_space_handler(u32 function, 442 acpi_physical_address address, 443 u32 bit_width, 444 u64 *value, 445 void *handler_context, void *region_context) 446 { 447 acpi_status status = AE_OK; 448 449 ACPI_FUNCTION_TRACE(ex_cmos_space_handler); 450 451 return_ACPI_STATUS(status); 452 } 453 454 /******************************************************************************* 455 * 456 * FUNCTION: acpi_ex_pci_bar_space_handler 457 * 458 * PARAMETERS: function - Read or Write operation 459 * address - Where in the space to read or write 460 * bit_width - Field width in bits (8, 16, or 32) 461 * value - Pointer to in or out value 462 * handler_context - Pointer to Handler's context 463 * region_context - Pointer to context specific to the 464 * accessed region 465 * 466 * RETURN: Status 467 * 468 * DESCRIPTION: Handler for the PCI bar_target address space (Op Region) 469 * 470 ******************************************************************************/ 471 472 acpi_status 473 acpi_ex_pci_bar_space_handler(u32 function, 474 acpi_physical_address address, 475 u32 bit_width, 476 u64 *value, 477 void *handler_context, void *region_context) 478 { 479 acpi_status status = AE_OK; 480 481 ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler); 482 483 return_ACPI_STATUS(status); 484 } 485 486 /******************************************************************************* 487 * 488 * FUNCTION: acpi_ex_data_table_space_handler 489 * 490 * PARAMETERS: function - Read or Write operation 491 * address - Where in the space to read or write 492 * bit_width - Field width in bits (8, 16, or 32) 493 * value - Pointer to in or out value 494 * handler_context - Pointer to Handler's context 495 * region_context - Pointer to context specific to the 496 * accessed region 497 * 498 * RETURN: Status 499 * 500 * DESCRIPTION: Handler for the Data Table address space (Op Region) 501 * 502 ******************************************************************************/ 503 504 acpi_status 505 acpi_ex_data_table_space_handler(u32 function, 506 acpi_physical_address address, 507 u32 bit_width, 508 u64 *value, 509 void *handler_context, void *region_context) 510 { 511 ACPI_FUNCTION_TRACE(ex_data_table_space_handler); 512 513 /* 514 * Perform the memory read or write. The bit_width was already 515 * validated. 516 */ 517 switch (function) { 518 case ACPI_READ: 519 520 memcpy(ACPI_CAST_PTR(char, value), 521 ACPI_PHYSADDR_TO_PTR(address), ACPI_DIV_8(bit_width)); 522 break; 523 524 case ACPI_WRITE: 525 526 memcpy(ACPI_PHYSADDR_TO_PTR(address), 527 ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width)); 528 break; 529 530 default: 531 532 return_ACPI_STATUS(AE_BAD_PARAMETER); 533 } 534 535 return_ACPI_STATUS(AE_OK); 536 } 537