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