1 /****************************************************************************** 2 * 3 * Module Name: exregion - ACPI default OpRegion (address space) handlers 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 #define __EXREGION_C__ 45 46 #include "acpi.h" 47 #include "accommon.h" 48 #include "acinterp.h" 49 50 51 #define _COMPONENT ACPI_EXECUTER 52 ACPI_MODULE_NAME ("exregion") 53 54 55 /******************************************************************************* 56 * 57 * FUNCTION: AcpiExSystemMemorySpaceHandler 58 * 59 * PARAMETERS: Function - Read or Write operation 60 * Address - Where in the space to read or write 61 * BitWidth - Field width in bits (8, 16, or 32) 62 * Value - Pointer to in or out value 63 * HandlerContext - Pointer to Handler's context 64 * RegionContext - Pointer to context specific to the 65 * accessed region 66 * 67 * RETURN: Status 68 * 69 * DESCRIPTION: Handler for the System Memory address space (Op Region) 70 * 71 ******************************************************************************/ 72 73 ACPI_STATUS 74 AcpiExSystemMemorySpaceHandler ( 75 UINT32 Function, 76 ACPI_PHYSICAL_ADDRESS Address, 77 UINT32 BitWidth, 78 UINT64 *Value, 79 void *HandlerContext, 80 void *RegionContext) 81 { 82 ACPI_STATUS Status = AE_OK; 83 void *LogicalAddrPtr = NULL; 84 ACPI_MEM_SPACE_CONTEXT *MemInfo = RegionContext; 85 UINT32 Length; 86 ACPI_SIZE MapLength; 87 ACPI_SIZE PageBoundaryMapLength; 88 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED 89 UINT32 Remainder; 90 #endif 91 92 93 ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler); 94 95 96 /* Validate and translate the bit width */ 97 98 switch (BitWidth) 99 { 100 case 8: 101 102 Length = 1; 103 break; 104 105 case 16: 106 107 Length = 2; 108 break; 109 110 case 32: 111 112 Length = 4; 113 break; 114 115 case 64: 116 117 Length = 8; 118 break; 119 120 default: 121 122 ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %u", 123 BitWidth)); 124 return_ACPI_STATUS (AE_AML_OPERAND_VALUE); 125 } 126 127 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED 128 /* 129 * Hardware does not support non-aligned data transfers, we must verify 130 * the request. 131 */ 132 (void) AcpiUtShortDivide ((UINT64) Address, Length, NULL, &Remainder); 133 if (Remainder != 0) 134 { 135 return_ACPI_STATUS (AE_AML_ALIGNMENT); 136 } 137 #endif 138 139 /* 140 * Does the request fit into the cached memory mapping? 141 * Is 1) Address below the current mapping? OR 142 * 2) Address beyond the current mapping? 143 */ 144 if ((Address < MemInfo->MappedPhysicalAddress) || 145 (((UINT64) Address + Length) > 146 ((UINT64) 147 MemInfo->MappedPhysicalAddress + MemInfo->MappedLength))) 148 { 149 /* 150 * The request cannot be resolved by the current memory mapping; 151 * Delete the existing mapping and create a new one. 152 */ 153 if (MemInfo->MappedLength) 154 { 155 /* Valid mapping, delete it */ 156 157 AcpiOsUnmapMemory (MemInfo->MappedLogicalAddress, 158 MemInfo->MappedLength); 159 } 160 161 /* 162 * October 2009: Attempt to map from the requested address to the 163 * end of the region. However, we will never map more than one 164 * page, nor will we cross a page boundary. 165 */ 166 MapLength = (ACPI_SIZE) 167 ((MemInfo->Address + MemInfo->Length) - Address); 168 169 /* 170 * If mapping the entire remaining portion of the region will cross 171 * a page boundary, just map up to the page boundary, do not cross. 172 * On some systems, crossing a page boundary while mapping regions 173 * can cause warnings if the pages have different attributes 174 * due to resource management. 175 * 176 * This has the added benefit of constraining a single mapping to 177 * one page, which is similar to the original code that used a 4k 178 * maximum window. 179 */ 180 PageBoundaryMapLength = 181 ACPI_ROUND_UP (Address, ACPI_DEFAULT_PAGE_SIZE) - Address; 182 if (PageBoundaryMapLength == 0) 183 { 184 PageBoundaryMapLength = ACPI_DEFAULT_PAGE_SIZE; 185 } 186 187 if (MapLength > PageBoundaryMapLength) 188 { 189 MapLength = PageBoundaryMapLength; 190 } 191 192 /* Create a new mapping starting at the address given */ 193 194 MemInfo->MappedLogicalAddress = AcpiOsMapMemory ( 195 (ACPI_PHYSICAL_ADDRESS) Address, MapLength); 196 if (!MemInfo->MappedLogicalAddress) 197 { 198 ACPI_ERROR ((AE_INFO, 199 "Could not map memory at 0x%8.8X%8.8X, size %u", 200 ACPI_FORMAT_NATIVE_UINT (Address), (UINT32) MapLength)); 201 MemInfo->MappedLength = 0; 202 return_ACPI_STATUS (AE_NO_MEMORY); 203 } 204 205 /* Save the physical address and mapping size */ 206 207 MemInfo->MappedPhysicalAddress = Address; 208 MemInfo->MappedLength = MapLength; 209 } 210 211 /* 212 * Generate a logical pointer corresponding to the address we want to 213 * access 214 */ 215 LogicalAddrPtr = MemInfo->MappedLogicalAddress + 216 ((UINT64) Address - (UINT64) MemInfo->MappedPhysicalAddress); 217 218 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 219 "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", 220 BitWidth, Function, ACPI_FORMAT_NATIVE_UINT (Address))); 221 222 /* 223 * Perform the memory read or write 224 * 225 * Note: For machines that do not support non-aligned transfers, the target 226 * address was checked for alignment above. We do not attempt to break the 227 * transfer up into smaller (byte-size) chunks because the AML specifically 228 * asked for a transfer width that the hardware may require. 229 */ 230 switch (Function) 231 { 232 case ACPI_READ: 233 234 *Value = 0; 235 switch (BitWidth) 236 { 237 case 8: 238 239 *Value = (UINT64) ACPI_GET8 (LogicalAddrPtr); 240 break; 241 242 case 16: 243 244 *Value = (UINT64) ACPI_GET16 (LogicalAddrPtr); 245 break; 246 247 case 32: 248 249 *Value = (UINT64) ACPI_GET32 (LogicalAddrPtr); 250 break; 251 252 case 64: 253 254 *Value = (UINT64) ACPI_GET64 (LogicalAddrPtr); 255 break; 256 257 default: 258 259 /* BitWidth was already validated */ 260 261 break; 262 } 263 break; 264 265 case ACPI_WRITE: 266 267 switch (BitWidth) 268 { 269 case 8: 270 271 ACPI_SET8 (LogicalAddrPtr, *Value); 272 break; 273 274 case 16: 275 276 ACPI_SET16 (LogicalAddrPtr, *Value); 277 break; 278 279 case 32: 280 281 ACPI_SET32 (LogicalAddrPtr, *Value); 282 break; 283 284 case 64: 285 286 ACPI_SET64 (LogicalAddrPtr, *Value); 287 break; 288 289 default: 290 291 /* BitWidth was already validated */ 292 293 break; 294 } 295 break; 296 297 default: 298 299 Status = AE_BAD_PARAMETER; 300 break; 301 } 302 303 return_ACPI_STATUS (Status); 304 } 305 306 307 /******************************************************************************* 308 * 309 * FUNCTION: AcpiExSystemIoSpaceHandler 310 * 311 * PARAMETERS: Function - Read or Write operation 312 * Address - Where in the space to read or write 313 * BitWidth - Field width in bits (8, 16, or 32) 314 * Value - Pointer to in or out value 315 * HandlerContext - Pointer to Handler's context 316 * RegionContext - Pointer to context specific to the 317 * accessed region 318 * 319 * RETURN: Status 320 * 321 * DESCRIPTION: Handler for the System IO address space (Op Region) 322 * 323 ******************************************************************************/ 324 325 ACPI_STATUS 326 AcpiExSystemIoSpaceHandler ( 327 UINT32 Function, 328 ACPI_PHYSICAL_ADDRESS Address, 329 UINT32 BitWidth, 330 UINT64 *Value, 331 void *HandlerContext, 332 void *RegionContext) 333 { 334 ACPI_STATUS Status = AE_OK; 335 UINT32 Value32; 336 337 338 ACPI_FUNCTION_TRACE (ExSystemIoSpaceHandler); 339 340 341 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 342 "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n", 343 BitWidth, Function, ACPI_FORMAT_NATIVE_UINT (Address))); 344 345 /* Decode the function parameter */ 346 347 switch (Function) 348 { 349 case ACPI_READ: 350 351 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) Address, 352 &Value32, BitWidth); 353 *Value = Value32; 354 break; 355 356 case ACPI_WRITE: 357 358 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) Address, 359 (UINT32) *Value, BitWidth); 360 break; 361 362 default: 363 364 Status = AE_BAD_PARAMETER; 365 break; 366 } 367 368 return_ACPI_STATUS (Status); 369 } 370 371 372 /******************************************************************************* 373 * 374 * FUNCTION: AcpiExPciConfigSpaceHandler 375 * 376 * PARAMETERS: Function - Read or Write operation 377 * Address - Where in the space to read or write 378 * BitWidth - Field width in bits (8, 16, or 32) 379 * Value - Pointer to in or out value 380 * HandlerContext - Pointer to Handler's context 381 * RegionContext - Pointer to context specific to the 382 * accessed region 383 * 384 * RETURN: Status 385 * 386 * DESCRIPTION: Handler for the PCI Config address space (Op Region) 387 * 388 ******************************************************************************/ 389 390 ACPI_STATUS 391 AcpiExPciConfigSpaceHandler ( 392 UINT32 Function, 393 ACPI_PHYSICAL_ADDRESS Address, 394 UINT32 BitWidth, 395 UINT64 *Value, 396 void *HandlerContext, 397 void *RegionContext) 398 { 399 ACPI_STATUS Status = AE_OK; 400 ACPI_PCI_ID *PciId; 401 UINT16 PciRegister; 402 403 404 ACPI_FUNCTION_TRACE (ExPciConfigSpaceHandler); 405 406 407 /* 408 * The arguments to AcpiOs(Read|Write)PciConfiguration are: 409 * 410 * PciSegment is the PCI bus segment range 0-31 411 * PciBus is the PCI bus number range 0-255 412 * PciDevice is the PCI device number range 0-31 413 * PciFunction is the PCI device function number 414 * PciRegister is the Config space register range 0-255 bytes 415 * 416 * Value - input value for write, output address for read 417 * 418 */ 419 PciId = (ACPI_PCI_ID *) RegionContext; 420 PciRegister = (UINT16) (UINT32) Address; 421 422 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 423 "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", 424 Function, BitWidth, PciId->Segment, PciId->Bus, PciId->Device, 425 PciId->Function, PciRegister)); 426 427 switch (Function) 428 { 429 case ACPI_READ: 430 431 *Value = 0; 432 Status = AcpiOsReadPciConfiguration (PciId, PciRegister, 433 Value, BitWidth); 434 break; 435 436 case ACPI_WRITE: 437 438 Status = AcpiOsWritePciConfiguration (PciId, PciRegister, 439 *Value, BitWidth); 440 break; 441 442 default: 443 444 Status = AE_BAD_PARAMETER; 445 break; 446 } 447 448 return_ACPI_STATUS (Status); 449 } 450 451 452 /******************************************************************************* 453 * 454 * FUNCTION: AcpiExCmosSpaceHandler 455 * 456 * PARAMETERS: Function - Read or Write operation 457 * Address - Where in the space to read or write 458 * BitWidth - Field width in bits (8, 16, or 32) 459 * Value - Pointer to in or out value 460 * HandlerContext - Pointer to Handler's context 461 * RegionContext - Pointer to context specific to the 462 * accessed region 463 * 464 * RETURN: Status 465 * 466 * DESCRIPTION: Handler for the CMOS address space (Op Region) 467 * 468 ******************************************************************************/ 469 470 ACPI_STATUS 471 AcpiExCmosSpaceHandler ( 472 UINT32 Function, 473 ACPI_PHYSICAL_ADDRESS Address, 474 UINT32 BitWidth, 475 UINT64 *Value, 476 void *HandlerContext, 477 void *RegionContext) 478 { 479 ACPI_STATUS Status = AE_OK; 480 481 482 ACPI_FUNCTION_TRACE (ExCmosSpaceHandler); 483 484 485 return_ACPI_STATUS (Status); 486 } 487 488 489 /******************************************************************************* 490 * 491 * FUNCTION: AcpiExPciBarSpaceHandler 492 * 493 * PARAMETERS: Function - Read or Write operation 494 * Address - Where in the space to read or write 495 * BitWidth - Field width in bits (8, 16, or 32) 496 * Value - Pointer to in or out value 497 * HandlerContext - Pointer to Handler's context 498 * RegionContext - Pointer to context specific to the 499 * accessed region 500 * 501 * RETURN: Status 502 * 503 * DESCRIPTION: Handler for the PCI BarTarget address space (Op Region) 504 * 505 ******************************************************************************/ 506 507 ACPI_STATUS 508 AcpiExPciBarSpaceHandler ( 509 UINT32 Function, 510 ACPI_PHYSICAL_ADDRESS Address, 511 UINT32 BitWidth, 512 UINT64 *Value, 513 void *HandlerContext, 514 void *RegionContext) 515 { 516 ACPI_STATUS Status = AE_OK; 517 518 519 ACPI_FUNCTION_TRACE (ExPciBarSpaceHandler); 520 521 522 return_ACPI_STATUS (Status); 523 } 524 525 526 /******************************************************************************* 527 * 528 * FUNCTION: AcpiExDataTableSpaceHandler 529 * 530 * PARAMETERS: Function - Read or Write operation 531 * Address - Where in the space to read or write 532 * BitWidth - Field width in bits (8, 16, or 32) 533 * Value - Pointer to in or out value 534 * HandlerContext - Pointer to Handler's context 535 * RegionContext - Pointer to context specific to the 536 * accessed region 537 * 538 * RETURN: Status 539 * 540 * DESCRIPTION: Handler for the Data Table address space (Op Region) 541 * 542 ******************************************************************************/ 543 544 ACPI_STATUS 545 AcpiExDataTableSpaceHandler ( 546 UINT32 Function, 547 ACPI_PHYSICAL_ADDRESS Address, 548 UINT32 BitWidth, 549 UINT64 *Value, 550 void *HandlerContext, 551 void *RegionContext) 552 { 553 ACPI_FUNCTION_TRACE (ExDataTableSpaceHandler); 554 555 556 /* 557 * Perform the memory read or write. The BitWidth was already 558 * validated. 559 */ 560 switch (Function) 561 { 562 case ACPI_READ: 563 564 ACPI_MEMCPY (ACPI_CAST_PTR (char, Value), ACPI_PHYSADDR_TO_PTR (Address), 565 ACPI_DIV_8 (BitWidth)); 566 break; 567 568 case ACPI_WRITE: 569 570 ACPI_MEMCPY (ACPI_PHYSADDR_TO_PTR (Address), ACPI_CAST_PTR (char, Value), 571 ACPI_DIV_8 (BitWidth)); 572 break; 573 574 default: 575 576 return_ACPI_STATUS (AE_BAD_PARAMETER); 577 } 578 579 return_ACPI_STATUS (AE_OK); 580 } 581