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