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