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 
  45 #define __EXREGION_C__
  46 
  47 #include "acpi.h"
  48 #include "accommon.h"
  49 #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 }