hwregs.c revision 193249
1
2/*******************************************************************************
3 *
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 *                       control and status registers.
6 *              $Revision: 1.187 $
7 *
8 ******************************************************************************/
9
10/******************************************************************************
11 *
12 * 1. Copyright Notice
13 *
14 * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp.
15 * All rights reserved.
16 *
17 * 2. License
18 *
19 * 2.1. This is your license from Intel Corp. under its intellectual property
20 * rights.  You may have additional license terms from the party that provided
21 * you this software, covering your right to use that party's intellectual
22 * property rights.
23 *
24 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
25 * copy of the source code appearing in this file ("Covered Code") an
26 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
27 * base code distributed originally by Intel ("Original Intel Code") to copy,
28 * make derivatives, distribute, use and display any portion of the Covered
29 * Code in any form, with the right to sublicense such rights; and
30 *
31 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
32 * license (with the right to sublicense), under only those claims of Intel
33 * patents that are infringed by the Original Intel Code, to make, use, sell,
34 * offer to sell, and import the Covered Code and derivative works thereof
35 * solely to the minimum extent necessary to exercise the above copyright
36 * license, and in no event shall the patent license extend to any additions
37 * to or modifications of the Original Intel Code.  No other license or right
38 * is granted directly or by implication, estoppel or otherwise;
39 *
40 * The above copyright and patent license is granted only if the following
41 * conditions are met:
42 *
43 * 3. Conditions
44 *
45 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
46 * Redistribution of source code of any substantial portion of the Covered
47 * Code or modification with rights to further distribute source must include
48 * the above Copyright Notice, the above License, this list of Conditions,
49 * and the following Disclaimer and Export Compliance provision.  In addition,
50 * Licensee must cause all Covered Code to which Licensee contributes to
51 * contain a file documenting the changes Licensee made to create that Covered
52 * Code and the date of any change.  Licensee must include in that file the
53 * documentation of any changes made by any predecessor Licensee.  Licensee
54 * must include a prominent statement that the modification is derived,
55 * directly or indirectly, from Original Intel Code.
56 *
57 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
58 * Redistribution of source code of any substantial portion of the Covered
59 * Code or modification without rights to further distribute source must
60 * include the following Disclaimer and Export Compliance provision in the
61 * documentation and/or other materials provided with distribution.  In
62 * addition, Licensee may not authorize further sublicense of source of any
63 * portion of the Covered Code, and must include terms to the effect that the
64 * license from Licensee to its licensee is limited to the intellectual
65 * property embodied in the software Licensee provides to its licensee, and
66 * not to intellectual property embodied in modifications its licensee may
67 * make.
68 *
69 * 3.3. Redistribution of Executable. Redistribution in executable form of any
70 * substantial portion of the Covered Code or modification must reproduce the
71 * above Copyright Notice, and the following Disclaimer and Export Compliance
72 * provision in the documentation and/or other materials provided with the
73 * distribution.
74 *
75 * 3.4. Intel retains all right, title, and interest in and to the Original
76 * Intel Code.
77 *
78 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
79 * Intel shall be used in advertising or otherwise to promote the sale, use or
80 * other dealings in products derived from or relating to the Covered Code
81 * without prior written authorization from Intel.
82 *
83 * 4. Disclaimer and Export Compliance
84 *
85 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
86 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
87 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
88 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
89 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
90 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
91 * PARTICULAR PURPOSE.
92 *
93 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
94 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
95 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
96 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
97 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
98 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
99 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
100 * LIMITED REMEDY.
101 *
102 * 4.3. Licensee shall not export, either directly or indirectly, any of this
103 * software or system incorporating such software without first obtaining any
104 * required license or other approval from the U. S. Department of Commerce or
105 * any other agency or department of the United States Government.  In the
106 * event Licensee exports any such software from the United States or
107 * re-exports any such software from a foreign destination, Licensee shall
108 * ensure that the distribution and export/re-export of the software is in
109 * compliance with all laws, regulations, orders, or other restrictions of the
110 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
111 * any of its subsidiaries will export/re-export any technical data, process,
112 * software, or service, directly or indirectly, to any country for which the
113 * United States government or any agency thereof requires an export license,
114 * other governmental approval, or letter of assurance, without first obtaining
115 * such license, approval or letter.
116 *
117 *****************************************************************************/
118
119#define __HWREGS_C__
120
121#include <contrib/dev/acpica/acpi.h>
122#include <contrib/dev/acpica/acnamesp.h>
123#include <contrib/dev/acpica/acevents.h>
124
125#define _COMPONENT          ACPI_HARDWARE
126        ACPI_MODULE_NAME    ("hwregs")
127
128
129/*******************************************************************************
130 *
131 * FUNCTION:    AcpiHwClearAcpiStatus
132 *
133 * PARAMETERS:  None
134 *
135 * RETURN:      None
136 *
137 * DESCRIPTION: Clears all fixed and general purpose status bits
138 *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
139 *
140 ******************************************************************************/
141
142ACPI_STATUS
143AcpiHwClearAcpiStatus (
144    void)
145{
146    ACPI_STATUS             Status;
147    ACPI_CPU_FLAGS          LockFlags = 0;
148
149
150    ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
151
152
153    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
154        ACPI_BITMASK_ALL_FIXED_STATUS,
155        (UINT16) AcpiGbl_FADT.XPm1aEventBlock.Address));
156
157    LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
158
159    Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
160                ACPI_REGISTER_PM1_STATUS,
161                ACPI_BITMASK_ALL_FIXED_STATUS);
162    if (ACPI_FAILURE (Status))
163    {
164        goto UnlockAndExit;
165    }
166
167    /* Clear the fixed events */
168
169    if (AcpiGbl_FADT.XPm1bEventBlock.Address)
170    {
171        Status = AcpiHwLowLevelWrite (16, ACPI_BITMASK_ALL_FIXED_STATUS,
172                    &AcpiGbl_FADT.XPm1bEventBlock);
173        if (ACPI_FAILURE (Status))
174        {
175            goto UnlockAndExit;
176        }
177    }
178
179    /* Clear the GPE Bits in all GPE registers in all GPE blocks */
180
181    Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock);
182
183UnlockAndExit:
184    AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
185    return_ACPI_STATUS (Status);
186}
187
188
189/*******************************************************************************
190 *
191 * FUNCTION:    AcpiGetSleepTypeData
192 *
193 * PARAMETERS:  SleepState          - Numeric sleep state
194 *              *SleepTypeA         - Where SLP_TYPa is returned
195 *              *SleepTypeB         - Where SLP_TYPb is returned
196 *
197 * RETURN:      Status - ACPI status
198 *
199 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
200 *              state.
201 *
202 ******************************************************************************/
203
204ACPI_STATUS
205AcpiGetSleepTypeData (
206    UINT8                   SleepState,
207    UINT8                   *SleepTypeA,
208    UINT8                   *SleepTypeB)
209{
210    ACPI_STATUS             Status = AE_OK;
211    ACPI_EVALUATE_INFO      *Info;
212
213
214    ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
215
216
217    /* Validate parameters */
218
219    if ((SleepState > ACPI_S_STATES_MAX) ||
220        !SleepTypeA || !SleepTypeB)
221    {
222        return_ACPI_STATUS (AE_BAD_PARAMETER);
223    }
224
225    /* Allocate the evaluation information block */
226
227    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
228    if (!Info)
229    {
230        return_ACPI_STATUS (AE_NO_MEMORY);
231    }
232
233    Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
234
235    /* Evaluate the namespace object containing the values for this state */
236
237    Status = AcpiNsEvaluate (Info);
238    if (ACPI_FAILURE (Status))
239    {
240        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
241            "%s while evaluating SleepState [%s]\n",
242            AcpiFormatException (Status), Info->Pathname));
243
244        goto Cleanup;
245    }
246
247    /* Must have a return object */
248
249    if (!Info->ReturnObject)
250    {
251        ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
252            Info->Pathname));
253        Status = AE_NOT_EXIST;
254    }
255
256    /* It must be of type Package */
257
258    else if (ACPI_GET_OBJECT_TYPE (Info->ReturnObject) != ACPI_TYPE_PACKAGE)
259    {
260        ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
261        Status = AE_AML_OPERAND_TYPE;
262    }
263
264    /*
265     * The package must have at least two elements. NOTE (March 2005): This
266     * goes against the current ACPI spec which defines this object as a
267     * package with one encoded DWORD element. However, existing practice
268     * by BIOS vendors seems to be to have 2 or more elements, at least
269     * one per sleep type (A/B).
270     */
271    else if (Info->ReturnObject->Package.Count < 2)
272    {
273        ACPI_ERROR ((AE_INFO,
274            "Sleep State return package does not have at least two elements"));
275        Status = AE_AML_NO_OPERAND;
276    }
277
278    /* The first two elements must both be of type Integer */
279
280    else if ((ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[0])
281                != ACPI_TYPE_INTEGER) ||
282             (ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[1])
283                != ACPI_TYPE_INTEGER))
284    {
285        ACPI_ERROR ((AE_INFO,
286            "Sleep State return package elements are not both Integers (%s, %s)",
287            AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
288            AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
289        Status = AE_AML_OPERAND_TYPE;
290    }
291    else
292    {
293        /* Valid _Sx_ package size, type, and value */
294
295        *SleepTypeA = (UINT8)
296            (Info->ReturnObject->Package.Elements[0])->Integer.Value;
297        *SleepTypeB = (UINT8)
298            (Info->ReturnObject->Package.Elements[1])->Integer.Value;
299    }
300
301    if (ACPI_FAILURE (Status))
302    {
303        ACPI_EXCEPTION ((AE_INFO, Status,
304            "While evaluating SleepState [%s], bad Sleep object %p type %s",
305            Info->Pathname, Info->ReturnObject,
306            AcpiUtGetObjectTypeName (Info->ReturnObject)));
307    }
308
309    AcpiUtRemoveReference (Info->ReturnObject);
310
311Cleanup:
312    ACPI_FREE (Info);
313    return_ACPI_STATUS (Status);
314}
315
316ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
317
318
319/*******************************************************************************
320 *
321 * FUNCTION:    AcpiHwGetRegisterBitMask
322 *
323 * PARAMETERS:  RegisterId          - Index of ACPI Register to access
324 *
325 * RETURN:      The bitmask to be used when accessing the register
326 *
327 * DESCRIPTION: Map RegisterId into a register bitmask.
328 *
329 ******************************************************************************/
330
331ACPI_BIT_REGISTER_INFO *
332AcpiHwGetBitRegisterInfo (
333    UINT32                  RegisterId)
334{
335    ACPI_FUNCTION_ENTRY ();
336
337
338    if (RegisterId > ACPI_BITREG_MAX)
339    {
340        ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: %X", RegisterId));
341        return (NULL);
342    }
343
344    return (&AcpiGbl_BitRegisterInfo[RegisterId]);
345}
346
347
348/*******************************************************************************
349 *
350 * FUNCTION:    AcpiGetRegister
351 *
352 * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
353 *              ReturnValue     - Value that was read from the register
354 *
355 * RETURN:      Status and the value read from specified Register. Value
356 *              returned is normalized to bit0 (is shifted all the way right)
357 *
358 * DESCRIPTION: ACPI BitRegister read function.
359 *
360 ******************************************************************************/
361
362ACPI_STATUS
363AcpiGetRegister (
364    UINT32                  RegisterId,
365    UINT32                  *ReturnValue)
366{
367    UINT32                  RegisterValue = 0;
368    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
369    ACPI_STATUS             Status;
370
371
372    ACPI_FUNCTION_TRACE (AcpiGetRegister);
373
374
375    /* Get the info structure corresponding to the requested ACPI Register */
376
377    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
378    if (!BitRegInfo)
379    {
380        return_ACPI_STATUS (AE_BAD_PARAMETER);
381    }
382
383    /* Read from the register */
384
385    Status = AcpiHwRegisterRead (ACPI_MTX_LOCK,
386                BitRegInfo->ParentRegister, &RegisterValue);
387
388    if (ACPI_SUCCESS (Status))
389    {
390        /* Normalize the value that was read */
391
392        RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask)
393                            >> BitRegInfo->BitPosition);
394
395        *ReturnValue = RegisterValue;
396
397        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n",
398            RegisterValue, BitRegInfo->ParentRegister));
399    }
400
401    return_ACPI_STATUS (Status);
402}
403
404ACPI_EXPORT_SYMBOL (AcpiGetRegister)
405
406
407/*******************************************************************************
408 *
409 * FUNCTION:    AcpiSetRegister
410 *
411 * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
412 *              Value           - (only used on write) value to write to the
413 *                                Register, NOT pre-normalized to the bit pos
414 *
415 * RETURN:      Status
416 *
417 * DESCRIPTION: ACPI Bit Register write function.
418 *
419 ******************************************************************************/
420
421ACPI_STATUS
422AcpiSetRegister (
423    UINT32                  RegisterId,
424    UINT32                  Value)
425{
426    UINT32                  RegisterValue = 0;
427    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
428    ACPI_STATUS             Status;
429    ACPI_CPU_FLAGS          LockFlags;
430
431
432    ACPI_FUNCTION_TRACE_U32 (AcpiSetRegister, RegisterId);
433
434
435    /* Get the info structure corresponding to the requested ACPI Register */
436
437    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
438    if (!BitRegInfo)
439    {
440        ACPI_ERROR ((AE_INFO, "Bad ACPI HW RegisterId: %X", RegisterId));
441        return_ACPI_STATUS (AE_BAD_PARAMETER);
442    }
443
444    LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
445
446    /* Always do a register read first so we can insert the new bits  */
447
448    Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
449                BitRegInfo->ParentRegister, &RegisterValue);
450    if (ACPI_FAILURE (Status))
451    {
452        goto UnlockAndExit;
453    }
454
455    /*
456     * Decode the Register ID
457     * Register ID = [Register block ID] | [bit ID]
458     *
459     * Check bit ID to fine locate Register offset.
460     * Check Mask to determine Register offset, and then read-write.
461     */
462    switch (BitRegInfo->ParentRegister)
463    {
464    case ACPI_REGISTER_PM1_STATUS:
465
466        /*
467         * Status Registers are different from the rest. Clear by
468         * writing 1, and writing 0 has no effect. So, the only relevant
469         * information is the single bit we're interested in, all others should
470         * be written as 0 so they will be left unchanged.
471         */
472        Value = ACPI_REGISTER_PREPARE_BITS (Value,
473                    BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
474        if (Value)
475        {
476            Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
477                        ACPI_REGISTER_PM1_STATUS, (UINT16) Value);
478            RegisterValue = 0;
479        }
480        break;
481
482
483    case ACPI_REGISTER_PM1_ENABLE:
484
485        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
486            BitRegInfo->AccessBitMask, Value);
487
488        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
489                    ACPI_REGISTER_PM1_ENABLE, (UINT16) RegisterValue);
490        break;
491
492
493    case ACPI_REGISTER_PM1_CONTROL:
494
495        /*
496         * Write the PM1 Control register.
497         * Note that at this level, the fact that there are actually TWO
498         * registers (A and B - and B may not exist) is abstracted.
499         */
500        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n",
501            RegisterValue));
502
503        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
504            BitRegInfo->AccessBitMask, Value);
505
506        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
507                    ACPI_REGISTER_PM1_CONTROL, (UINT16) RegisterValue);
508        break;
509
510
511    case ACPI_REGISTER_PM2_CONTROL:
512
513        Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
514                    ACPI_REGISTER_PM2_CONTROL, &RegisterValue);
515        if (ACPI_FAILURE (Status))
516        {
517            goto UnlockAndExit;
518        }
519
520        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
521            RegisterValue,
522            ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XPm2ControlBlock.Address)));
523
524        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
525                BitRegInfo->AccessBitMask, Value);
526
527        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n",
528            RegisterValue,
529            ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XPm2ControlBlock.Address)));
530
531        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
532                    ACPI_REGISTER_PM2_CONTROL, (UINT8) (RegisterValue));
533        break;
534
535
536    default:
537        break;
538    }
539
540
541UnlockAndExit:
542
543    AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
544
545    /* Normalize the value that was read */
546
547    ACPI_DEBUG_EXEC (RegisterValue =
548        ((RegisterValue & BitRegInfo->AccessBitMask) >>
549            BitRegInfo->BitPosition));
550
551    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n",
552        Value, RegisterValue, BitRegInfo->ParentRegister));
553    return_ACPI_STATUS (Status);
554}
555
556ACPI_EXPORT_SYMBOL (AcpiSetRegister)
557
558
559/******************************************************************************
560 *
561 * FUNCTION:    AcpiHwRegisterRead
562 *
563 * PARAMETERS:  UseLock             - Lock hardware? True/False
564 *              RegisterId          - ACPI Register ID
565 *              ReturnValue         - Where the register value is returned
566 *
567 * RETURN:      Status and the value read.
568 *
569 * DESCRIPTION: Read from the specified ACPI register
570 *
571 ******************************************************************************/
572
573ACPI_STATUS
574AcpiHwRegisterRead (
575    BOOLEAN                 UseLock,
576    UINT32                  RegisterId,
577    UINT32                  *ReturnValue)
578{
579    UINT32                  Value1 = 0;
580    UINT32                  Value2 = 0;
581    ACPI_STATUS             Status;
582    ACPI_CPU_FLAGS          LockFlags = 0;
583
584
585    ACPI_FUNCTION_TRACE (HwRegisterRead);
586
587
588    if (ACPI_MTX_LOCK == UseLock)
589    {
590        LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
591    }
592
593    switch (RegisterId)
594    {
595    case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
596
597        Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT.XPm1aEventBlock);
598        if (ACPI_FAILURE (Status))
599        {
600            goto UnlockAndExit;
601        }
602
603        /* PM1B is optional */
604
605        Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT.XPm1bEventBlock);
606        Value1 |= Value2;
607        break;
608
609
610    case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access */
611
612        Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_XPm1aEnable);
613        if (ACPI_FAILURE (Status))
614        {
615            goto UnlockAndExit;
616        }
617
618        /* PM1B is optional */
619
620        Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_XPm1bEnable);
621        Value1 |= Value2;
622        break;
623
624
625    case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
626
627        Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT.XPm1aControlBlock);
628        if (ACPI_FAILURE (Status))
629        {
630            goto UnlockAndExit;
631        }
632
633        Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT.XPm1bControlBlock);
634        Value1 |= Value2;
635        break;
636
637
638    case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
639
640        Status = AcpiHwLowLevelRead (8, &Value1, &AcpiGbl_FADT.XPm2ControlBlock);
641        break;
642
643
644    case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
645
646        Status = AcpiHwLowLevelRead (32, &Value1, &AcpiGbl_FADT.XPmTimerBlock);
647        break;
648
649    case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
650
651        Status = AcpiOsReadPort (AcpiGbl_FADT.SmiCommand, &Value1, 8);
652        break;
653
654    default:
655        ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X",
656            RegisterId));
657        Status = AE_BAD_PARAMETER;
658        break;
659    }
660
661UnlockAndExit:
662    if (ACPI_MTX_LOCK == UseLock)
663    {
664        AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
665    }
666
667    if (ACPI_SUCCESS (Status))
668    {
669        *ReturnValue = Value1;
670    }
671
672    return_ACPI_STATUS (Status);
673}
674
675
676/******************************************************************************
677 *
678 * FUNCTION:    AcpiHwRegisterWrite
679 *
680 * PARAMETERS:  UseLock             - Lock hardware? True/False
681 *              RegisterId          - ACPI Register ID
682 *              Value               - The value to write
683 *
684 * RETURN:      Status
685 *
686 * DESCRIPTION: Write to the specified ACPI register
687 *
688 * NOTE: In accordance with the ACPI specification, this function automatically
689 * preserves the value of the following bits, meaning that these bits cannot be
690 * changed via this interface:
691 *
692 * PM1_CONTROL[0] = SCI_EN
693 * PM1_CONTROL[9]
694 * PM1_STATUS[11]
695 *
696 * ACPI References:
697 * 1) Hardware Ignored Bits: When software writes to a register with ignored
698 *      bit fields, it preserves the ignored bit fields
699 * 2) SCI_EN: OSPM always preserves this bit position
700 *
701 ******************************************************************************/
702
703ACPI_STATUS
704AcpiHwRegisterWrite (
705    BOOLEAN                 UseLock,
706    UINT32                  RegisterId,
707    UINT32                  Value)
708{
709    ACPI_STATUS             Status;
710    ACPI_CPU_FLAGS          LockFlags = 0;
711    UINT32                  ReadValue;
712
713
714    ACPI_FUNCTION_TRACE (HwRegisterWrite);
715
716
717    if (ACPI_MTX_LOCK == UseLock)
718    {
719        LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
720    }
721
722    switch (RegisterId)
723    {
724    case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
725
726        /* Perform a read first to preserve certain bits (per ACPI spec) */
727
728        Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
729                    ACPI_REGISTER_PM1_STATUS, &ReadValue);
730        if (ACPI_FAILURE (Status))
731        {
732            goto UnlockAndExit;
733        }
734
735        /* Insert the bits to be preserved */
736
737        ACPI_INSERT_BITS (Value, ACPI_PM1_STATUS_PRESERVED_BITS, ReadValue);
738
739        /* Now we can write the data */
740
741        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aEventBlock);
742        if (ACPI_FAILURE (Status))
743        {
744            goto UnlockAndExit;
745        }
746
747        /* PM1B is optional */
748
749        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bEventBlock);
750        break;
751
752
753    case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access */
754
755        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1aEnable);
756        if (ACPI_FAILURE (Status))
757        {
758            goto UnlockAndExit;
759        }
760
761        /* PM1B is optional */
762
763        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1bEnable);
764        break;
765
766
767    case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
768
769        /*
770         * Perform a read first to preserve certain bits (per ACPI spec)
771         *
772         * Note: This includes SCI_EN, we never want to change this bit
773         */
774        Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
775                    ACPI_REGISTER_PM1_CONTROL, &ReadValue);
776        if (ACPI_FAILURE (Status))
777        {
778            goto UnlockAndExit;
779        }
780
781        /* Insert the bits to be preserved */
782
783        ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
784
785        /* Now we can write the data */
786
787        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aControlBlock);
788        if (ACPI_FAILURE (Status))
789        {
790            goto UnlockAndExit;
791        }
792
793        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bControlBlock);
794        break;
795
796
797    case ACPI_REGISTER_PM1A_CONTROL:         /* 16-bit access */
798
799        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aControlBlock);
800        break;
801
802
803    case ACPI_REGISTER_PM1B_CONTROL:         /* 16-bit access */
804
805        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bControlBlock);
806        break;
807
808
809    case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
810
811        Status = AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT.XPm2ControlBlock);
812        break;
813
814
815    case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
816
817        Status = AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT.XPmTimerBlock);
818        break;
819
820
821    case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
822
823        /* SMI_CMD is currently always in IO space */
824
825        Status = AcpiOsWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
826        break;
827
828
829    default:
830        Status = AE_BAD_PARAMETER;
831        break;
832    }
833
834UnlockAndExit:
835    if (ACPI_MTX_LOCK == UseLock)
836    {
837        AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
838    }
839
840    return_ACPI_STATUS (Status);
841}
842
843
844/******************************************************************************
845 *
846 * FUNCTION:    AcpiHwLowLevelRead
847 *
848 * PARAMETERS:  Width               - 8, 16, or 32
849 *              Value               - Where the value is returned
850 *              Reg                 - GAS register structure
851 *
852 * RETURN:      Status
853 *
854 * DESCRIPTION: Read from either memory or IO space.
855 *
856 ******************************************************************************/
857
858ACPI_STATUS
859AcpiHwLowLevelRead (
860    UINT32                  Width,
861    UINT32                  *Value,
862    ACPI_GENERIC_ADDRESS    *Reg)
863{
864    UINT64                  Address;
865    ACPI_STATUS             Status;
866
867
868    ACPI_FUNCTION_NAME (HwLowLevelRead);
869
870
871    /*
872     * Must have a valid pointer to a GAS structure, and
873     * a non-zero address within. However, don't return an error
874     * because the PM1A/B code must not fail if B isn't present.
875     */
876    if (!Reg)
877    {
878        return (AE_OK);
879    }
880
881    /* Get a local copy of the address. Handles possible alignment issues */
882
883    ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
884    if (!Address)
885    {
886        return (AE_OK);
887    }
888    *Value = 0;
889
890    /*
891     * Two address spaces supported: Memory or IO.
892     * PCI_Config is not supported here because the GAS struct is insufficient
893     */
894    switch (Reg->SpaceId)
895    {
896    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
897
898        Status = AcpiOsReadMemory (
899                    (ACPI_PHYSICAL_ADDRESS) Address, Value, Width);
900        break;
901
902
903    case ACPI_ADR_SPACE_SYSTEM_IO:
904
905        Status = AcpiOsReadPort ((ACPI_IO_ADDRESS) Address, Value, Width);
906        break;
907
908
909    default:
910        ACPI_ERROR ((AE_INFO,
911            "Unsupported address space: %X", Reg->SpaceId));
912        return (AE_BAD_PARAMETER);
913    }
914
915    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
916        "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
917        *Value, Width, ACPI_FORMAT_UINT64 (Address),
918        AcpiUtGetRegionName (Reg->SpaceId)));
919
920    return (Status);
921}
922
923
924/******************************************************************************
925 *
926 * FUNCTION:    AcpiHwLowLevelWrite
927 *
928 * PARAMETERS:  Width               - 8, 16, or 32
929 *              Value               - To be written
930 *              Reg                 - GAS register structure
931 *
932 * RETURN:      Status
933 *
934 * DESCRIPTION: Write to either memory or IO space.
935 *
936 ******************************************************************************/
937
938ACPI_STATUS
939AcpiHwLowLevelWrite (
940    UINT32                  Width,
941    UINT32                  Value,
942    ACPI_GENERIC_ADDRESS    *Reg)
943{
944    UINT64                  Address;
945    ACPI_STATUS             Status;
946
947
948    ACPI_FUNCTION_NAME (HwLowLevelWrite);
949
950
951    /*
952     * Must have a valid pointer to a GAS structure, and
953     * a non-zero address within. However, don't return an error
954     * because the PM1A/B code must not fail if B isn't present.
955     */
956    if (!Reg)
957    {
958        return (AE_OK);
959    }
960
961    /* Get a local copy of the address. Handles possible alignment issues */
962
963    ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
964    if (!Address)
965    {
966        return (AE_OK);
967    }
968
969    /*
970     * Two address spaces supported: Memory or IO.
971     * PCI_Config is not supported here because the GAS struct is insufficient
972     */
973    switch (Reg->SpaceId)
974    {
975    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
976
977        Status = AcpiOsWriteMemory (
978                    (ACPI_PHYSICAL_ADDRESS) Address, Value, Width);
979        break;
980
981
982    case ACPI_ADR_SPACE_SYSTEM_IO:
983
984        Status = AcpiOsWritePort (
985                    (ACPI_IO_ADDRESS) Address, Value, Width);
986        break;
987
988
989    default:
990        ACPI_ERROR ((AE_INFO,
991            "Unsupported address space: %X", Reg->SpaceId));
992        return (AE_BAD_PARAMETER);
993    }
994
995    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
996        "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
997        Value, Width, ACPI_FORMAT_UINT64 (Address),
998        AcpiUtGetRegionName (Reg->SpaceId)));
999
1000    return (Status);
1001}
1002