1 /****************************************************************************** 2 * 3 * Module Name: exregion - ACPI default op_region (address space) handlers 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2012, 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 length = 1; 92 break; 93 94 case 16: 95 length = 2; 96 break; 97 98 case 32: 99 length = 4; 100 break; 101 102 case 64: 103 length = 8; 104 break; 105 106 default: 107 ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u", 108 bit_width)); 109 return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 110 } 111 112 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED 113 /* 114 * Hardware does not support non-aligned data transfers, we must verify 115 * the request. 116 */ 117 (void)acpi_ut_short_divide((u64) address, length, NULL, &remainder); 118 if (remainder != 0) { 119 return_ACPI_STATUS(AE_AML_ALIGNMENT); 120 } 121 #endif 122 123 /* 124 * Does the request fit into the cached memory mapping? 125 * Is 1) Address below the current mapping? OR 126 * 2) Address beyond the current mapping? 127 */ 128 if ((address < mem_info->mapped_physical_address) || 129 (((u64) address + length) > ((u64) 130 mem_info->mapped_physical_address + 131 mem_info->mapped_length))) { 132 /* 133 * The request cannot be resolved by the current memory mapping; 134 * Delete the existing mapping and create a new one. 135 */ 136 if (mem_info->mapped_length) { 137 138 /* Valid mapping, delete it */ 139 140 acpi_os_unmap_memory(mem_info->mapped_logical_address, 141 mem_info->mapped_length); 142 } 143 144 /* 145 * October 2009: Attempt to map from the requested address to the 146 * end of the region. However, we will never map more than one 147 * page, nor will we cross a page boundary. 148 */ 149 map_length = (acpi_size) 150 ((mem_info->address + mem_info->length) - address); 151 152 /* 153 * If mapping the entire remaining portion of the region will cross 154 * a page boundary, just map up to the page boundary, do not cross. 155 * On some systems, crossing a page boundary while mapping regions 156 * can cause warnings if the pages have different attributes 157 * due to resource management. 158 * 159 * This has the added benefit of constraining a single mapping to 160 * one page, which is similar to the original code that used a 4k 161 * maximum window. 162 */ 163 page_boundary_map_length = 164 ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address; 165 if (page_boundary_map_length == 0) { 166 page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE; 167 } 168 169 if (map_length > page_boundary_map_length) { 170 map_length = page_boundary_map_length; 171 } 172 173 /* Create a new mapping starting at the address given */ 174 175 mem_info->mapped_logical_address = acpi_os_map_memory((acpi_physical_address) address, map_length); 176 if (!mem_info->mapped_logical_address) { 177 ACPI_ERROR((AE_INFO, 178 "Could not map memory at 0x%8.8X%8.8X, size %u", 179 ACPI_FORMAT_NATIVE_UINT(address), 180 (u32) map_length)); 181 mem_info->mapped_length = 0; 182 return_ACPI_STATUS(AE_NO_MEMORY); 183 } 184 185 /* Save the physical address and mapping size */ 186 187 mem_info->mapped_physical_address = address; 188 mem_info->mapped_length = map_length; 189 } 190 191 /* 192 * Generate a logical pointer corresponding to the address we want to 193 * access 194 */ 195 logical_addr_ptr = mem_info->mapped_logical_address + 196 ((u64) address - (u64) mem_info->mapped_physical_address); 197 198 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 199 "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", 200 bit_width, function, 201 ACPI_FORMAT_NATIVE_UINT(address))); 202 203 /* 204 * Perform the memory read or write 205 * 206 * Note: For machines that do not support non-aligned transfers, the target 207 * address was checked for alignment above. We do not attempt to break the 208 * transfer up into smaller (byte-size) chunks because the AML specifically 209 * asked for a transfer width that the hardware may require. 210 */ 211 switch (function) { 212 case ACPI_READ: 213 214 *value = 0; 215 switch (bit_width) { 216 case 8: 217 *value = (u64) ACPI_GET8(logical_addr_ptr); 218 break; 219 220 case 16: 221 *value = (u64) ACPI_GET16(logical_addr_ptr); 222 break; 223 224 case 32: 225 *value = (u64) ACPI_GET32(logical_addr_ptr); 226 break; 227 228 case 64: 229 *value = (u64) ACPI_GET64(logical_addr_ptr); 230 break; 231 232 default: 233 /* bit_width was already validated */ 234 break; 235 } 236 break; 237 238 case ACPI_WRITE: 239 240 switch (bit_width) { 241 case 8: 242 ACPI_SET8(logical_addr_ptr, *value); 243 break; 244 245 case 16: 246 ACPI_SET16(logical_addr_ptr, *value); 247 break; 248 249 case 32: 250 ACPI_SET32(logical_addr_ptr, *value); 251 break; 252 253 case 64: 254 ACPI_SET64(logical_addr_ptr, *value); 255 break; 256 257 default: 258 /* bit_width was already validated */ 259 break; 260 } 261 break; 262 263 default: 264 status = AE_BAD_PARAMETER; 265 break; 266 } 267 268 return_ACPI_STATUS(status); 269 } 270 271 /******************************************************************************* 272 * 273 * FUNCTION: acpi_ex_system_io_space_handler 274 * 275 * PARAMETERS: function - Read or Write operation 276 * address - Where in the space to read or write 277 * bit_width - Field width in bits (8, 16, or 32) 278 * value - Pointer to in or out value 279 * handler_context - Pointer to Handler's context 280 * region_context - Pointer to context specific to the 281 * accessed region 282 * 283 * RETURN: Status 284 * 285 * DESCRIPTION: Handler for the System IO address space (Op Region) 286 * 287 ******************************************************************************/ 288 289 acpi_status 290 acpi_ex_system_io_space_handler(u32 function, 291 acpi_physical_address address, 292 u32 bit_width, 293 u64 *value, 294 void *handler_context, void *region_context) 295 { 296 acpi_status status = AE_OK; 297 u32 value32; 298 299 ACPI_FUNCTION_TRACE(ex_system_io_space_handler); 300 301 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 302 "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n", 303 bit_width, function, 304 ACPI_FORMAT_NATIVE_UINT(address))); 305 306 /* Decode the function parameter */ 307 308 switch (function) { 309 case ACPI_READ: 310 311 status = acpi_hw_read_port((acpi_io_address) address, 312 &value32, bit_width); 313 *value = value32; 314 break; 315 316 case ACPI_WRITE: 317 318 status = acpi_hw_write_port((acpi_io_address) address, 319 (u32) * value, bit_width); 320 break; 321 322 default: 323 status = AE_BAD_PARAMETER; 324 break; 325 } 326 327 return_ACPI_STATUS(status); 328 } 329 330 /******************************************************************************* 331 * 332 * FUNCTION: acpi_ex_pci_config_space_handler 333 * 334 * PARAMETERS: function - Read or Write operation 335 * address - Where in the space to read or write 336 * bit_width - Field width in bits (8, 16, or 32) 337 * value - Pointer to in or out value 338 * handler_context - Pointer to Handler's context 339 * region_context - Pointer to context specific to the 340 * accessed region 341 * 342 * RETURN: Status 343 * 344 * DESCRIPTION: Handler for the PCI Config address space (Op Region) 345 * 346 ******************************************************************************/ 347 348 acpi_status 349 acpi_ex_pci_config_space_handler(u32 function, 350 acpi_physical_address address, 351 u32 bit_width, 352 u64 *value, 353 void *handler_context, void *region_context) 354 { 355 acpi_status status = AE_OK; 356 struct acpi_pci_id *pci_id; 357 u16 pci_register; 358 359 ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); 360 361 /* 362 * The arguments to acpi_os(Read|Write)pci_configuration are: 363 * 364 * pci_segment is the PCI bus segment range 0-31 365 * pci_bus is the PCI bus number range 0-255 366 * pci_device is the PCI device number range 0-31 367 * pci_function is the PCI device function number 368 * pci_register is the Config space register range 0-255 bytes 369 * 370 * value - input value for write, output address for read 371 * 372 */ 373 pci_id = (struct acpi_pci_id *)region_context; 374 pci_register = (u16) (u32) address; 375 376 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 377 "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", 378 function, bit_width, pci_id->segment, pci_id->bus, 379 pci_id->device, pci_id->function, pci_register)); 380 381 switch (function) { 382 case ACPI_READ: 383 384 status = acpi_os_read_pci_configuration(pci_id, pci_register, 385 value, bit_width); 386 break; 387 388 case ACPI_WRITE: 389 390 status = acpi_os_write_pci_configuration(pci_id, pci_register, 391 *value, bit_width); 392 break; 393 394 default: 395 396 status = AE_BAD_PARAMETER; 397 break; 398 } 399 400 return_ACPI_STATUS(status); 401 } 402 403 /******************************************************************************* 404 * 405 * FUNCTION: acpi_ex_cmos_space_handler 406 * 407 * PARAMETERS: function - Read or Write operation 408 * address - Where in the space to read or write 409 * bit_width - Field width in bits (8, 16, or 32) 410 * value - Pointer to in or out value 411 * handler_context - Pointer to Handler's context 412 * region_context - Pointer to context specific to the 413 * accessed region 414 * 415 * RETURN: Status 416 * 417 * DESCRIPTION: Handler for the CMOS address space (Op Region) 418 * 419 ******************************************************************************/ 420 421 acpi_status 422 acpi_ex_cmos_space_handler(u32 function, 423 acpi_physical_address address, 424 u32 bit_width, 425 u64 *value, 426 void *handler_context, void *region_context) 427 { 428 acpi_status status = AE_OK; 429 430 ACPI_FUNCTION_TRACE(ex_cmos_space_handler); 431 432 return_ACPI_STATUS(status); 433 } 434 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 467 /******************************************************************************* 468 * 469 * FUNCTION: acpi_ex_data_table_space_handler 470 * 471 * PARAMETERS: function - Read or Write operation 472 * address - Where in the space to read or write 473 * bit_width - Field width in bits (8, 16, or 32) 474 * value - Pointer to in or out value 475 * handler_context - Pointer to Handler's context 476 * region_context - Pointer to context specific to the 477 * accessed region 478 * 479 * RETURN: Status 480 * 481 * DESCRIPTION: Handler for the Data Table address space (Op Region) 482 * 483 ******************************************************************************/ 484 485 acpi_status 486 acpi_ex_data_table_space_handler(u32 function, 487 acpi_physical_address address, 488 u32 bit_width, 489 u64 *value, 490 void *handler_context, void *region_context) 491 { 492 ACPI_FUNCTION_TRACE(ex_data_table_space_handler); 493 494 /* 495 * Perform the memory read or write. The bit_width was already 496 * validated. 497 */ 498 switch (function) { 499 case ACPI_READ: 500 501 ACPI_MEMCPY(ACPI_CAST_PTR(char, value), 502 ACPI_PHYSADDR_TO_PTR(address), 503 ACPI_DIV_8(bit_width)); 504 break; 505 506 case ACPI_WRITE: 507 508 ACPI_MEMCPY(ACPI_PHYSADDR_TO_PTR(address), 509 ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width)); 510 break; 511 512 default: 513 514 return_ACPI_STATUS(AE_BAD_PARAMETER); 515 } 516 517 return_ACPI_STATUS(AE_OK); 518 } 519