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