1 /****************************************************************************** 2 * 3 * Module Name: exregion - ACPI default op_region (address space) handlers 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 = 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 = acpi_os_map_memory((acpi_physical_address) address, map_length); 181 if (!mem_info->mapped_logical_address) { 182 ACPI_ERROR((AE_INFO, 183 "Could not map memory at 0x%8.8X%8.8X, size %u", 184 ACPI_FORMAT_NATIVE_UINT(address), 185 (u32) map_length)); 186 mem_info->mapped_length = 0; 187 return_ACPI_STATUS(AE_NO_MEMORY); 188 } 189 190 /* Save the physical address and mapping size */ 191 192 mem_info->mapped_physical_address = address; 193 mem_info->mapped_length = map_length; 194 } 195 196 /* 197 * Generate a logical pointer corresponding to the address we want to 198 * access 199 */ 200 logical_addr_ptr = mem_info->mapped_logical_address + 201 ((u64) address - (u64) mem_info->mapped_physical_address); 202 203 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 204 "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", 205 bit_width, function, 206 ACPI_FORMAT_NATIVE_UINT(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, 322 ACPI_FORMAT_NATIVE_UINT(address))); 323 324 /* Decode the function parameter */ 325 326 switch (function) { 327 case ACPI_READ: 328 329 status = acpi_hw_read_port((acpi_io_address) address, 330 &value32, bit_width); 331 *value = value32; 332 break; 333 334 case ACPI_WRITE: 335 336 status = acpi_hw_write_port((acpi_io_address) address, 337 (u32) * value, bit_width); 338 break; 339 340 default: 341 342 status = AE_BAD_PARAMETER; 343 break; 344 } 345 346 return_ACPI_STATUS(status); 347 } 348 349 /******************************************************************************* 350 * 351 * FUNCTION: acpi_ex_pci_config_space_handler 352 * 353 * PARAMETERS: function - Read or Write operation 354 * address - Where in the space to read or write 355 * bit_width - Field width in bits (8, 16, or 32) 356 * value - Pointer to in or out value 357 * handler_context - Pointer to Handler's context 358 * region_context - Pointer to context specific to the 359 * accessed region 360 * 361 * RETURN: Status 362 * 363 * DESCRIPTION: Handler for the PCI Config address space (Op Region) 364 * 365 ******************************************************************************/ 366 367 acpi_status 368 acpi_ex_pci_config_space_handler(u32 function, 369 acpi_physical_address address, 370 u32 bit_width, 371 u64 *value, 372 void *handler_context, void *region_context) 373 { 374 acpi_status status = AE_OK; 375 struct acpi_pci_id *pci_id; 376 u16 pci_register; 377 378 ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); 379 380 /* 381 * The arguments to acpi_os(Read|Write)pci_configuration are: 382 * 383 * pci_segment is the PCI bus segment range 0-31 384 * pci_bus is the PCI bus number range 0-255 385 * pci_device is the PCI device number range 0-31 386 * pci_function is the PCI device function number 387 * pci_register is the Config space register range 0-255 bytes 388 * 389 * value - input value for write, output address for read 390 * 391 */ 392 pci_id = (struct acpi_pci_id *)region_context; 393 pci_register = (u16) (u32) address; 394 395 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 396 "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", 397 function, bit_width, pci_id->segment, pci_id->bus, 398 pci_id->device, pci_id->function, pci_register)); 399 400 switch (function) { 401 case ACPI_READ: 402 403 *value = 0; 404 status = acpi_os_read_pci_configuration(pci_id, pci_register, 405 value, bit_width); 406 break; 407 408 case ACPI_WRITE: 409 410 status = acpi_os_write_pci_configuration(pci_id, pci_register, 411 *value, bit_width); 412 break; 413 414 default: 415 416 status = AE_BAD_PARAMETER; 417 break; 418 } 419 420 return_ACPI_STATUS(status); 421 } 422 423 /******************************************************************************* 424 * 425 * FUNCTION: acpi_ex_cmos_space_handler 426 * 427 * PARAMETERS: function - Read or Write operation 428 * address - Where in the space to read or write 429 * bit_width - Field width in bits (8, 16, or 32) 430 * value - Pointer to in or out value 431 * handler_context - Pointer to Handler's context 432 * region_context - Pointer to context specific to the 433 * accessed region 434 * 435 * RETURN: Status 436 * 437 * DESCRIPTION: Handler for the CMOS address space (Op Region) 438 * 439 ******************************************************************************/ 440 441 acpi_status 442 acpi_ex_cmos_space_handler(u32 function, 443 acpi_physical_address address, 444 u32 bit_width, 445 u64 *value, 446 void *handler_context, void *region_context) 447 { 448 acpi_status status = AE_OK; 449 450 ACPI_FUNCTION_TRACE(ex_cmos_space_handler); 451 452 return_ACPI_STATUS(status); 453 } 454 455 /******************************************************************************* 456 * 457 * FUNCTION: acpi_ex_pci_bar_space_handler 458 * 459 * PARAMETERS: function - Read or Write operation 460 * address - Where in the space to read or write 461 * bit_width - Field width in bits (8, 16, or 32) 462 * value - Pointer to in or out value 463 * handler_context - Pointer to Handler's context 464 * region_context - Pointer to context specific to the 465 * accessed region 466 * 467 * RETURN: Status 468 * 469 * DESCRIPTION: Handler for the PCI bar_target address space (Op Region) 470 * 471 ******************************************************************************/ 472 473 acpi_status 474 acpi_ex_pci_bar_space_handler(u32 function, 475 acpi_physical_address address, 476 u32 bit_width, 477 u64 *value, 478 void *handler_context, void *region_context) 479 { 480 acpi_status status = AE_OK; 481 482 ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler); 483 484 return_ACPI_STATUS(status); 485 } 486 487 /******************************************************************************* 488 * 489 * FUNCTION: acpi_ex_data_table_space_handler 490 * 491 * PARAMETERS: function - Read or Write operation 492 * address - Where in the space to read or write 493 * bit_width - Field width in bits (8, 16, or 32) 494 * value - Pointer to in or out value 495 * handler_context - Pointer to Handler's context 496 * region_context - Pointer to context specific to the 497 * accessed region 498 * 499 * RETURN: Status 500 * 501 * DESCRIPTION: Handler for the Data Table address space (Op Region) 502 * 503 ******************************************************************************/ 504 505 acpi_status 506 acpi_ex_data_table_space_handler(u32 function, 507 acpi_physical_address address, 508 u32 bit_width, 509 u64 *value, 510 void *handler_context, void *region_context) 511 { 512 ACPI_FUNCTION_TRACE(ex_data_table_space_handler); 513 514 /* 515 * Perform the memory read or write. The bit_width was already 516 * validated. 517 */ 518 switch (function) { 519 case ACPI_READ: 520 521 ACPI_MEMCPY(ACPI_CAST_PTR(char, value), 522 ACPI_PHYSADDR_TO_PTR(address), 523 ACPI_DIV_8(bit_width)); 524 break; 525 526 case ACPI_WRITE: 527 528 ACPI_MEMCPY(ACPI_PHYSADDR_TO_PTR(address), 529 ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width)); 530 break; 531 532 default: 533 534 return_ACPI_STATUS(AE_BAD_PARAMETER); 535 } 536 537 return_ACPI_STATUS(AE_OK); 538 } 539