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