1 2/****************************************************************************** 3 * 4 * Module Name: exregion - ACPI default op_region (address space) handlers 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000 - 2010, 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 50ACPI_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 ******************************************************************************/ 69acpi_status 70acpi_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 287acpi_status 288acpi_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 346acpi_status 347acpi_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 u32 value32; 357 358 ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); 359 360 /* 361 * The arguments to acpi_os(Read|Write)pci_configuration are: 362 * 363 * pci_segment is the PCI bus segment range 0-31 364 * pci_bus is the PCI bus number range 0-255 365 * pci_device is the PCI device number range 0-31 366 * pci_function is the PCI device function number 367 * pci_register is the Config space register range 0-255 bytes 368 * 369 * Value - input value for write, output address for read 370 * 371 */ 372 pci_id = (struct acpi_pci_id *)region_context; 373 pci_register = (u16) (u32) address; 374 375 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 376 "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", 377 function, bit_width, pci_id->segment, pci_id->bus, 378 pci_id->device, pci_id->function, pci_register)); 379 380 switch (function) { 381 case ACPI_READ: 382 383 status = acpi_os_read_pci_configuration(pci_id, pci_register, 384 &value32, bit_width); 385 *value = value32; 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 421acpi_status 422acpi_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 453acpi_status 454acpi_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 485acpi_status 486acpi_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