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