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