hwregs.c revision 80062
1
2/*******************************************************************************
3 *
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 *                       control and status registers.
6 *              $Revision: 102 $
7 *
8 ******************************************************************************/
9
10/******************************************************************************
11 *
12 * 1. Copyright Notice
13 *
14 * Some or all of this work - Copyright (c) 1999, 2000, 2001, 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 "achware.h"
123#include "acnamesp.h"
124
125#define _COMPONENT          ACPI_HARDWARE
126        MODULE_NAME         ("hwregs")
127
128
129/* This matches the #defines in actypes.h. */
130
131NATIVE_CHAR                 *SleepStateTable[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_",
132                                                  "\\_S4_","\\_S5_","\\_S4B"};
133
134
135/*******************************************************************************
136 *
137 * FUNCTION:    AcpiHwGetBitShift
138 *
139 * PARAMETERS:  Mask            - Input mask to determine bit shift from.
140 *                                Must have at least 1 bit set.
141 *
142 * RETURN:      Bit location of the lsb of the mask
143 *
144 * DESCRIPTION: Returns the bit number for the low order bit that's set.
145 *
146 ******************************************************************************/
147
148UINT32
149AcpiHwGetBitShift (
150    UINT32                  Mask)
151{
152    UINT32                  Shift;
153
154
155    FUNCTION_TRACE ("HwGetBitShift");
156
157
158    for (Shift = 0; ((Mask >> Shift) & 1) == 0; Shift++)
159    { ; }
160
161    return_VALUE (Shift);
162}
163
164
165/*******************************************************************************
166 *
167 * FUNCTION:    AcpiHwClearAcpiStatus
168 *
169 * PARAMETERS:  none
170 *
171 * RETURN:      none
172 *
173 * DESCRIPTION: Clears all fixed and general purpose status bits
174 *
175 ******************************************************************************/
176
177void
178AcpiHwClearAcpiStatus (void)
179{
180    UINT16                  GpeLength;
181    UINT16                  Index;
182
183
184    FUNCTION_TRACE ("HwClearAcpiStatus");
185
186
187    DEBUG_PRINTP (TRACE_IO, ("About to write %04X to %04X\n",
188        ALL_FIXED_STS_BITS,
189        (UINT16) ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1aEvtBlk.Address)));
190
191
192    AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
193
194    AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, PM1_STS, ALL_FIXED_STS_BITS);
195
196
197    if (ACPI_VALID_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address))
198    {
199        AcpiOsWritePort ((ACPI_IO_ADDRESS)
200            ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address),
201            ALL_FIXED_STS_BITS, 16);
202    }
203
204    /* now clear the GPE Bits */
205
206    if (AcpiGbl_FADT->Gpe0BlkLen)
207    {
208        GpeLength = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe0BlkLen);
209
210        for (Index = 0; Index < GpeLength; Index++)
211        {
212            AcpiOsWritePort ((ACPI_IO_ADDRESS) (
213                ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe0Blk.Address) + Index),
214                    0xFF, 8);
215        }
216    }
217
218    if (AcpiGbl_FADT->Gpe1BlkLen)
219    {
220        GpeLength = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe1BlkLen);
221
222        for (Index = 0; Index < GpeLength; Index++)
223        {
224            AcpiOsWritePort ((ACPI_IO_ADDRESS) (
225                ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe1Blk.Address) + Index),
226                0xFF, 8);
227        }
228    }
229
230    AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
231    return_VOID;
232}
233
234
235/*******************************************************************************
236 *
237 * FUNCTION:    AcpiHwObtainSleepTypeRegisterData
238 *
239 * PARAMETERS:  SleepState        - Numeric state requested
240 *              *Slp_TypA         - Pointer to byte to receive SLP_TYPa value
241 *              *Slp_TypB         - Pointer to byte to receive SLP_TYPb value
242 *
243 * RETURN:      Status - ACPI status
244 *
245 * DESCRIPTION: AcpiHwObtainSleepTypeRegisterData() obtains the SLP_TYP and
246 *              SLP_TYPb values for the sleep state requested.
247 *
248 ******************************************************************************/
249
250ACPI_STATUS
251AcpiHwObtainSleepTypeRegisterData (
252    UINT8                   SleepState,
253    UINT8                   *Slp_TypA,
254    UINT8                   *Slp_TypB)
255{
256    ACPI_STATUS             Status = AE_OK;
257    ACPI_OPERAND_OBJECT     *ObjDesc;
258
259
260    FUNCTION_TRACE ("HwObtainSleepTypeRegisterData");
261
262
263    /*
264     *  Validate parameters
265     */
266
267    if ((SleepState > ACPI_S_STATES_MAX) ||
268        !Slp_TypA || !Slp_TypB)
269    {
270        return_ACPI_STATUS (AE_BAD_PARAMETER);
271    }
272
273    /*
274     *  AcpiEvaluate the namespace object containing the values for this state
275     */
276
277    Status = AcpiNsEvaluateByName (SleepStateTable[SleepState], NULL, &ObjDesc);
278    if (ACPI_FAILURE (Status))
279    {
280        return_ACPI_STATUS (Status);
281    }
282
283    if (!ObjDesc)
284    {
285        REPORT_ERROR (("Missing Sleep State object\n"));
286        return_ACPI_STATUS (AE_NOT_EXIST);
287    }
288
289    /*
290     *  We got something, now ensure it is correct.  The object must
291     *  be a package and must have at least 2 numeric values as the
292     *  two elements
293     */
294
295    /* Even though AcpiEvaluateObject resolves package references,
296     * NsEvaluate dpesn't. So, we do it here.
297     */
298    Status = AcpiUtResolvePackageReferences(ObjDesc);
299
300    if (ObjDesc->Package.Count < 2)
301    {
302        /* Must have at least two elements */
303
304        REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
305        Status = AE_ERROR;
306    }
307
308    else if (((ObjDesc->Package.Elements[0])->Common.Type !=
309                ACPI_TYPE_INTEGER) ||
310             ((ObjDesc->Package.Elements[1])->Common.Type !=
311                ACPI_TYPE_INTEGER))
312    {
313        /* Must have two  */
314
315        REPORT_ERROR (("Sleep State package elements are not both of type Number\n"));
316        Status = AE_ERROR;
317    }
318
319    else
320    {
321        /*
322         *  Valid _Sx_ package size, type, and value
323         */
324        *Slp_TypA = (UINT8) (ObjDesc->Package.Elements[0])->Integer.Value;
325
326        *Slp_TypB = (UINT8) (ObjDesc->Package.Elements[1])->Integer.Value;
327    }
328
329
330    if (ACPI_FAILURE (Status))
331    {
332        DEBUG_PRINTP (ACPI_ERROR, ("Bad Sleep object %p type %X\n",
333            ObjDesc, ObjDesc->Common.Type));
334    }
335
336    AcpiUtRemoveReference (ObjDesc);
337
338    return_ACPI_STATUS (Status);
339}
340
341
342/*******************************************************************************
343 *
344 * FUNCTION:    AcpiHwRegisterBitAccess
345 *
346 * PARAMETERS:  ReadWrite       - Either ACPI_READ or ACPI_WRITE.
347 *              UseLock         - Lock the hardware
348 *              RegisterId      - index of ACPI Register to access
349 *              Value           - (only used on write) value to write to the
350 *                                Register.  Shifted all the way right.
351 *
352 * RETURN:      Value written to or read from specified Register.  This value
353 *              is shifted all the way right.
354 *
355 * DESCRIPTION: Generic ACPI Register read/write function.
356 *
357 ******************************************************************************/
358
359UINT32
360AcpiHwRegisterBitAccess (
361    NATIVE_UINT             ReadWrite,
362    BOOLEAN                 UseLock,
363    UINT32                  RegisterId,
364    ...)                    /* Value (only used on write) */
365{
366    UINT32                  RegisterValue = 0;
367    UINT32                  Mask = 0;
368    UINT32                  Value = 0;
369    va_list                 marker;
370
371
372    FUNCTION_TRACE ("HwRegisterBitAccess");
373
374
375    if (ReadWrite == ACPI_WRITE)
376    {
377        va_start (marker, RegisterId);
378        Value = va_arg (marker, UINT32);
379        va_end (marker);
380    }
381
382    if (ACPI_MTX_LOCK == UseLock)
383    {
384        AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
385    }
386
387    /*
388     * Decode the Register ID
389     * Register id = Register block id | bit id
390     *
391     * Check bit id to fine locate Register offset.
392     * Check Mask to determine Register offset, and then read-write.
393     */
394
395    switch (REGISTER_BLOCK_ID (RegisterId))
396    {
397    case PM1_STS:
398
399        switch (RegisterId)
400        {
401        case TMR_STS:
402            Mask = TMR_STS_MASK;
403            break;
404
405        case BM_STS:
406            Mask = BM_STS_MASK;
407            break;
408
409        case GBL_STS:
410            Mask = GBL_STS_MASK;
411            break;
412
413        case PWRBTN_STS:
414            Mask = PWRBTN_STS_MASK;
415            break;
416
417        case SLPBTN_STS:
418            Mask = SLPBTN_STS_MASK;
419            break;
420
421        case RTC_STS:
422            Mask = RTC_STS_MASK;
423            break;
424
425        case WAK_STS:
426            Mask = WAK_STS_MASK;
427            break;
428
429        default:
430            Mask = 0;
431            break;
432        }
433
434        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
435
436        if (ReadWrite == ACPI_WRITE)
437        {
438            /*
439             * Status Registers are different from the rest.  Clear by
440             * writing 1, writing 0 has no effect.  So, the only relevent
441             * information is the single bit we're interested in, all
442             * others should be written as 0 so they will be left
443             * unchanged
444             */
445
446            Value <<= AcpiHwGetBitShift (Mask);
447            Value &= Mask;
448
449            if (Value)
450            {
451                AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, PM1_STS,
452                    (UINT16) Value);
453                RegisterValue = 0;
454            }
455        }
456
457        break;
458
459
460    case PM1_EN:
461
462        switch (RegisterId)
463        {
464        case TMR_EN:
465            Mask = TMR_EN_MASK;
466            break;
467
468        case GBL_EN:
469            Mask = GBL_EN_MASK;
470            break;
471
472        case PWRBTN_EN:
473            Mask = PWRBTN_EN_MASK;
474            break;
475
476        case SLPBTN_EN:
477            Mask = SLPBTN_EN_MASK;
478            break;
479
480        case RTC_EN:
481            Mask = RTC_EN_MASK;
482            break;
483
484        default:
485            Mask = 0;
486            break;
487        }
488
489        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_EN);
490
491        if (ReadWrite == ACPI_WRITE)
492        {
493            RegisterValue &= ~Mask;
494            Value          <<= AcpiHwGetBitShift (Mask);
495            Value          &= Mask;
496            RegisterValue |= Value;
497
498            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, PM1_EN, (UINT16) RegisterValue);
499        }
500
501        break;
502
503
504    case PM1_CONTROL:
505
506        switch (RegisterId)
507        {
508        case SCI_EN:
509            Mask = SCI_EN_MASK;
510            break;
511
512        case BM_RLD:
513            Mask = BM_RLD_MASK;
514            break;
515
516        case GBL_RLS:
517            Mask = GBL_RLS_MASK;
518            break;
519
520        case SLP_TYPE_A:
521        case SLP_TYPE_B:
522            Mask = SLP_TYPE_X_MASK;
523            break;
524
525        case SLP_EN:
526            Mask = SLP_EN_MASK;
527            break;
528
529        default:
530            Mask = 0;
531            break;
532        }
533
534
535        /*
536         * Read the PM1 Control register.
537         * Note that at this level, the fact that there are actually TWO
538         * registers (A and B) and that B may not exist, are abstracted.
539         */
540        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_CONTROL);
541
542        DEBUG_PRINT (TRACE_IO, ("PM1 control: Read %X\n", RegisterValue));
543
544        if (ReadWrite == ACPI_WRITE)
545        {
546            RegisterValue  &= ~Mask;
547            Value          <<= AcpiHwGetBitShift (Mask);
548            Value          &= Mask;
549            RegisterValue  |= Value;
550
551            /*
552             * SLP_TYPE_x Registers are written differently
553             * than any other control Registers with
554             * respect to A and B Registers.  The value
555             * for A may be different than the value for B
556             *
557             * Therefore, pass the RegisterId, not just generic PM1_CONTROL,
558             * because we need to do different things. Yuck.
559             */
560
561            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, RegisterId,
562                    (UINT16) RegisterValue);
563        }
564        break;
565
566
567    case PM2_CONTROL:
568
569        switch (RegisterId)
570        {
571        case ARB_DIS:
572            Mask = ARB_DIS_MASK;
573            break;
574
575        default:
576            Mask = 0;
577            break;
578        }
579
580        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);
581
582        DEBUG_PRINT (TRACE_IO, ("PM2 control: Read %X from %p\n",
583            RegisterValue, ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm2CntBlk.Address)));
584
585        if (ReadWrite == ACPI_WRITE)
586        {
587            RegisterValue  &= ~Mask;
588            Value          <<= AcpiHwGetBitShift (Mask);
589            Value          &= Mask;
590            RegisterValue  |= Value;
591
592            DEBUG_PRINT (TRACE_IO, ("About to write %04X to %p\n", RegisterValue,
593                AcpiGbl_FADT->XPm2CntBlk.Address));
594
595            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
596                                PM2_CONTROL, (UINT8) (RegisterValue));
597        }
598        break;
599
600
601    case PM_TIMER:
602
603        Mask = TMR_VAL_MASK;
604        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
605                                            PM_TIMER);
606        DEBUG_PRINT (TRACE_IO, ("PM_TIMER: Read %X from %p\n",
607            RegisterValue, ACPI_GET_ADDRESS (AcpiGbl_FADT->XPmTmrBlk.Address)));
608
609        break;
610
611
612    case GPE1_EN_BLOCK:
613    case GPE1_STS_BLOCK:
614    case GPE0_EN_BLOCK:
615    case GPE0_STS_BLOCK:
616
617        /* Determine the bit to be accessed
618         *
619         *  (UINT32) RegisterId:
620         *      31      24       16       8        0
621         *      +--------+--------+--------+--------+
622         *      |  gpe_block_id   |  gpe_bit_number |
623         *      +--------+--------+--------+--------+
624         *
625         *     gpe_block_id is one of GPE[01]_EN_BLOCK and GPE[01]_STS_BLOCK
626         *     gpe_bit_number is relative from the gpe_block (0x00~0xFF)
627         */
628
629        Mask = REGISTER_BIT_ID(RegisterId); /* gpe_bit_number */
630        RegisterId = REGISTER_BLOCK_ID(RegisterId) | (Mask >> 3);
631        Mask = AcpiGbl_DecodeTo8bit [Mask % 8];
632
633        /*
634         * The base address of the GPE 0 Register Block
635         * Plus 1/2 the length of the GPE 0 Register Block
636         * The enable Register is the Register following the Status Register
637         * and each Register is defined as 1/2 of the total Register Block
638         */
639
640        /*
641         * This sets the bit within EnableBit that needs to be written to
642         * the Register indicated in Mask to a 1, all others are 0
643         */
644
645        /* Now get the current Enable Bits in the selected Reg */
646
647        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, RegisterId);
648        DEBUG_PRINT (TRACE_IO, ("GPE Enable bits: Read %X from %X\n",
649            RegisterValue, RegisterId));
650
651        if (ReadWrite == ACPI_WRITE)
652        {
653            RegisterValue  &= ~Mask;
654            Value          <<= AcpiHwGetBitShift (Mask);
655            Value          &= Mask;
656            RegisterValue  |= Value;
657
658            /* This write will put the Action state into the General Purpose */
659            /* Enable Register indexed by the value in Mask */
660
661            DEBUG_PRINT (TRACE_IO, ("About to write %04X to %04X\n",
662                RegisterValue, RegisterId));
663            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, RegisterId,
664                (UINT8) RegisterValue);
665            RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
666                                RegisterId);
667        }
668        break;
669
670
671    case SMI_CMD_BLOCK:
672    case PROCESSOR_BLOCK:
673        /* Not used by any callers at this time - therefore, not implemented */
674
675    default:
676
677        Mask = 0;
678        break;
679    }
680
681    if (ACPI_MTX_LOCK == UseLock) {
682        AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
683    }
684
685
686    RegisterValue &= Mask;
687    RegisterValue >>= AcpiHwGetBitShift (Mask);
688
689    DEBUG_PRINT (TRACE_IO, ("Register I/O: returning %X\n", RegisterValue));
690    return_VALUE (RegisterValue);
691}
692
693
694/******************************************************************************
695 *
696 * FUNCTION:    AcpiHwRegisterRead
697 *
698 * PARAMETERS:  UseLock                - Mutex hw access.
699 *              RegisterId             - RegisterID + Offset.
700 *
701 * RETURN:      Value read or written.
702 *
703 * DESCRIPTION: Acpi register read function.  Registers are read at the
704 *              given offset.
705 *
706 ******************************************************************************/
707
708UINT32
709AcpiHwRegisterRead (
710    BOOLEAN                 UseLock,
711    UINT32                  RegisterId)
712{
713    UINT32                  Value = 0;
714    UINT32                  BankOffset;
715
716
717    FUNCTION_TRACE ("AcpiHwRegisterRead");
718
719
720    if (ACPI_MTX_LOCK == UseLock)
721    {
722        AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
723    }
724
725
726    switch (REGISTER_BLOCK_ID(RegisterId))
727    {
728    case PM1_STS: /* 16-bit access */
729
730        Value =  AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aEvtBlk, 0);
731        Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bEvtBlk, 0);
732        break;
733
734
735    case PM1_EN: /* 16-bit access*/
736
737        BankOffset  = DIV_2 (AcpiGbl_FADT->Pm1EvtLen);
738        Value =  AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aEvtBlk, BankOffset);
739        Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bEvtBlk, BankOffset);
740        break;
741
742
743    case PM1_CONTROL: /* 16-bit access */
744
745        Value =  AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aCntBlk, 0);
746        Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bCntBlk, 0);
747        break;
748
749
750    case PM2_CONTROL: /* 8-bit access */
751
752        Value =  AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XPm2CntBlk, 0);
753        break;
754
755
756    case PM_TIMER: /* 32-bit access */
757
758        Value =  AcpiHwLowLevelRead (32, &AcpiGbl_FADT->XPmTmrBlk, 0);
759        break;
760
761
762    case GPE0_STS_BLOCK: /* 8-bit access */
763
764        Value =  AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe0Blk, 0);
765        break;
766
767
768    case GPE0_EN_BLOCK: /* 8-bit access */
769
770        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe0BlkLen);
771        Value =  AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe0Blk, BankOffset);
772        break;
773
774
775    case GPE1_STS_BLOCK: /* 8-bit access */
776
777        Value =  AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe1Blk, 0);
778        break;
779
780
781    case GPE1_EN_BLOCK: /* 8-bit access */
782
783        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe1BlkLen);
784        Value =  AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe1Blk, BankOffset);
785        break;
786
787
788    case SMI_CMD_BLOCK: /* 8bit */
789
790        AcpiOsReadPort (AcpiGbl_FADT->SmiCmd, &Value, 8);
791        break;
792
793
794    default:
795        /* Value will be returned as 0 */
796        break;
797    }
798
799
800    if (ACPI_MTX_LOCK == UseLock)
801    {
802        AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
803    }
804
805    return_VALUE (Value);
806}
807
808
809/******************************************************************************
810 *
811 * FUNCTION:    AcpiHwRegisterWrite
812 *
813 * PARAMETERS:  UseLock                - Mutex hw access.
814 *              RegisterId             - RegisterID + Offset.
815 *
816 * RETURN:      Value read or written.
817 *
818 * DESCRIPTION: Acpi register Write function.  Registers are written at the
819 *              given offset.
820 *
821 ******************************************************************************/
822
823void
824AcpiHwRegisterWrite (
825    BOOLEAN                 UseLock,
826    UINT32                  RegisterId,
827    UINT32                  Value)
828{
829    UINT32                  BankOffset;
830
831    FUNCTION_TRACE ("AcpiHwRegisterWrite");
832
833
834    if (ACPI_MTX_LOCK == UseLock)
835    {
836        AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
837    }
838
839
840    switch (REGISTER_BLOCK_ID (RegisterId))
841    {
842    case PM1_STS: /* 16-bit access */
843
844        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk, 0);
845        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk, 0);
846        break;
847
848
849    case PM1_EN: /* 16-bit access*/
850
851        BankOffset = DIV_2 (AcpiGbl_FADT->Pm1EvtLen);
852        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk, BankOffset);
853        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk, BankOffset);
854        break;
855
856
857    case PM1_CONTROL: /* 16-bit access */
858
859        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk, 0);
860        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk, 0);
861        break;
862
863
864    case PM1A_CONTROL: /* 16-bit access */
865
866        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk, 0);
867        break;
868
869
870    case PM1B_CONTROL: /* 16-bit access */
871
872        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk, 0);
873        break;
874
875
876    case PM2_CONTROL: /* 8-bit access */
877
878        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XPm2CntBlk, 0);
879        break;
880
881
882    case PM_TIMER: /* 32-bit access */
883
884        AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT->XPmTmrBlk, 0);
885        break;
886
887
888    case GPE0_STS_BLOCK: /* 8-bit access */
889
890        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe0Blk, 0);
891        break;
892
893
894    case GPE0_EN_BLOCK: /* 8-bit access */
895
896        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe0BlkLen);
897        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe0Blk, BankOffset);
898        break;
899
900
901    case GPE1_STS_BLOCK: /* 8-bit access */
902
903        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe1Blk, 0);
904        break;
905
906
907    case GPE1_EN_BLOCK: /* 8-bit access */
908
909        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe1BlkLen);
910        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe1Blk, BankOffset);
911        break;
912
913
914    case SMI_CMD_BLOCK: /* 8bit */
915
916        /* For 2.0, SMI_CMD is always in IO space */
917        /* TBD: what about 1.0? 0.71? */
918
919        AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, Value, 8);
920        break;
921
922
923    default:
924        Value = 0;
925        break;
926    }
927
928
929    if (ACPI_MTX_LOCK == UseLock)
930    {
931        AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
932    }
933
934    return_VOID;
935}
936
937
938/******************************************************************************
939 *
940 * FUNCTION:    AcpiHwLowLevelRead
941 *
942 * PARAMETERS:  Register            - GAS register structure
943 *              Offset              - Offset from the base address in the GAS
944 *              Width               - 8, 16, or 32
945 *
946 * RETURN:      Value read
947 *
948 * DESCRIPTION: Read from either memory, IO, or PCI config space.
949 *
950 ******************************************************************************/
951
952UINT32
953AcpiHwLowLevelRead (
954    UINT32                  Width,
955    ACPI_GENERIC_ADDRESS    *Reg,
956    UINT32                  Offset)
957{
958    UINT32                  Value = 0;
959    ACPI_PHYSICAL_ADDRESS   MemAddress;
960    ACPI_IO_ADDRESS         IoAddress;
961    ACPI_PCI_ID             PciId;
962    UINT16                  PciRegister;
963
964
965    /*
966     * Must have a valid pointer to a GAS structure, and
967     * a non-zero address within
968     */
969    if ((!Reg) ||
970        (!ACPI_VALID_ADDRESS (Reg->Address)))
971    {
972        return 0;
973    }
974
975
976    /*
977     * Three address spaces supported:
978     * Memory, Io, or PCI config.
979     */
980
981    switch (Reg->AddressSpaceId)
982    {
983    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
984
985        MemAddress = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
986
987        AcpiOsReadMemory (MemAddress, &Value, Width);
988        break;
989
990
991    case ACPI_ADR_SPACE_SYSTEM_IO:
992
993        IoAddress = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
994
995        AcpiOsReadPort (IoAddress, &Value, Width);
996        break;
997
998
999    case ACPI_ADR_SPACE_PCI_CONFIG:
1000
1001        PciId.Segment  = 0;
1002        PciId.Bus      = 0;
1003        PciId.Device   = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (Reg->Address));
1004        PciId.Function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (Reg->Address));
1005        PciRegister    = (UINT16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address)) + Offset);
1006
1007        AcpiOsReadPciConfiguration  (&PciId, PciRegister, &Value, Width);
1008        break;
1009    }
1010
1011    return Value;
1012}
1013
1014
1015/******************************************************************************
1016 *
1017 * FUNCTION:    AcpiHwLowLevelWrite
1018 *
1019 * PARAMETERS:  Width               - 8, 16, or 32
1020 *              Value               - To be written
1021 *              Register            - GAS register structure
1022 *              Offset              - Offset from the base address in the GAS
1023 *
1024 *
1025 * RETURN:      Value read
1026 *
1027 * DESCRIPTION: Read from either memory, IO, or PCI config space.
1028 *
1029 ******************************************************************************/
1030
1031void
1032AcpiHwLowLevelWrite (
1033    UINT32                  Width,
1034    UINT32                  Value,
1035    ACPI_GENERIC_ADDRESS    *Reg,
1036    UINT32                  Offset)
1037{
1038    ACPI_PHYSICAL_ADDRESS   MemAddress;
1039    ACPI_IO_ADDRESS         IoAddress;
1040    ACPI_PCI_ID             PciId;
1041    UINT16                  PciRegister;
1042
1043
1044    /*
1045     * Must have a valid pointer to a GAS structure, and
1046     * a non-zero address within
1047     */
1048    if ((!Reg) ||
1049        (!ACPI_VALID_ADDRESS (Reg->Address)))
1050    {
1051        return;
1052    }
1053
1054
1055    /*
1056     * Three address spaces supported:
1057     * Memory, Io, or PCI config.
1058     */
1059
1060    switch (Reg->AddressSpaceId)
1061    {
1062    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1063
1064        MemAddress = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
1065
1066        AcpiOsWriteMemory (MemAddress, Value, Width);
1067        break;
1068
1069
1070    case ACPI_ADR_SPACE_SYSTEM_IO:
1071
1072        IoAddress = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
1073
1074        AcpiOsWritePort (IoAddress, Value, Width);
1075        break;
1076
1077
1078    case ACPI_ADR_SPACE_PCI_CONFIG:
1079
1080        PciId.Segment  = 0;
1081        PciId.Bus      = 0;
1082        PciId.Device   = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (Reg->Address));
1083        PciId.Function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (Reg->Address));
1084        PciRegister    = (UINT16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address)) + Offset);
1085
1086        AcpiOsWritePciConfiguration (&PciId, PciRegister, Value, Width);
1087        break;
1088    }
1089}
1090