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