The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/acpica/components/hardware/hwregs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*******************************************************************************
    2  *
    3  * Module Name: hwregs - Read/write access functions for the various ACPI
    4  *                       control and status registers.
    5  *
    6  ******************************************************************************/
    7 
    8 /******************************************************************************
    9  *
   10  * 1. Copyright Notice
   11  *
   12  * Some or all of this work - Copyright (c) 1999 - 2022, Intel Corp.
   13  * All rights reserved.
   14  *
   15  * 2. License
   16  *
   17  * 2.1. This is your license from Intel Corp. under its intellectual property
   18  * rights. You may have additional license terms from the party that provided
   19  * you this software, covering your right to use that party's intellectual
   20  * property rights.
   21  *
   22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
   23  * copy of the source code appearing in this file ("Covered Code") an
   24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
   25  * base code distributed originally by Intel ("Original Intel Code") to copy,
   26  * make derivatives, distribute, use and display any portion of the Covered
   27  * Code in any form, with the right to sublicense such rights; and
   28  *
   29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
   30  * license (with the right to sublicense), under only those claims of Intel
   31  * patents that are infringed by the Original Intel Code, to make, use, sell,
   32  * offer to sell, and import the Covered Code and derivative works thereof
   33  * solely to the minimum extent necessary to exercise the above copyright
   34  * license, and in no event shall the patent license extend to any additions
   35  * to or modifications of the Original Intel Code. No other license or right
   36  * is granted directly or by implication, estoppel or otherwise;
   37  *
   38  * The above copyright and patent license is granted only if the following
   39  * conditions are met:
   40  *
   41  * 3. Conditions
   42  *
   43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
   44  * Redistribution of source code of any substantial portion of the Covered
   45  * Code or modification with rights to further distribute source must include
   46  * the above Copyright Notice, the above License, this list of Conditions,
   47  * and the following Disclaimer and Export Compliance provision. In addition,
   48  * Licensee must cause all Covered Code to which Licensee contributes to
   49  * contain a file documenting the changes Licensee made to create that Covered
   50  * Code and the date of any change. Licensee must include in that file the
   51  * documentation of any changes made by any predecessor Licensee. Licensee
   52  * must include a prominent statement that the modification is derived,
   53  * directly or indirectly, from Original Intel Code.
   54  *
   55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
   56  * Redistribution of source code of any substantial portion of the Covered
   57  * Code or modification without rights to further distribute source must
   58  * include the following Disclaimer and Export Compliance provision in the
   59  * documentation and/or other materials provided with distribution. In
   60  * addition, Licensee may not authorize further sublicense of source of any
   61  * portion of the Covered Code, and must include terms to the effect that the
   62  * license from Licensee to its licensee is limited to the intellectual
   63  * property embodied in the software Licensee provides to its licensee, and
   64  * not to intellectual property embodied in modifications its licensee may
   65  * make.
   66  *
   67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
   68  * substantial portion of the Covered Code or modification must reproduce the
   69  * above Copyright Notice, and the following Disclaimer and Export Compliance
   70  * provision in the documentation and/or other materials provided with the
   71  * distribution.
   72  *
   73  * 3.4. Intel retains all right, title, and interest in and to the Original
   74  * Intel Code.
   75  *
   76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
   77  * Intel shall be used in advertising or otherwise to promote the sale, use or
   78  * other dealings in products derived from or relating to the Covered Code
   79  * without prior written authorization from Intel.
   80  *
   81  * 4. Disclaimer and Export Compliance
   82  *
   83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
   84  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
   85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
   86  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
   87  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
   88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
   89  * PARTICULAR PURPOSE.
   90  *
   91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
   92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
   93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
   94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
   95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
   96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
   97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
   98  * LIMITED REMEDY.
   99  *
  100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
  101  * software or system incorporating such software without first obtaining any
  102  * required license or other approval from the U. S. Department of Commerce or
  103  * any other agency or department of the United States Government. In the
  104  * event Licensee exports any such software from the United States or
  105  * re-exports any such software from a foreign destination, Licensee shall
  106  * ensure that the distribution and export/re-export of the software is in
  107  * compliance with all laws, regulations, orders, or other restrictions of the
  108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
  109  * any of its subsidiaries will export/re-export any technical data, process,
  110  * software, or service, directly or indirectly, to any country for which the
  111  * United States government or any agency thereof requires an export license,
  112  * other governmental approval, or letter of assurance, without first obtaining
  113  * such license, approval or letter.
  114  *
  115  *****************************************************************************
  116  *
  117  * Alternatively, you may choose to be licensed under the terms of the
  118  * following license:
  119  *
  120  * Redistribution and use in source and binary forms, with or without
  121  * modification, are permitted provided that the following conditions
  122  * are met:
  123  * 1. Redistributions of source code must retain the above copyright
  124  *    notice, this list of conditions, and the following disclaimer,
  125  *    without modification.
  126  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  127  *    substantially similar to the "NO WARRANTY" disclaimer below
  128  *    ("Disclaimer") and any redistribution must be conditioned upon
  129  *    including a substantially similar Disclaimer requirement for further
  130  *    binary redistribution.
  131  * 3. Neither the names of the above-listed copyright holders nor the names
  132  *    of any contributors may be used to endorse or promote products derived
  133  *    from this software without specific prior written permission.
  134  *
  135  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  136  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  137  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  138  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  139  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  140  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  141  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  142  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  143  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  144  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  145  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  146  *
  147  * Alternatively, you may choose to be licensed under the terms of the
  148  * GNU General Public License ("GPL") version 2 as published by the Free
  149  * Software Foundation.
  150  *
  151  *****************************************************************************/
  152 
  153 #include <contrib/dev/acpica/include/acpi.h>
  154 #include <contrib/dev/acpica/include/accommon.h>
  155 #include <contrib/dev/acpica/include/acevents.h>
  156 
  157 #define _COMPONENT          ACPI_HARDWARE
  158         ACPI_MODULE_NAME    ("hwregs")
  159 
  160 
  161 #if (!ACPI_REDUCED_HARDWARE)
  162 
  163 /* Local Prototypes */
  164 
  165 static UINT8
  166 AcpiHwGetAccessBitWidth (
  167     UINT64                  Address,
  168     ACPI_GENERIC_ADDRESS    *Reg,
  169     UINT8                   MaxBitWidth);
  170 
  171 static ACPI_STATUS
  172 AcpiHwReadMultiple (
  173     UINT32                  *Value,
  174     ACPI_GENERIC_ADDRESS    *RegisterA,
  175     ACPI_GENERIC_ADDRESS    *RegisterB);
  176 
  177 static ACPI_STATUS
  178 AcpiHwWriteMultiple (
  179     UINT32                  Value,
  180     ACPI_GENERIC_ADDRESS    *RegisterA,
  181     ACPI_GENERIC_ADDRESS    *RegisterB);
  182 
  183 #endif /* !ACPI_REDUCED_HARDWARE */
  184 
  185 
  186 /******************************************************************************
  187  *
  188  * FUNCTION:    AcpiHwGetAccessBitWidth
  189  *
  190  * PARAMETERS:  Address             - GAS register address
  191  *              Reg                 - GAS register structure
  192  *              MaxBitWidth         - Max BitWidth supported (32 or 64)
  193  *
  194  * RETURN:      Status
  195  *
  196  * DESCRIPTION: Obtain optimal access bit width
  197  *
  198  ******************************************************************************/
  199 
  200 static UINT8
  201 AcpiHwGetAccessBitWidth (
  202     UINT64                  Address,
  203     ACPI_GENERIC_ADDRESS    *Reg,
  204     UINT8                   MaxBitWidth)
  205 {
  206     UINT8                   AccessBitWidth;
  207 
  208 
  209     /*
  210      * GAS format "register", used by FADT:
  211      *  1. Detected if BitOffset is 0 and BitWidth is 8/16/32/64;
  212      *  2. AccessSize field is ignored and BitWidth field is used for
  213      *     determining the boundary of the IO accesses.
  214      * GAS format "region", used by APEI registers:
  215      *  1. Detected if BitOffset is not 0 or BitWidth is not 8/16/32/64;
  216      *  2. AccessSize field is used for determining the boundary of the
  217      *     IO accesses;
  218      *  3. BitOffset/BitWidth fields are used to describe the "region".
  219      *
  220      * Note: This algorithm assumes that the "Address" fields should always
  221      *       contain aligned values.
  222      */
  223     if (!Reg->BitOffset && Reg->BitWidth &&
  224         ACPI_IS_POWER_OF_TWO (Reg->BitWidth) &&
  225         ACPI_IS_ALIGNED (Reg->BitWidth, 8))
  226     {
  227         AccessBitWidth = Reg->BitWidth;
  228     }
  229     else if (Reg->AccessWidth)
  230     {
  231         AccessBitWidth = ACPI_ACCESS_BIT_WIDTH (Reg->AccessWidth);
  232     }
  233     else
  234     {
  235         AccessBitWidth = ACPI_ROUND_UP_POWER_OF_TWO_8 (
  236             Reg->BitOffset + Reg->BitWidth);
  237         if (AccessBitWidth <= 8)
  238         {
  239             AccessBitWidth = 8;
  240         }
  241         else
  242         {
  243             while (!ACPI_IS_ALIGNED (Address, AccessBitWidth >> 3))
  244             {
  245                 AccessBitWidth >>= 1;
  246             }
  247         }
  248     }
  249 
  250     /* Maximum IO port access bit width is 32 */
  251 
  252     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
  253     {
  254         MaxBitWidth = 32;
  255     }
  256 
  257     /*
  258      * Return access width according to the requested maximum access bit width,
  259      * as the caller should know the format of the register and may enforce
  260      * a 32-bit accesses.
  261      */
  262     if (AccessBitWidth < MaxBitWidth)
  263     {
  264         return (AccessBitWidth);
  265     }
  266     return (MaxBitWidth);
  267 }
  268 
  269 
  270 /******************************************************************************
  271  *
  272  * FUNCTION:    AcpiHwValidateRegister
  273  *
  274  * PARAMETERS:  Reg                 - GAS register structure
  275  *              MaxBitWidth         - Max BitWidth supported (32 or 64)
  276  *              Address             - Pointer to where the gas->address
  277  *                                    is returned
  278  *
  279  * RETURN:      Status
  280  *
  281  * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
  282  *              pointer, Address, SpaceId, BitWidth, and BitOffset.
  283  *
  284  ******************************************************************************/
  285 
  286 ACPI_STATUS
  287 AcpiHwValidateRegister (
  288     ACPI_GENERIC_ADDRESS    *Reg,
  289     UINT8                   MaxBitWidth,
  290     UINT64                  *Address)
  291 {
  292     UINT8                   BitWidth;
  293     UINT8                   AccessWidth;
  294 
  295 
  296     /* Must have a valid pointer to a GAS structure */
  297 
  298     if (!Reg)
  299     {
  300         return (AE_BAD_PARAMETER);
  301     }
  302 
  303     /*
  304      * Copy the target address. This handles possible alignment issues.
  305      * Address must not be null. A null address also indicates an optional
  306      * ACPI register that is not supported, so no error message.
  307      */
  308     ACPI_MOVE_64_TO_64 (Address, &Reg->Address);
  309     if (!(*Address))
  310     {
  311         return (AE_BAD_ADDRESS);
  312     }
  313 
  314     /* Validate the SpaceID */
  315 
  316     if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
  317         (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
  318     {
  319         ACPI_ERROR ((AE_INFO,
  320             "Unsupported address space: 0x%X", Reg->SpaceId));
  321         return (AE_SUPPORT);
  322     }
  323 
  324     /* Validate the AccessWidth */
  325 
  326     if (Reg->AccessWidth > 4)
  327     {
  328         ACPI_ERROR ((AE_INFO,
  329             "Unsupported register access width: 0x%X", Reg->AccessWidth));
  330         return (AE_SUPPORT);
  331     }
  332 
  333     /* Validate the BitWidth, convert AccessWidth into number of bits */
  334 
  335     AccessWidth = AcpiHwGetAccessBitWidth (*Address, Reg, MaxBitWidth);
  336     BitWidth = ACPI_ROUND_UP (Reg->BitOffset + Reg->BitWidth, AccessWidth);
  337     if (MaxBitWidth < BitWidth)
  338     {
  339         ACPI_WARNING ((AE_INFO,
  340             "Requested bit width 0x%X is smaller than register bit width 0x%X",
  341             MaxBitWidth, BitWidth));
  342         return (AE_SUPPORT);
  343     }
  344 
  345     return (AE_OK);
  346 }
  347 
  348 
  349 /******************************************************************************
  350  *
  351  * FUNCTION:    AcpiHwRead
  352  *
  353  * PARAMETERS:  Value               - Where the value is returned
  354  *              Reg                 - GAS register structure
  355  *
  356  * RETURN:      Status
  357  *
  358  * DESCRIPTION: Read from either memory or IO space. This is a 64-bit max
  359  *              version of AcpiRead.
  360  *
  361  * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
  362  *      SpaceID must be SystemMemory or SystemIO.
  363  *
  364  ******************************************************************************/
  365 
  366 ACPI_STATUS
  367 AcpiHwRead (
  368     UINT64                  *Value,
  369     ACPI_GENERIC_ADDRESS    *Reg)
  370 {
  371     UINT64                  Address;
  372     UINT8                   AccessWidth;
  373     UINT32                  BitWidth;
  374     UINT8                   BitOffset;
  375     UINT64                  Value64;
  376     UINT32                  Value32;
  377     UINT8                   Index;
  378     ACPI_STATUS             Status;
  379 
  380 
  381     ACPI_FUNCTION_NAME (HwRead);
  382 
  383 
  384     /* Validate contents of the GAS register */
  385 
  386     Status = AcpiHwValidateRegister (Reg, 64, &Address);
  387     if (ACPI_FAILURE (Status))
  388     {
  389         return (Status);
  390     }
  391 
  392     /*
  393      * Initialize entire 64-bit return value to zero, convert AccessWidth
  394      * into number of bits based
  395      */
  396     *Value = 0;
  397     AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64);
  398     BitWidth = Reg->BitOffset + Reg->BitWidth;
  399     BitOffset = Reg->BitOffset;
  400 
  401     /*
  402      * Two address spaces supported: Memory or IO. PCI_Config is
  403      * not supported here because the GAS structure is insufficient
  404      */
  405     Index = 0;
  406     while (BitWidth)
  407     {
  408         if (BitOffset >= AccessWidth)
  409         {
  410             Value64 = 0;
  411             BitOffset -= AccessWidth;
  412         }
  413         else
  414         {
  415             if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
  416             {
  417                 Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
  418                     Address + Index * ACPI_DIV_8 (AccessWidth),
  419                     &Value64, AccessWidth);
  420             }
  421             else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
  422             {
  423                 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
  424                     Address + Index * ACPI_DIV_8 (AccessWidth),
  425                     &Value32, AccessWidth);
  426                 Value64 = (UINT64) Value32;
  427             }
  428         }
  429 
  430         /*
  431          * Use offset style bit writes because "Index * AccessWidth" is
  432          * ensured to be less than 64-bits by AcpiHwValidateRegister().
  433          */
  434         ACPI_SET_BITS (Value, Index * AccessWidth,
  435             ACPI_MASK_BITS_ABOVE_64 (AccessWidth), Value64);
  436 
  437         BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth;
  438         Index++;
  439     }
  440 
  441     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
  442         "Read:  %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
  443         ACPI_FORMAT_UINT64 (*Value), AccessWidth,
  444         ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId)));
  445 
  446     return (Status);
  447 }
  448 
  449 
  450 /******************************************************************************
  451  *
  452  * FUNCTION:    AcpiHwWrite
  453  *
  454  * PARAMETERS:  Value               - Value to be written
  455  *              Reg                 - GAS register structure
  456  *
  457  * RETURN:      Status
  458  *
  459  * DESCRIPTION: Write to either memory or IO space. This is a 64-bit max
  460  *              version of AcpiWrite.
  461  *
  462  ******************************************************************************/
  463 
  464 ACPI_STATUS
  465 AcpiHwWrite (
  466     UINT64                  Value,
  467     ACPI_GENERIC_ADDRESS    *Reg)
  468 {
  469     UINT64                  Address;
  470     UINT8                   AccessWidth;
  471     UINT32                  BitWidth;
  472     UINT8                   BitOffset;
  473     UINT64                  Value64;
  474     UINT8                   Index;
  475     ACPI_STATUS             Status;
  476 
  477 
  478     ACPI_FUNCTION_NAME (HwWrite);
  479 
  480 
  481     /* Validate contents of the GAS register */
  482 
  483     Status = AcpiHwValidateRegister (Reg, 64, &Address);
  484     if (ACPI_FAILURE (Status))
  485     {
  486         return (Status);
  487     }
  488 
  489     /* Convert AccessWidth into number of bits based */
  490 
  491     AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64);
  492     BitWidth = Reg->BitOffset + Reg->BitWidth;
  493     BitOffset = Reg->BitOffset;
  494 
  495     /*
  496      * Two address spaces supported: Memory or IO. PCI_Config is
  497      * not supported here because the GAS structure is insufficient
  498      */
  499     Index = 0;
  500     while (BitWidth)
  501     {
  502         /*
  503          * Use offset style bit reads because "Index * AccessWidth" is
  504          * ensured to be less than 64-bits by AcpiHwValidateRegister().
  505          */
  506         Value64 = ACPI_GET_BITS (&Value, Index * AccessWidth,
  507             ACPI_MASK_BITS_ABOVE_64 (AccessWidth));
  508 
  509         if (BitOffset >= AccessWidth)
  510         {
  511             BitOffset -= AccessWidth;
  512         }
  513         else
  514         {
  515             if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
  516             {
  517                 Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
  518                     Address + Index * ACPI_DIV_8 (AccessWidth),
  519                     Value64, AccessWidth);
  520             }
  521             else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
  522             {
  523                 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
  524                     Address + Index * ACPI_DIV_8 (AccessWidth),
  525                     (UINT32) Value64, AccessWidth);
  526             }
  527         }
  528 
  529         /*
  530          * Index * AccessWidth is ensured to be less than 32-bits by
  531          * AcpiHwValidateRegister().
  532          */
  533         BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth;
  534         Index++;
  535     }
  536 
  537     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
  538         "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
  539         ACPI_FORMAT_UINT64 (Value), AccessWidth,
  540         ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId)));
  541 
  542     return (Status);
  543 }
  544 
  545 
  546 #if (!ACPI_REDUCED_HARDWARE)
  547 /*******************************************************************************
  548  *
  549  * FUNCTION:    AcpiHwClearAcpiStatus
  550  *
  551  * PARAMETERS:  None
  552  *
  553  * RETURN:      Status
  554  *
  555  * DESCRIPTION: Clears all fixed and general purpose status bits
  556  *
  557  ******************************************************************************/
  558 
  559 ACPI_STATUS
  560 AcpiHwClearAcpiStatus (
  561     void)
  562 {
  563     ACPI_STATUS             Status;
  564     ACPI_CPU_FLAGS          LockFlags = 0;
  565 
  566 
  567     ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
  568 
  569 
  570     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
  571         ACPI_BITMASK_ALL_FIXED_STATUS,
  572         ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address)));
  573 
  574     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
  575 
  576     /* Clear the fixed events in PM1 A/B */
  577 
  578     Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
  579         ACPI_BITMASK_ALL_FIXED_STATUS);
  580 
  581     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
  582 
  583     if (ACPI_FAILURE (Status))
  584     {
  585         goto Exit;
  586     }
  587 
  588     /* Clear the GPE Bits in all GPE registers in all GPE blocks */
  589 
  590     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
  591 
  592 Exit:
  593     return_ACPI_STATUS (Status);
  594 }
  595 
  596 
  597 /*******************************************************************************
  598  *
  599  * FUNCTION:    AcpiHwGetBitRegisterInfo
  600  *
  601  * PARAMETERS:  RegisterId          - Index of ACPI Register to access
  602  *
  603  * RETURN:      The bitmask to be used when accessing the register
  604  *
  605  * DESCRIPTION: Map RegisterId into a register bitmask.
  606  *
  607  ******************************************************************************/
  608 
  609 ACPI_BIT_REGISTER_INFO *
  610 AcpiHwGetBitRegisterInfo (
  611     UINT32                  RegisterId)
  612 {
  613     ACPI_FUNCTION_ENTRY ();
  614 
  615 
  616     if (RegisterId > ACPI_BITREG_MAX)
  617     {
  618         ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
  619         return (NULL);
  620     }
  621 
  622     return (&AcpiGbl_BitRegisterInfo[RegisterId]);
  623 }
  624 
  625 
  626 /******************************************************************************
  627  *
  628  * FUNCTION:    AcpiHwWritePm1Control
  629  *
  630  * PARAMETERS:  Pm1aControl         - Value to be written to PM1A control
  631  *              Pm1bControl         - Value to be written to PM1B control
  632  *
  633  * RETURN:      Status
  634  *
  635  * DESCRIPTION: Write the PM1 A/B control registers. These registers are
  636  *              different than the PM1 A/B status and enable registers
  637  *              in that different values can be written to the A/B registers.
  638  *              Most notably, the SLP_TYP bits can be different, as per the
  639  *              values returned from the _Sx predefined methods.
  640  *
  641  ******************************************************************************/
  642 
  643 ACPI_STATUS
  644 AcpiHwWritePm1Control (
  645     UINT32                  Pm1aControl,
  646     UINT32                  Pm1bControl)
  647 {
  648     ACPI_STATUS             Status;
  649 
  650 
  651     ACPI_FUNCTION_TRACE (HwWritePm1Control);
  652 
  653 
  654     Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock);
  655     if (ACPI_FAILURE (Status))
  656     {
  657         return_ACPI_STATUS (Status);
  658     }
  659 
  660     if (AcpiGbl_FADT.XPm1bControlBlock.Address)
  661     {
  662         Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock);
  663     }
  664     return_ACPI_STATUS (Status);
  665 }
  666 
  667 
  668 /******************************************************************************
  669  *
  670  * FUNCTION:    AcpiHwRegisterRead
  671  *
  672  * PARAMETERS:  RegisterId          - ACPI Register ID
  673  *              ReturnValue         - Where the register value is returned
  674  *
  675  * RETURN:      Status and the value read.
  676  *
  677  * DESCRIPTION: Read from the specified ACPI register
  678  *
  679  ******************************************************************************/
  680 
  681 ACPI_STATUS
  682 AcpiHwRegisterRead (
  683     UINT32                  RegisterId,
  684     UINT32                  *ReturnValue)
  685 {
  686     UINT32                  Value = 0;
  687     UINT64                  Value64;
  688     ACPI_STATUS             Status;
  689 
  690 
  691     ACPI_FUNCTION_TRACE (HwRegisterRead);
  692 
  693 
  694     switch (RegisterId)
  695     {
  696     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
  697 
  698         Status = AcpiHwReadMultiple (&Value,
  699             &AcpiGbl_XPm1aStatus,
  700             &AcpiGbl_XPm1bStatus);
  701         break;
  702 
  703     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
  704 
  705         Status = AcpiHwReadMultiple (&Value,
  706             &AcpiGbl_XPm1aEnable,
  707             &AcpiGbl_XPm1bEnable);
  708         break;
  709 
  710     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
  711 
  712         Status = AcpiHwReadMultiple (&Value,
  713             &AcpiGbl_FADT.XPm1aControlBlock,
  714             &AcpiGbl_FADT.XPm1bControlBlock);
  715 
  716         /*
  717          * Zero the write-only bits. From the ACPI specification, "Hardware
  718          * Write-Only Bits": "Upon reads to registers with write-only bits,
  719          * software masks out all write-only bits."
  720          */
  721         Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
  722         break;
  723 
  724     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
  725 
  726         Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPm2ControlBlock);
  727         if (ACPI_SUCCESS (Status))
  728         {
  729             Value = (UINT32) Value64;
  730         }
  731         break;
  732 
  733     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
  734 
  735         Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPmTimerBlock);
  736         if (ACPI_SUCCESS (Status))
  737         {
  738             Value = (UINT32) Value64;
  739         }
  740 
  741         break;
  742 
  743     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
  744 
  745         Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
  746         break;
  747 
  748     default:
  749 
  750         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
  751             RegisterId));
  752         Status = AE_BAD_PARAMETER;
  753         break;
  754     }
  755 
  756     if (ACPI_SUCCESS (Status))
  757     {
  758         *ReturnValue = (UINT32) Value;
  759     }
  760 
  761     return_ACPI_STATUS (Status);
  762 }
  763 
  764 
  765 /******************************************************************************
  766  *
  767  * FUNCTION:    AcpiHwRegisterWrite
  768  *
  769  * PARAMETERS:  RegisterId          - ACPI Register ID
  770  *              Value               - The value to write
  771  *
  772  * RETURN:      Status
  773  *
  774  * DESCRIPTION: Write to the specified ACPI register
  775  *
  776  * NOTE: In accordance with the ACPI specification, this function automatically
  777  * preserves the value of the following bits, meaning that these bits cannot be
  778  * changed via this interface:
  779  *
  780  * PM1_CONTROL[0] = SCI_EN
  781  * PM1_CONTROL[9]
  782  * PM1_STATUS[11]
  783  *
  784  * ACPI References:
  785  * 1) Hardware Ignored Bits: When software writes to a register with ignored
  786  *      bit fields, it preserves the ignored bit fields
  787  * 2) SCI_EN: OSPM always preserves this bit position
  788  *
  789  ******************************************************************************/
  790 
  791 ACPI_STATUS
  792 AcpiHwRegisterWrite (
  793     UINT32                  RegisterId,
  794     UINT32                  Value)
  795 {
  796     ACPI_STATUS             Status;
  797     UINT32                  ReadValue;
  798     UINT64                  ReadValue64;
  799 
  800 
  801     ACPI_FUNCTION_TRACE (HwRegisterWrite);
  802 
  803 
  804     switch (RegisterId)
  805     {
  806     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
  807         /*
  808          * Handle the "ignored" bit in PM1 Status. According to the ACPI
  809          * specification, ignored bits are to be preserved when writing.
  810          * Normally, this would mean a read/modify/write sequence. However,
  811          * preserving a bit in the status register is different. Writing a
  812          * one clears the status, and writing a zero preserves the status.
  813          * Therefore, we must always write zero to the ignored bit.
  814          *
  815          * This behavior is clarified in the ACPI 4.0 specification.
  816          */
  817         Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
  818 
  819         Status = AcpiHwWriteMultiple (Value,
  820             &AcpiGbl_XPm1aStatus,
  821             &AcpiGbl_XPm1bStatus);
  822         break;
  823 
  824     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
  825 
  826         Status = AcpiHwWriteMultiple (Value,
  827             &AcpiGbl_XPm1aEnable,
  828             &AcpiGbl_XPm1bEnable);
  829         break;
  830 
  831     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
  832         /*
  833          * Perform a read first to preserve certain bits (per ACPI spec)
  834          * Note: This includes SCI_EN, we never want to change this bit
  835          */
  836         Status = AcpiHwReadMultiple (&ReadValue,
  837             &AcpiGbl_FADT.XPm1aControlBlock,
  838             &AcpiGbl_FADT.XPm1bControlBlock);
  839         if (ACPI_FAILURE (Status))
  840         {
  841             goto Exit;
  842         }
  843 
  844         /* Insert the bits to be preserved */
  845 
  846         ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
  847 
  848         /* Now we can write the data */
  849 
  850         Status = AcpiHwWriteMultiple (Value,
  851             &AcpiGbl_FADT.XPm1aControlBlock,
  852             &AcpiGbl_FADT.XPm1bControlBlock);
  853         break;
  854 
  855     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
  856         /*
  857          * For control registers, all reserved bits must be preserved,
  858          * as per the ACPI spec.
  859          */
  860         Status = AcpiHwRead (&ReadValue64, &AcpiGbl_FADT.XPm2ControlBlock);
  861         if (ACPI_FAILURE (Status))
  862         {
  863             goto Exit;
  864         }
  865         ReadValue = (UINT32) ReadValue64;
  866 
  867         /* Insert the bits to be preserved */
  868 
  869         ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
  870 
  871         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
  872         break;
  873 
  874     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
  875 
  876         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
  877         break;
  878 
  879     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
  880 
  881         /* SMI_CMD is currently always in IO space */
  882 
  883         Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
  884         break;
  885 
  886     default:
  887 
  888         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
  889             RegisterId));
  890         Status = AE_BAD_PARAMETER;
  891         break;
  892     }
  893 
  894 Exit:
  895     return_ACPI_STATUS (Status);
  896 }
  897 
  898 
  899 /******************************************************************************
  900  *
  901  * FUNCTION:    AcpiHwReadMultiple
  902  *
  903  * PARAMETERS:  Value               - Where the register value is returned
  904  *              RegisterA           - First ACPI register (required)
  905  *              RegisterB           - Second ACPI register (optional)
  906  *
  907  * RETURN:      Status
  908  *
  909  * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
  910  *
  911  ******************************************************************************/
  912 
  913 static ACPI_STATUS
  914 AcpiHwReadMultiple (
  915     UINT32                  *Value,
  916     ACPI_GENERIC_ADDRESS    *RegisterA,
  917     ACPI_GENERIC_ADDRESS    *RegisterB)
  918 {
  919     UINT32                  ValueA = 0;
  920     UINT32                  ValueB = 0;
  921     UINT64                  Value64;
  922     ACPI_STATUS             Status;
  923 
  924 
  925     /* The first register is always required */
  926 
  927     Status = AcpiHwRead (&Value64, RegisterA);
  928     if (ACPI_FAILURE (Status))
  929     {
  930         return (Status);
  931     }
  932     ValueA = (UINT32) Value64;
  933 
  934     /* Second register is optional */
  935 
  936     if (RegisterB->Address)
  937     {
  938         Status = AcpiHwRead (&Value64, RegisterB);
  939         if (ACPI_FAILURE (Status))
  940         {
  941             return (Status);
  942         }
  943         ValueB = (UINT32) Value64;
  944     }
  945 
  946     /*
  947      * OR the two return values together. No shifting or masking is necessary,
  948      * because of how the PM1 registers are defined in the ACPI specification:
  949      *
  950      * "Although the bits can be split between the two register blocks (each
  951      * register block has a unique pointer within the FADT), the bit positions
  952      * are maintained. The register block with unimplemented bits (that is,
  953      * those implemented in the other register block) always returns zeros,
  954      * and writes have no side effects"
  955      */
  956     *Value = (ValueA | ValueB);
  957     return (AE_OK);
  958 }
  959 
  960 
  961 /******************************************************************************
  962  *
  963  * FUNCTION:    AcpiHwWriteMultiple
  964  *
  965  * PARAMETERS:  Value               - The value to write
  966  *              RegisterA           - First ACPI register (required)
  967  *              RegisterB           - Second ACPI register (optional)
  968  *
  969  * RETURN:      Status
  970  *
  971  * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
  972  *
  973  ******************************************************************************/
  974 
  975 static ACPI_STATUS
  976 AcpiHwWriteMultiple (
  977     UINT32                  Value,
  978     ACPI_GENERIC_ADDRESS    *RegisterA,
  979     ACPI_GENERIC_ADDRESS    *RegisterB)
  980 {
  981     ACPI_STATUS             Status;
  982 
  983 
  984     /* The first register is always required */
  985 
  986     Status = AcpiHwWrite (Value, RegisterA);
  987     if (ACPI_FAILURE (Status))
  988     {
  989         return (Status);
  990     }
  991 
  992     /*
  993      * Second register is optional
  994      *
  995      * No bit shifting or clearing is necessary, because of how the PM1
  996      * registers are defined in the ACPI specification:
  997      *
  998      * "Although the bits can be split between the two register blocks (each
  999      * register block has a unique pointer within the FADT), the bit positions
 1000      * are maintained. The register block with unimplemented bits (that is,
 1001      * those implemented in the other register block) always returns zeros,
 1002      * and writes have no side effects"
 1003      */
 1004     if (RegisterB->Address)
 1005     {
 1006         Status = AcpiHwWrite (Value, RegisterB);
 1007     }
 1008 
 1009     return (Status);
 1010 }
 1011 
 1012 #endif /* !ACPI_REDUCED_HARDWARE */

Cache object: c6eb054113603f9a22287e74db2246ee


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.