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