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