hwregs.c revision 129684
1
2/*******************************************************************************
3 *
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 *                       control and status registers.
6 *              $Revision: 156 $
7 *
8 ******************************************************************************/
9
10/******************************************************************************
11 *
12 * 1. Copyright Notice
13 *
14 * Some or all of this work - Copyright (c) 1999 - 2004, 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 "acpi.h"
122#include "acnamesp.h"
123#include "acevents.h"
124
125#define _COMPONENT          ACPI_HARDWARE
126        ACPI_MODULE_NAME    ("hwregs")
127
128
129/*******************************************************************************
130 *
131 * FUNCTION:    AcpiHwClearAcpiStatus
132 *
133 * PARAMETERS:  Flags           - Lock the hardware or not
134 *
135 * RETURN:      none
136 *
137 * DESCRIPTION: Clears all fixed and general purpose status bits
138 *
139 ******************************************************************************/
140
141ACPI_STATUS
142AcpiHwClearAcpiStatus (
143    UINT32                  Flags)
144{
145    ACPI_STATUS             Status;
146
147
148    ACPI_FUNCTION_TRACE ("HwClearAcpiStatus");
149
150
151    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
152        ACPI_BITMASK_ALL_FIXED_STATUS,
153        (UINT16) ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1aEvtBlk.Address)));
154
155    if (Flags & ACPI_MTX_LOCK)
156    {
157        Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
158        if (ACPI_FAILURE (Status))
159        {
160            return_ACPI_STATUS (Status);
161        }
162    }
163
164    Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS,
165                    ACPI_BITMASK_ALL_FIXED_STATUS);
166    if (ACPI_FAILURE (Status))
167    {
168        goto UnlockAndExit;
169    }
170
171    /* Clear the fixed events */
172
173    if (ACPI_VALID_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address))
174    {
175        Status = AcpiHwLowLevelWrite (16, ACPI_BITMASK_ALL_FIXED_STATUS,
176                    &AcpiGbl_FADT->XPm1bEvtBlk);
177        if (ACPI_FAILURE (Status))
178        {
179            goto UnlockAndExit;
180        }
181    }
182
183    /* Clear the GPE Bits in all GPE registers in all GPE blocks */
184
185    Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock);
186
187UnlockAndExit:
188    if (Flags & ACPI_MTX_LOCK)
189    {
190        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
191    }
192    return_ACPI_STATUS (Status);
193}
194
195
196/*******************************************************************************
197 *
198 * FUNCTION:    AcpiGetSleepTypeData
199 *
200 * PARAMETERS:  SleepState          - Numeric sleep state
201 *              *SleepTypeA         - Where SLP_TYPa is returned
202 *              *SleepTypeB         - Where SLP_TYPb is returned
203 *
204 * RETURN:      Status - ACPI status
205 *
206 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
207 *              state.
208 *
209 ******************************************************************************/
210
211ACPI_STATUS
212AcpiGetSleepTypeData (
213    UINT8                   SleepState,
214    UINT8                   *SleepTypeA,
215    UINT8                   *SleepTypeB)
216{
217    ACPI_STATUS             Status = AE_OK;
218    ACPI_PARAMETER_INFO     Info;
219
220
221    ACPI_FUNCTION_TRACE ("AcpiGetSleepTypeData");
222
223
224    /*
225     * Validate parameters
226     */
227    if ((SleepState > ACPI_S_STATES_MAX) ||
228        !SleepTypeA || !SleepTypeB)
229    {
230        return_ACPI_STATUS (AE_BAD_PARAMETER);
231    }
232
233    /*
234     * Evaluate the namespace object containing the values for this state
235     */
236    Info.Parameters = NULL;
237    Status = AcpiNsEvaluateByName ((char *) AcpiGbl_SleepStateNames[SleepState],
238                    &Info);
239    if (ACPI_FAILURE (Status))
240    {
241        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating SleepState [%s]\n",
242            AcpiFormatException (Status), AcpiGbl_SleepStateNames[SleepState]));
243
244        return_ACPI_STATUS (Status);
245    }
246
247    /* Must have a return object */
248
249    if (!Info.ReturnObject)
250    {
251        ACPI_REPORT_ERROR (("Missing Sleep State object\n"));
252        Status = AE_NOT_EXIST;
253    }
254
255    /* It must be of type Package */
256
257    else if (ACPI_GET_OBJECT_TYPE (Info.ReturnObject) != ACPI_TYPE_PACKAGE)
258    {
259        ACPI_REPORT_ERROR (("Sleep State object not a Package\n"));
260        Status = AE_AML_OPERAND_TYPE;
261    }
262
263    /* The package must have at least two elements */
264
265    else if (Info.ReturnObject->Package.Count < 2)
266    {
267        ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
268        Status = AE_AML_NO_OPERAND;
269    }
270
271    /* The first two elements must both be of type Integer */
272
273    else if ((ACPI_GET_OBJECT_TYPE (Info.ReturnObject->Package.Elements[0]) != ACPI_TYPE_INTEGER) ||
274             (ACPI_GET_OBJECT_TYPE (Info.ReturnObject->Package.Elements[1]) != ACPI_TYPE_INTEGER))
275    {
276        ACPI_REPORT_ERROR (("Sleep State package elements are not both Integers (%s, %s)\n",
277            AcpiUtGetObjectTypeName (Info.ReturnObject->Package.Elements[0]),
278            AcpiUtGetObjectTypeName (Info.ReturnObject->Package.Elements[1])));
279        Status = AE_AML_OPERAND_TYPE;
280    }
281    else
282    {
283        /*
284         * Valid _Sx_ package size, type, and value
285         */
286        *SleepTypeA = (UINT8) (Info.ReturnObject->Package.Elements[0])->Integer.Value;
287        *SleepTypeB = (UINT8) (Info.ReturnObject->Package.Elements[1])->Integer.Value;
288    }
289
290    if (ACPI_FAILURE (Status))
291    {
292        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
293            "While evaluating SleepState [%s], bad Sleep object %p type %s\n",
294            AcpiGbl_SleepStateNames[SleepState], Info.ReturnObject,
295            AcpiUtGetObjectTypeName (Info.ReturnObject)));
296    }
297
298    AcpiUtRemoveReference (Info.ReturnObject);
299    return_ACPI_STATUS (Status);
300}
301
302
303/*******************************************************************************
304 *
305 * FUNCTION:    AcpiHwGetRegisterBitMask
306 *
307 * PARAMETERS:  RegisterId          - Index of ACPI Register to access
308 *
309 * RETURN:      The bit mask to be used when accessing the register
310 *
311 * DESCRIPTION: Map RegisterId into a register bit mask.
312 *
313 ******************************************************************************/
314
315ACPI_BIT_REGISTER_INFO *
316AcpiHwGetBitRegisterInfo (
317    UINT32                  RegisterId)
318{
319    ACPI_FUNCTION_NAME ("HwGetBitRegisterInfo");
320
321
322    if (RegisterId > ACPI_BITREG_MAX)
323    {
324        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid BitRegister ID: %X\n", RegisterId));
325        return (NULL);
326    }
327
328    return (&AcpiGbl_BitRegisterInfo[RegisterId]);
329}
330
331
332/*******************************************************************************
333 *
334 * FUNCTION:    AcpiGetRegister
335 *
336 * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
337 *              ReturnValue     - Value that was read from the register
338 *              Flags           - Lock the hardware or not
339 *
340 * RETURN:      Value is read from specified Register.  Value returned is
341 *              normalized to bit0 (is shifted all the way right)
342 *
343 * DESCRIPTION: ACPI BitRegister read function.
344 *
345 ******************************************************************************/
346
347ACPI_STATUS
348AcpiGetRegister (
349    UINT32                  RegisterId,
350    UINT32                  *ReturnValue,
351    UINT32                  Flags)
352{
353    UINT32                  RegisterValue = 0;
354    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
355    ACPI_STATUS             Status;
356
357
358    ACPI_FUNCTION_TRACE ("AcpiGetRegister");
359
360
361    /* Get the info structure corresponding to the requested ACPI Register */
362
363    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
364    if (!BitRegInfo)
365    {
366        return_ACPI_STATUS (AE_BAD_PARAMETER);
367    }
368
369    if (Flags & ACPI_MTX_LOCK)
370    {
371        Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
372        if (ACPI_FAILURE (Status))
373        {
374            return_ACPI_STATUS (Status);
375        }
376    }
377
378    Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
379                    BitRegInfo->ParentRegister, &RegisterValue);
380
381    if (Flags & ACPI_MTX_LOCK)
382    {
383        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
384    }
385
386    if (ACPI_SUCCESS (Status))
387    {
388        /* Normalize the value that was read */
389
390        RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask)
391                            >> BitRegInfo->BitPosition);
392
393        *ReturnValue = RegisterValue;
394
395        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n",
396                RegisterValue, BitRegInfo->ParentRegister));
397    }
398
399    return_ACPI_STATUS (Status);
400}
401
402
403/*******************************************************************************
404 *
405 * FUNCTION:    AcpiSetRegister
406 *
407 * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
408 *              Value           - (only used on write) value to write to the
409 *                                Register, NOT pre-normalized to the bit pos.
410 *              Flags           - Lock the hardware or not
411 *
412 * RETURN:      None
413 *
414 * DESCRIPTION: ACPI Bit Register write function.
415 *
416 ******************************************************************************/
417
418ACPI_STATUS
419AcpiSetRegister (
420    UINT32                  RegisterId,
421    UINT32                  Value,
422    UINT32                  Flags)
423{
424    UINT32                  RegisterValue = 0;
425    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
426    ACPI_STATUS             Status;
427
428
429    ACPI_FUNCTION_TRACE_U32 ("AcpiSetRegister", RegisterId);
430
431
432    /* Get the info structure corresponding to the requested ACPI Register */
433
434    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
435    if (!BitRegInfo)
436    {
437        ACPI_REPORT_ERROR (("Bad ACPI HW RegisterId: %X\n", RegisterId));
438        return_ACPI_STATUS (AE_BAD_PARAMETER);
439    }
440
441    if (Flags & ACPI_MTX_LOCK)
442    {
443        Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
444        if (ACPI_FAILURE (Status))
445        {
446            return_ACPI_STATUS (Status);
447        }
448    }
449
450    /* Always do a register read first so we can insert the new bits  */
451
452    Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
453                    BitRegInfo->ParentRegister, &RegisterValue);
454    if (ACPI_FAILURE (Status))
455    {
456        goto UnlockAndExit;
457    }
458
459    /*
460     * Decode the Register ID
461     * Register ID = [Register block ID] | [bit ID]
462     *
463     * Check bit ID to fine locate Register offset.
464     * Check Mask to determine Register offset, and then read-write.
465     */
466    switch (BitRegInfo->ParentRegister)
467    {
468    case ACPI_REGISTER_PM1_STATUS:
469
470        /*
471         * Status Registers are different from the rest.  Clear by
472         * writing 1, and writing 0 has no effect.  So, the only relevant
473         * information is the single bit we're interested in, all others should
474         * be written as 0 so they will be left unchanged.
475         */
476        Value = ACPI_REGISTER_PREPARE_BITS (Value,
477                    BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
478        if (Value)
479        {
480            Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
481                        ACPI_REGISTER_PM1_STATUS, (UINT16) Value);
482            RegisterValue = 0;
483        }
484        break;
485
486
487    case ACPI_REGISTER_PM1_ENABLE:
488
489        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
490                BitRegInfo->AccessBitMask, Value);
491
492        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
493                        ACPI_REGISTER_PM1_ENABLE, (UINT16) RegisterValue);
494        break;
495
496
497    case ACPI_REGISTER_PM1_CONTROL:
498
499        /*
500         * Write the PM1 Control register.
501         * Note that at this level, the fact that there are actually TWO
502         * registers (A and B - and B may not exist) is abstracted.
503         */
504        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", RegisterValue));
505
506        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
507                BitRegInfo->AccessBitMask, Value);
508
509        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
510                        ACPI_REGISTER_PM1_CONTROL, (UINT16) RegisterValue);
511        break;
512
513
514    case ACPI_REGISTER_PM2_CONTROL:
515
516        Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
517                    ACPI_REGISTER_PM2_CONTROL, &RegisterValue);
518        if (ACPI_FAILURE (Status))
519        {
520            goto UnlockAndExit;
521        }
522
523        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
524            RegisterValue,
525            ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm2CntBlk.Address))));
526
527        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
528                BitRegInfo->AccessBitMask, Value);
529
530        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n",
531            RegisterValue,
532            ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm2CntBlk.Address))));
533
534        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
535                            ACPI_REGISTER_PM2_CONTROL, (UINT8) (RegisterValue));
536        break;
537
538
539    default:
540        break;
541    }
542
543
544UnlockAndExit:
545
546    if (Flags & ACPI_MTX_LOCK)
547    {
548        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
549    }
550
551    /* Normalize the value that was read */
552
553    ACPI_DEBUG_EXEC (RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask) >> BitRegInfo->BitPosition));
554
555    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n",
556            Value, RegisterValue, BitRegInfo->ParentRegister));
557    return_ACPI_STATUS (Status);
558}
559
560
561/******************************************************************************
562 *
563 * FUNCTION:    AcpiHwRegisterRead
564 *
565 * PARAMETERS:  UseLock                - Mutex hw access.
566 *              RegisterId             - RegisterID + Offset.
567 *
568 * RETURN:      Value read or written.
569 *
570 * DESCRIPTION: Acpi register read function.  Registers are read at the
571 *              given offset.
572 *
573 ******************************************************************************/
574
575ACPI_STATUS
576AcpiHwRegisterRead (
577    BOOLEAN                 UseLock,
578    UINT32                  RegisterId,
579    UINT32                  *ReturnValue)
580{
581    UINT32                  Value1 = 0;
582    UINT32                  Value2 = 0;
583    ACPI_STATUS             Status;
584
585
586    ACPI_FUNCTION_TRACE ("HwRegisterRead");
587
588
589    if (ACPI_MTX_LOCK == UseLock)
590    {
591        Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
592        if (ACPI_FAILURE (Status))
593        {
594            return_ACPI_STATUS (Status);
595        }
596    }
597
598    switch (RegisterId)
599    {
600    case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
601
602        Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT->XPm1aEvtBlk);
603        if (ACPI_FAILURE (Status))
604        {
605            goto UnlockAndExit;
606        }
607
608        /* PM1B is optional */
609
610        Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT->XPm1bEvtBlk);
611        Value1 |= Value2;
612        break;
613
614
615    case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access */
616
617        Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_XPm1aEnable);
618        if (ACPI_FAILURE (Status))
619        {
620            goto UnlockAndExit;
621        }
622
623        /* PM1B is optional */
624
625        Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_XPm1bEnable);
626        Value1 |= Value2;
627        break;
628
629
630    case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
631
632        Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT->XPm1aCntBlk);
633        if (ACPI_FAILURE (Status))
634        {
635            goto UnlockAndExit;
636        }
637
638        Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT->XPm1bCntBlk);
639        Value1 |= Value2;
640        break;
641
642
643    case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
644
645        Status = AcpiHwLowLevelRead (8, &Value1, &AcpiGbl_FADT->XPm2CntBlk);
646        break;
647
648
649    case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
650
651        Status = AcpiHwLowLevelRead (32, &Value1, &AcpiGbl_FADT->XPmTmrBlk);
652        break;
653
654    case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
655
656        Status = AcpiOsReadPort (AcpiGbl_FADT->SmiCmd, &Value1, 8);
657        break;
658
659    default:
660        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Register ID: %X\n", RegisterId));
661        Status = AE_BAD_PARAMETER;
662        break;
663    }
664
665UnlockAndExit:
666    if (ACPI_MTX_LOCK == UseLock)
667    {
668        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
669    }
670
671    if (ACPI_SUCCESS (Status))
672    {
673        *ReturnValue = Value1;
674    }
675
676    return_ACPI_STATUS (Status);
677}
678
679
680/******************************************************************************
681 *
682 * FUNCTION:    AcpiHwRegisterWrite
683 *
684 * PARAMETERS:  UseLock                - Mutex hw access.
685 *              RegisterId             - RegisterID + Offset.
686 *
687 * RETURN:      Value read or written.
688 *
689 * DESCRIPTION: Acpi register Write function.  Registers are written at the
690 *              given offset.
691 *
692 ******************************************************************************/
693
694ACPI_STATUS
695AcpiHwRegisterWrite (
696    BOOLEAN                 UseLock,
697    UINT32                  RegisterId,
698    UINT32                  Value)
699{
700    ACPI_STATUS             Status;
701
702
703    ACPI_FUNCTION_TRACE ("HwRegisterWrite");
704
705
706    if (ACPI_MTX_LOCK == UseLock)
707    {
708        Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
709        if (ACPI_FAILURE (Status))
710        {
711            return_ACPI_STATUS (Status);
712        }
713    }
714
715    switch (RegisterId)
716    {
717    case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
718
719        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk);
720        if (ACPI_FAILURE (Status))
721        {
722            goto UnlockAndExit;
723        }
724
725        /* PM1B is optional */
726
727        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk);
728        break;
729
730
731    case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access*/
732
733        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1aEnable);
734        if (ACPI_FAILURE (Status))
735        {
736            goto UnlockAndExit;
737        }
738
739        /* PM1B is optional */
740
741        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1bEnable);
742        break;
743
744
745    case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
746
747        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk);
748        if (ACPI_FAILURE (Status))
749        {
750            goto UnlockAndExit;
751        }
752
753        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk);
754        break;
755
756
757    case ACPI_REGISTER_PM1A_CONTROL:         /* 16-bit access */
758
759        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk);
760        break;
761
762
763    case ACPI_REGISTER_PM1B_CONTROL:         /* 16-bit access */
764
765        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk);
766        break;
767
768
769    case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
770
771        Status = AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XPm2CntBlk);
772        break;
773
774
775    case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
776
777        Status = AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT->XPmTmrBlk);
778        break;
779
780
781    case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
782
783        /* SMI_CMD is currently always in IO space */
784
785        Status = AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, Value, 8);
786        break;
787
788
789    default:
790        Status = AE_BAD_PARAMETER;
791        break;
792    }
793
794UnlockAndExit:
795    if (ACPI_MTX_LOCK == UseLock)
796    {
797        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
798    }
799
800    return_ACPI_STATUS (Status);
801}
802
803
804/******************************************************************************
805 *
806 * FUNCTION:    AcpiHwLowLevelRead
807 *
808 * PARAMETERS:  Width               - 8, 16, or 32
809 *              Value               - Where the value is returned
810 *              Register            - GAS register structure
811 *
812 * RETURN:      Status
813 *
814 * DESCRIPTION: Read from either memory, IO, or PCI config space.
815 *
816 ******************************************************************************/
817
818ACPI_STATUS
819AcpiHwLowLevelRead (
820    UINT32                  Width,
821    UINT32                  *Value,
822    ACPI_GENERIC_ADDRESS    *Reg)
823{
824    ACPI_PCI_ID             PciId;
825    UINT16                  PciRegister;
826    ACPI_STATUS             Status;
827
828
829    ACPI_FUNCTION_NAME ("HwLowLevelRead");
830
831
832    /*
833     * Must have a valid pointer to a GAS structure, and
834     * a non-zero address within. However, don't return an error
835     * because the PM1A/B code must not fail if B isn't present.
836     */
837    if ((!Reg) ||
838        (!ACPI_VALID_ADDRESS (Reg->Address)))
839    {
840        return (AE_OK);
841    }
842    *Value = 0;
843
844    /*
845     * Three address spaces supported:
846     * Memory, IO, or PCI_Config.
847     */
848    switch (Reg->AddressSpaceId)
849    {
850    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
851
852        Status = AcpiOsReadMemory (
853                    (ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (Reg->Address),
854                    Value, Width);
855        break;
856
857
858    case ACPI_ADR_SPACE_SYSTEM_IO:
859
860        Status = AcpiOsReadPort ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (Reg->Address),
861                    Value, Width);
862        break;
863
864
865    case ACPI_ADR_SPACE_PCI_CONFIG:
866
867        PciId.Segment  = 0;
868        PciId.Bus      = 0;
869        PciId.Device   = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (Reg->Address));
870        PciId.Function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (Reg->Address));
871        PciRegister    = (UINT16) ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address));
872
873        Status = AcpiOsReadPciConfiguration  (&PciId, PciRegister,
874                    Value, Width);
875        break;
876
877
878    default:
879        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
880            "Unsupported address space: %X\n", Reg->AddressSpaceId));
881        return (AE_BAD_PARAMETER);
882    }
883
884    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
885            *Value, Width,
886            ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (Reg->Address)),
887            AcpiUtGetRegionName (Reg->AddressSpaceId)));
888
889    return (Status);
890}
891
892
893/******************************************************************************
894 *
895 * FUNCTION:    AcpiHwLowLevelWrite
896 *
897 * PARAMETERS:  Width               - 8, 16, or 32
898 *              Value               - To be written
899 *              Register            - GAS register structure
900 *
901 * RETURN:      Status
902 *
903 * DESCRIPTION: Write to either memory, IO, or PCI config space.
904 *
905 ******************************************************************************/
906
907ACPI_STATUS
908AcpiHwLowLevelWrite (
909    UINT32                  Width,
910    UINT32                  Value,
911    ACPI_GENERIC_ADDRESS    *Reg)
912{
913    ACPI_PCI_ID             PciId;
914    UINT16                  PciRegister;
915    ACPI_STATUS             Status;
916
917
918    ACPI_FUNCTION_NAME ("HwLowLevelWrite");
919
920
921    /*
922     * Must have a valid pointer to a GAS structure, and
923     * a non-zero address within. However, don't return an error
924     * because the PM1A/B code must not fail if B isn't present.
925     */
926    if ((!Reg) ||
927        (!ACPI_VALID_ADDRESS (Reg->Address)))
928    {
929        return (AE_OK);
930    }
931
932    /*
933     * Three address spaces supported:
934     * Memory, IO, or PCI_Config.
935     */
936    switch (Reg->AddressSpaceId)
937    {
938    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
939
940        Status = AcpiOsWriteMemory (
941                    (ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (Reg->Address),
942                    Value, Width);
943        break;
944
945
946    case ACPI_ADR_SPACE_SYSTEM_IO:
947
948        Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (Reg->Address),
949                    Value, Width);
950        break;
951
952
953    case ACPI_ADR_SPACE_PCI_CONFIG:
954
955        PciId.Segment  = 0;
956        PciId.Bus      = 0;
957        PciId.Device   = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (Reg->Address));
958        PciId.Function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (Reg->Address));
959        PciRegister    = (UINT16) ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address));
960
961        Status = AcpiOsWritePciConfiguration (&PciId, PciRegister,
962                    (ACPI_INTEGER) Value, Width);
963        break;
964
965
966    default:
967        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
968            "Unsupported address space: %X\n", Reg->AddressSpaceId));
969        return (AE_BAD_PARAMETER);
970    }
971
972    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
973            Value, Width,
974            ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (Reg->Address)),
975            AcpiUtGetRegionName (Reg->AddressSpaceId)));
976
977    return (Status);
978}
979