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 * Attempt to map from the requested address to the end of the region. 146 * However, we will never map more than one page, nor will we cross 147 * 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 page_boundary_map_length = 160 ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address; 161 162 if (!page_boundary_map_length) { 163 page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE; 164 } 165 166 if (map_length > page_boundary_map_length) { 167 map_length = page_boundary_map_length; 168 } 169 170 /* Create a new mapping starting at the address given */ 171 172 mem_info->mapped_logical_address = acpi_os_map_memory((acpi_physical_address) address, map_length); 173 if (!mem_info->mapped_logical_address) { 174 ACPI_ERROR((AE_INFO, 175 "Could not map memory at 0x%8.8X%8.8X, size %u", 176 ACPI_FORMAT_NATIVE_UINT(address), 177 (u32) map_length)); 178 mem_info->mapped_length = 0; 179 return_ACPI_STATUS(AE_NO_MEMORY); 180 } 181 182 /* Save the physical address and mapping size */ 183 184 mem_info->mapped_physical_address = address; 185 mem_info->mapped_length = map_length; 186 } 187 188 /* 189 * Generate a logical pointer corresponding to the address we want to 190 * access 191 */ 192 logical_addr_ptr = mem_info->mapped_logical_address + 193 ((u64) address - (u64) mem_info->mapped_physical_address); 194 195 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 196 "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", 197 bit_width, function, 198 ACPI_FORMAT_NATIVE_UINT(address))); 199 200 /* 201 * Perform the memory read or write 202 * 203 * Note: For machines that do not support non-aligned transfers, the target 204 * address was checked for alignment above. We do not attempt to break the 205 * transfer up into smaller (byte-size) chunks because the AML specifically 206 * asked for a transfer width that the hardware may require. 207 */ 208 switch (function) { 209 case ACPI_READ: 210 211 *value = 0; 212 switch (bit_width) { 213 case 8: 214 *value = (u64) ACPI_GET8(logical_addr_ptr); 215 break; 216 217 case 16: 218 *value = (u64) ACPI_GET16(logical_addr_ptr); 219 break; 220 221 case 32: 222 *value = (u64) ACPI_GET32(logical_addr_ptr); 223 break; 224 225 case 64: 226 *value = (u64) ACPI_GET64(logical_addr_ptr); 227 break; 228 229 default: 230 /* bit_width was already validated */ 231 break; 232 } 233 break; 234 235 case ACPI_WRITE: 236 237 switch (bit_width) { 238 case 8: 239 ACPI_SET8(logical_addr_ptr) = (u8) * value; 240 break; 241 242 case 16: 243 ACPI_SET16(logical_addr_ptr) = (u16) * value; 244 break; 245 246 case 32: 247 ACPI_SET32(logical_addr_ptr) = (u32) * value; 248 break; 249 250 case 64: 251 ACPI_SET64(logical_addr_ptr) = (u64) * value; 252 break; 253 254 default: 255 /* bit_width was already validated */ 256 break; 257 } 258 break; 259 260 default: 261 status = AE_BAD_PARAMETER; 262 break; 263 } 264 265 return_ACPI_STATUS(status); 266 } 267 268 /******************************************************************************* 269 * 270 * FUNCTION: acpi_ex_system_io_space_handler 271 * 272 * PARAMETERS: function - Read or Write operation 273 * address - Where in the space to read or write 274 * bit_width - Field width in bits (8, 16, or 32) 275 * value - Pointer to in or out value 276 * handler_context - Pointer to Handler's context 277 * region_context - Pointer to context specific to the 278 * accessed region 279 * 280 * RETURN: Status 281 * 282 * DESCRIPTION: Handler for the System IO address space (Op Region) 283 * 284 ******************************************************************************/ 285 286 acpi_status 287 acpi_ex_system_io_space_handler(u32 function, 288 acpi_physical_address address, 289 u32 bit_width, 290 u64 *value, 291 void *handler_context, void *region_context) 292 { 293 acpi_status status = AE_OK; 294 u32 value32; 295 296 ACPI_FUNCTION_TRACE(ex_system_io_space_handler); 297 298 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 299 "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n", 300 bit_width, function, 301 ACPI_FORMAT_NATIVE_UINT(address))); 302 303 /* Decode the function parameter */ 304 305 switch (function) { 306 case ACPI_READ: 307 308 status = acpi_hw_read_port((acpi_io_address) address, 309 &value32, bit_width); 310 *value = value32; 311 break; 312 313 case ACPI_WRITE: 314 315 status = acpi_hw_write_port((acpi_io_address) address, 316 (u32) * value, bit_width); 317 break; 318 319 default: 320 status = AE_BAD_PARAMETER; 321 break; 322 } 323 324 return_ACPI_STATUS(status); 325 } 326 327 /******************************************************************************* 328 * 329 * FUNCTION: acpi_ex_pci_config_space_handler 330 * 331 * PARAMETERS: function - Read or Write operation 332 * address - Where in the space to read or write 333 * bit_width - Field width in bits (8, 16, or 32) 334 * value - Pointer to in or out value 335 * handler_context - Pointer to Handler's context 336 * region_context - Pointer to context specific to the 337 * accessed region 338 * 339 * RETURN: Status 340 * 341 * DESCRIPTION: Handler for the PCI Config address space (Op Region) 342 * 343 ******************************************************************************/ 344 345 acpi_status 346 acpi_ex_pci_config_space_handler(u32 function, 347 acpi_physical_address address, 348 u32 bit_width, 349 u64 *value, 350 void *handler_context, void *region_context) 351 { 352 acpi_status status = AE_OK; 353 struct acpi_pci_id *pci_id; 354 u16 pci_register; 355 356 ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); 357 358 /* 359 * The arguments to acpi_os(Read|Write)pci_configuration are: 360 * 361 * pci_segment is the PCI bus segment range 0-31 362 * pci_bus is the PCI bus number range 0-255 363 * pci_device is the PCI device number range 0-31 364 * pci_function is the PCI device function number 365 * pci_register is the Config space register range 0-255 bytes 366 * 367 * value - input value for write, output address for read 368 * 369 */ 370 pci_id = (struct acpi_pci_id *)region_context; 371 pci_register = (u16) (u32) address; 372 373 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 374 "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", 375 function, bit_width, pci_id->segment, pci_id->bus, 376 pci_id->device, pci_id->function, pci_register)); 377 378 switch (function) { 379 case ACPI_READ: 380 381 status = acpi_os_read_pci_configuration(pci_id, pci_register, 382 value, bit_width); 383 break; 384 385 case ACPI_WRITE: 386 387 status = acpi_os_write_pci_configuration(pci_id, pci_register, 388 *value, bit_width); 389 break; 390 391 default: 392 393 status = AE_BAD_PARAMETER; 394 break; 395 } 396 397 return_ACPI_STATUS(status); 398 } 399 400 /******************************************************************************* 401 * 402 * FUNCTION: acpi_ex_cmos_space_handler 403 * 404 * PARAMETERS: function - Read or Write operation 405 * address - Where in the space to read or write 406 * bit_width - Field width in bits (8, 16, or 32) 407 * value - Pointer to in or out value 408 * handler_context - Pointer to Handler's context 409 * region_context - Pointer to context specific to the 410 * accessed region 411 * 412 * RETURN: Status 413 * 414 * DESCRIPTION: Handler for the CMOS address space (Op Region) 415 * 416 ******************************************************************************/ 417 418 acpi_status 419 acpi_ex_cmos_space_handler(u32 function, 420 acpi_physical_address address, 421 u32 bit_width, 422 u64 *value, 423 void *handler_context, void *region_context) 424 { 425 acpi_status status = AE_OK; 426 427 ACPI_FUNCTION_TRACE(ex_cmos_space_handler); 428 429 return_ACPI_STATUS(status); 430 } 431 432 /******************************************************************************* 433 * 434 * FUNCTION: acpi_ex_pci_bar_space_handler 435 * 436 * PARAMETERS: function - Read or Write operation 437 * address - Where in the space to read or write 438 * bit_width - Field width in bits (8, 16, or 32) 439 * value - Pointer to in or out value 440 * handler_context - Pointer to Handler's context 441 * region_context - Pointer to context specific to the 442 * accessed region 443 * 444 * RETURN: Status 445 * 446 * DESCRIPTION: Handler for the PCI bar_target address space (Op Region) 447 * 448 ******************************************************************************/ 449 450 acpi_status 451 acpi_ex_pci_bar_space_handler(u32 function, 452 acpi_physical_address address, 453 u32 bit_width, 454 u64 *value, 455 void *handler_context, void *region_context) 456 { 457 acpi_status status = AE_OK; 458 459 ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler); 460 461 return_ACPI_STATUS(status); 462 } 463 464 /******************************************************************************* 465 * 466 * FUNCTION: acpi_ex_data_table_space_handler 467 * 468 * PARAMETERS: function - Read or Write operation 469 * address - Where in the space to read or write 470 * bit_width - Field width in bits (8, 16, or 32) 471 * value - Pointer to in or out value 472 * handler_context - Pointer to Handler's context 473 * region_context - Pointer to context specific to the 474 * accessed region 475 * 476 * RETURN: Status 477 * 478 * DESCRIPTION: Handler for the Data Table address space (Op Region) 479 * 480 ******************************************************************************/ 481 482 acpi_status 483 acpi_ex_data_table_space_handler(u32 function, 484 acpi_physical_address address, 485 u32 bit_width, 486 u64 *value, 487 void *handler_context, void *region_context) 488 { 489 ACPI_FUNCTION_TRACE(ex_data_table_space_handler); 490 491 /* 492 * Perform the memory read or write. The bit_width was already 493 * validated. 494 */ 495 switch (function) { 496 case ACPI_READ: 497 498 ACPI_MEMCPY(ACPI_CAST_PTR(char, value), 499 ACPI_PHYSADDR_TO_PTR(address), 500 ACPI_DIV_8(bit_width)); 501 break; 502 503 case ACPI_WRITE: 504 505 ACPI_MEMCPY(ACPI_PHYSADDR_TO_PTR(address), 506 ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width)); 507 break; 508 509 default: 510 511 return_ACPI_STATUS(AE_BAD_PARAMETER); 512 } 513 514 return_ACPI_STATUS(AE_OK); 515 } 516