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