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