1 2/****************************************************************************** 3 * 4 * Module Name: exregion - ACPI default op_region (address space) handlers 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000 - 2007, R. Byron Moore 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 <acpi/acinterp.h> 47 48#define _COMPONENT ACPI_EXECUTER 49ACPI_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 ******************************************************************************/ 68acpi_status 69acpi_ex_system_memory_space_handler(u32 function, 70 acpi_physical_address address, 71 u32 bit_width, 72 acpi_integer * 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 window_size; 80#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED 81 u32 remainder; 82#endif 83 84 ACPI_FUNCTION_TRACE(ex_system_memory_space_handler); 85 86 /* Validate and translate the bit width */ 87 88 switch (bit_width) { 89 case 8: 90 length = 1; 91 break; 92 93 case 16: 94 length = 2; 95 break; 96 97 case 32: 98 length = 4; 99 break; 100 101 case 64: 102 length = 8; 103 break; 104 105 default: 106 ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %d", 107 bit_width)); 108 return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 109 } 110 111#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED 112 /* 113 * Hardware does not support non-aligned data transfers, we must verify 114 * the request. 115 */ 116 (void)acpi_ut_short_divide((acpi_integer) address, length, NULL, 117 &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 (((acpi_integer) address + length) > ((acpi_integer) 130 mem_info-> 131 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 * Don't attempt to map memory beyond the end of the region, and 147 * constrain the maximum mapping size to something reasonable. 148 */ 149 window_size = (acpi_size) 150 ((mem_info->address + mem_info->length) - address); 151 152 if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) { 153 window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE; 154 } 155 156 /* Create a new mapping starting at the address given */ 157 158 mem_info->mapped_logical_address = 159 acpi_os_map_memory((acpi_native_uint) address, window_size); 160 if (!mem_info->mapped_logical_address) { 161 ACPI_ERROR((AE_INFO, 162 "Could not map memory at %8.8X%8.8X, size %X", 163 ACPI_FORMAT_UINT64(address), 164 (u32) window_size)); 165 mem_info->mapped_length = 0; 166 return_ACPI_STATUS(AE_NO_MEMORY); 167 } 168 169 /* Save the physical address and mapping size */ 170 171 mem_info->mapped_physical_address = address; 172 mem_info->mapped_length = window_size; 173 } 174 175 /* 176 * Generate a logical pointer corresponding to the address we want to 177 * access 178 */ 179 logical_addr_ptr = mem_info->mapped_logical_address + 180 ((acpi_integer) address - 181 (acpi_integer) mem_info->mapped_physical_address); 182 183 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 184 "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", 185 bit_width, function, ACPI_FORMAT_UINT64(address))); 186 187 /* 188 * Perform the memory read or write 189 * 190 * Note: For machines that do not support non-aligned transfers, the target 191 * address was checked for alignment above. We do not attempt to break the 192 * transfer up into smaller (byte-size) chunks because the AML specifically 193 * asked for a transfer width that the hardware may require. 194 */ 195 switch (function) { 196 case ACPI_READ: 197 198 *value = 0; 199 switch (bit_width) { 200 case 8: 201 *value = (acpi_integer) ACPI_GET8(logical_addr_ptr); 202 break; 203 204 case 16: 205 *value = (acpi_integer) ACPI_GET16(logical_addr_ptr); 206 break; 207 208 case 32: 209 *value = (acpi_integer) ACPI_GET32(logical_addr_ptr); 210 break; 211 212 case 64: 213 *value = (acpi_integer) ACPI_GET64(logical_addr_ptr); 214 break; 215 216 default: 217 /* bit_width was already validated */ 218 break; 219 } 220 break; 221 222 case ACPI_WRITE: 223 224 switch (bit_width) { 225 case 8: 226 ACPI_SET8(logical_addr_ptr) = (u8) * value; 227 break; 228 229 case 16: 230 ACPI_SET16(logical_addr_ptr) = (u16) * value; 231 break; 232 233 case 32: 234 ACPI_SET32(logical_addr_ptr) = (u32) * value; 235 break; 236 237 case 64: 238 ACPI_SET64(logical_addr_ptr) = (u64) * value; 239 break; 240 241 default: 242 /* bit_width was already validated */ 243 break; 244 } 245 break; 246 247 default: 248 status = AE_BAD_PARAMETER; 249 break; 250 } 251 252 return_ACPI_STATUS(status); 253} 254 255/******************************************************************************* 256 * 257 * FUNCTION: acpi_ex_system_io_space_handler 258 * 259 * PARAMETERS: Function - Read or Write operation 260 * Address - Where in the space to read or write 261 * bit_width - Field width in bits (8, 16, or 32) 262 * Value - Pointer to in or out value 263 * handler_context - Pointer to Handler's context 264 * region_context - Pointer to context specific to the 265 * accessed region 266 * 267 * RETURN: Status 268 * 269 * DESCRIPTION: Handler for the System IO address space (Op Region) 270 * 271 ******************************************************************************/ 272 273acpi_status 274acpi_ex_system_io_space_handler(u32 function, 275 acpi_physical_address address, 276 u32 bit_width, 277 acpi_integer * value, 278 void *handler_context, void *region_context) 279{ 280 acpi_status status = AE_OK; 281 u32 value32; 282 283 ACPI_FUNCTION_TRACE(ex_system_io_space_handler); 284 285 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 286 "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n", 287 bit_width, function, ACPI_FORMAT_UINT64(address))); 288 289 /* Decode the function parameter */ 290 291 switch (function) { 292 case ACPI_READ: 293 294 status = acpi_os_read_port((acpi_io_address) address, 295 &value32, bit_width); 296 *value = value32; 297 break; 298 299 case ACPI_WRITE: 300 301 status = acpi_os_write_port((acpi_io_address) address, 302 (u32) * value, bit_width); 303 break; 304 305 default: 306 status = AE_BAD_PARAMETER; 307 break; 308 } 309 310 return_ACPI_STATUS(status); 311} 312 313/******************************************************************************* 314 * 315 * FUNCTION: acpi_ex_pci_config_space_handler 316 * 317 * PARAMETERS: Function - Read or Write operation 318 * Address - Where in the space to read or write 319 * bit_width - Field width in bits (8, 16, or 32) 320 * Value - Pointer to in or out value 321 * handler_context - Pointer to Handler's context 322 * region_context - Pointer to context specific to the 323 * accessed region 324 * 325 * RETURN: Status 326 * 327 * DESCRIPTION: Handler for the PCI Config address space (Op Region) 328 * 329 ******************************************************************************/ 330 331acpi_status 332acpi_ex_pci_config_space_handler(u32 function, 333 acpi_physical_address address, 334 u32 bit_width, 335 acpi_integer * value, 336 void *handler_context, void *region_context) 337{ 338 acpi_status status = AE_OK; 339 struct acpi_pci_id *pci_id; 340 u16 pci_register; 341 342 ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); 343 344 /* 345 * The arguments to acpi_os(Read|Write)pci_configuration are: 346 * 347 * pci_segment is the PCI bus segment range 0-31 348 * pci_bus is the PCI bus number range 0-255 349 * pci_device is the PCI device number range 0-31 350 * pci_function is the PCI device function number 351 * pci_register is the Config space register range 0-255 bytes 352 * 353 * Value - input value for write, output address for read 354 * 355 */ 356 pci_id = (struct acpi_pci_id *)region_context; 357 pci_register = (u16) (u32) address; 358 359 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 360 "Pci-Config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", 361 function, bit_width, pci_id->segment, pci_id->bus, 362 pci_id->device, pci_id->function, pci_register)); 363 364 switch (function) { 365 case ACPI_READ: 366 367 *value = 0; 368 status = acpi_os_read_pci_configuration(pci_id, pci_register, 369 value, bit_width); 370 break; 371 372 case ACPI_WRITE: 373 374 status = acpi_os_write_pci_configuration(pci_id, pci_register, 375 *value, bit_width); 376 break; 377 378 default: 379 380 status = AE_BAD_PARAMETER; 381 break; 382 } 383 384 return_ACPI_STATUS(status); 385} 386 387/******************************************************************************* 388 * 389 * FUNCTION: acpi_ex_cmos_space_handler 390 * 391 * PARAMETERS: Function - Read or Write operation 392 * Address - Where in the space to read or write 393 * bit_width - Field width in bits (8, 16, or 32) 394 * Value - Pointer to in or out value 395 * handler_context - Pointer to Handler's context 396 * region_context - Pointer to context specific to the 397 * accessed region 398 * 399 * RETURN: Status 400 * 401 * DESCRIPTION: Handler for the CMOS address space (Op Region) 402 * 403 ******************************************************************************/ 404 405acpi_status 406acpi_ex_cmos_space_handler(u32 function, 407 acpi_physical_address address, 408 u32 bit_width, 409 acpi_integer * value, 410 void *handler_context, void *region_context) 411{ 412 acpi_status status = AE_OK; 413 414 ACPI_FUNCTION_TRACE(ex_cmos_space_handler); 415 416 return_ACPI_STATUS(status); 417} 418 419/******************************************************************************* 420 * 421 * FUNCTION: acpi_ex_pci_bar_space_handler 422 * 423 * PARAMETERS: Function - Read or Write operation 424 * Address - Where in the space to read or write 425 * bit_width - Field width in bits (8, 16, or 32) 426 * Value - Pointer to in or out value 427 * handler_context - Pointer to Handler's context 428 * region_context - Pointer to context specific to the 429 * accessed region 430 * 431 * RETURN: Status 432 * 433 * DESCRIPTION: Handler for the PCI bar_target address space (Op Region) 434 * 435 ******************************************************************************/ 436 437acpi_status 438acpi_ex_pci_bar_space_handler(u32 function, 439 acpi_physical_address address, 440 u32 bit_width, 441 acpi_integer * value, 442 void *handler_context, void *region_context) 443{ 444 acpi_status status = AE_OK; 445 446 ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler); 447 448 return_ACPI_STATUS(status); 449} 450 451/******************************************************************************* 452 * 453 * FUNCTION: acpi_ex_data_table_space_handler 454 * 455 * PARAMETERS: Function - Read or Write operation 456 * Address - Where in the space to read or write 457 * bit_width - Field width in bits (8, 16, or 32) 458 * Value - Pointer to in or out value 459 * handler_context - Pointer to Handler's context 460 * region_context - Pointer to context specific to the 461 * accessed region 462 * 463 * RETURN: Status 464 * 465 * DESCRIPTION: Handler for the Data Table address space (Op Region) 466 * 467 ******************************************************************************/ 468 469acpi_status 470acpi_ex_data_table_space_handler(u32 function, 471 acpi_physical_address address, 472 u32 bit_width, 473 acpi_integer * value, 474 void *handler_context, void *region_context) 475{ 476 ACPI_FUNCTION_TRACE(ex_data_table_space_handler); 477 478 /* Perform the memory read or write */ 479 480 switch (function) { 481 case ACPI_READ: 482 483 ACPI_MEMCPY(ACPI_CAST_PTR(char, value), 484 ACPI_PHYSADDR_TO_PTR(address), 485 ACPI_DIV_8(bit_width)); 486 break; 487 488 case ACPI_WRITE: 489 default: 490 491 return_ACPI_STATUS(AE_SUPPORT); 492 } 493 494 return_ACPI_STATUS(AE_OK); 495} 496