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