hwregs.c revision 83174
1
2/*******************************************************************************
3 *
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 *                       control and status registers.
6 *              $Revision: 109 $
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 %p\n",
573            RegisterValue, ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm2CntBlk.Address)));
574
575        if (ReadWrite == ACPI_WRITE)
576        {
577            RegisterValue  &= ~Mask;
578            Value          <<= AcpiHwGetBitShift (Mask);
579            Value          &= Mask;
580            RegisterValue  |= Value;
581
582            ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %p\n", RegisterValue,
583                AcpiGbl_FADT->XPm2CntBlk.Address));
584
585            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
586                                PM2_CONTROL, (UINT8) (RegisterValue));
587        }
588        break;
589
590
591    case PM_TIMER:
592
593        Mask = TMR_VAL_MASK;
594        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
595                                            PM_TIMER);
596        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM_TIMER: Read %X from %p\n",
597            RegisterValue, ACPI_GET_ADDRESS (AcpiGbl_FADT->XPmTmrBlk.Address)));
598
599        break;
600
601
602    case GPE1_EN_BLOCK:
603    case GPE1_STS_BLOCK:
604    case GPE0_EN_BLOCK:
605    case GPE0_STS_BLOCK:
606
607        /* Determine the bit to be accessed
608         *
609         *  (UINT32) RegisterId:
610         *      31      24       16       8        0
611         *      +--------+--------+--------+--------+
612         *      |  gpe_block_id   |  gpe_bit_number |
613         *      +--------+--------+--------+--------+
614         *
615         *     gpe_block_id is one of GPE[01]_EN_BLOCK and GPE[01]_STS_BLOCK
616         *     gpe_bit_number is relative from the gpe_block (0x00~0xFF)
617         */
618        Mask = REGISTER_BIT_ID(RegisterId); /* gpe_bit_number */
619        RegisterId = REGISTER_BLOCK_ID(RegisterId) | (Mask >> 3);
620        Mask = AcpiGbl_DecodeTo8bit [Mask % 8];
621
622        /*
623         * The base address of the GPE 0 Register Block
624         * Plus 1/2 the length of the GPE 0 Register Block
625         * The enable Register is the Register following the Status Register
626         * and each Register is defined as 1/2 of the total Register Block
627         */
628
629        /*
630         * This sets the bit within EnableBit that needs to be written to
631         * the Register indicated in Mask to a 1, all others are 0
632         */
633
634        /* Now get the current Enable Bits in the selected Reg */
635
636        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, RegisterId);
637        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "GPE Enable bits: Read %X from %X\n",
638            RegisterValue, RegisterId));
639
640        if (ReadWrite == ACPI_WRITE)
641        {
642            RegisterValue  &= ~Mask;
643            Value          <<= AcpiHwGetBitShift (Mask);
644            Value          &= Mask;
645            RegisterValue  |= Value;
646
647            /*
648             * This write will put the Action state into the General Purpose
649             * Enable Register indexed by the value in Mask
650             */
651            ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
652                RegisterValue, RegisterId));
653            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, RegisterId,
654                (UINT8) RegisterValue);
655            RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
656                                RegisterId);
657        }
658        break;
659
660
661    case SMI_CMD_BLOCK:
662    case PROCESSOR_BLOCK:
663
664        /* Not used by any callers at this time - therefore, not implemented */
665
666    default:
667
668        Mask = 0;
669        break;
670    }
671
672    if (ACPI_MTX_LOCK == UseLock) {
673        AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
674    }
675
676
677    RegisterValue &= Mask;
678    RegisterValue >>= AcpiHwGetBitShift (Mask);
679
680    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Register I/O: returning %X\n", RegisterValue));
681    return_VALUE (RegisterValue);
682}
683
684
685/******************************************************************************
686 *
687 * FUNCTION:    AcpiHwRegisterRead
688 *
689 * PARAMETERS:  UseLock                - Mutex hw access.
690 *              RegisterId             - RegisterID + Offset.
691 *
692 * RETURN:      Value read or written.
693 *
694 * DESCRIPTION: Acpi register read function.  Registers are read at the
695 *              given offset.
696 *
697 ******************************************************************************/
698
699UINT32
700AcpiHwRegisterRead (
701    BOOLEAN                 UseLock,
702    UINT32                  RegisterId)
703{
704    UINT32                  Value = 0;
705    UINT32                  BankOffset;
706
707
708    FUNCTION_TRACE ("HwRegisterRead");
709
710
711    if (ACPI_MTX_LOCK == UseLock)
712    {
713        AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
714    }
715
716
717    switch (REGISTER_BLOCK_ID(RegisterId))
718    {
719    case PM1_STS: /* 16-bit access */
720
721        Value =  AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aEvtBlk, 0);
722        Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bEvtBlk, 0);
723        break;
724
725
726    case PM1_EN: /* 16-bit access*/
727
728        BankOffset  = DIV_2 (AcpiGbl_FADT->Pm1EvtLen);
729        Value =  AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aEvtBlk, BankOffset);
730        Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bEvtBlk, BankOffset);
731        break;
732
733
734    case PM1_CONTROL: /* 16-bit access */
735
736        Value =  AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aCntBlk, 0);
737        Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bCntBlk, 0);
738        break;
739
740
741    case PM2_CONTROL: /* 8-bit access */
742
743        Value =  AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XPm2CntBlk, 0);
744        break;
745
746
747    case PM_TIMER: /* 32-bit access */
748
749        Value =  AcpiHwLowLevelRead (32, &AcpiGbl_FADT->XPmTmrBlk, 0);
750        break;
751
752
753    /*
754     * For the GPE? Blocks, the lower word of RegisterId contains the
755     * byte offset for which to read, as each part of each block may be
756     * several bytes long.
757     */
758    case GPE0_STS_BLOCK: /* 8-bit access */
759
760        BankOffset = REGISTER_BIT_ID(RegisterId);
761        Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe0Blk, BankOffset);
762        break;
763
764    case GPE0_EN_BLOCK: /* 8-bit access */
765
766        BankOffset = DIV_2 (AcpiGbl_FADT->Gpe0BlkLen) + REGISTER_BIT_ID(RegisterId);
767        Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe0Blk, BankOffset);
768        break;
769
770    case GPE1_STS_BLOCK: /* 8-bit access */
771
772        BankOffset = REGISTER_BIT_ID(RegisterId);
773        Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe1Blk, BankOffset);
774        break;
775
776    case GPE1_EN_BLOCK: /* 8-bit access */
777
778        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe1BlkLen) + REGISTER_BIT_ID(RegisterId);
779        Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe1Blk, BankOffset);
780        break;
781
782    case SMI_CMD_BLOCK: /* 8bit */
783
784        AcpiOsReadPort (AcpiGbl_FADT->SmiCmd, &Value, 8);
785        break;
786
787    default:
788        /* Value will be returned as 0 */
789        break;
790    }
791
792
793    if (ACPI_MTX_LOCK == UseLock)
794    {
795        AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
796    }
797
798    return_VALUE (Value);
799}
800
801
802/******************************************************************************
803 *
804 * FUNCTION:    AcpiHwRegisterWrite
805 *
806 * PARAMETERS:  UseLock                - Mutex hw access.
807 *              RegisterId             - RegisterID + Offset.
808 *
809 * RETURN:      Value read or written.
810 *
811 * DESCRIPTION: Acpi register Write function.  Registers are written at the
812 *              given offset.
813 *
814 ******************************************************************************/
815
816void
817AcpiHwRegisterWrite (
818    BOOLEAN                 UseLock,
819    UINT32                  RegisterId,
820    UINT32                  Value)
821{
822    UINT32                  BankOffset;
823
824
825    FUNCTION_TRACE ("HwRegisterWrite");
826
827
828    if (ACPI_MTX_LOCK == UseLock)
829    {
830        AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
831    }
832
833
834    switch (REGISTER_BLOCK_ID (RegisterId))
835    {
836    case PM1_STS: /* 16-bit access */
837
838        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk, 0);
839        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk, 0);
840        break;
841
842
843    case PM1_EN: /* 16-bit access*/
844
845        BankOffset = DIV_2 (AcpiGbl_FADT->Pm1EvtLen);
846        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk, BankOffset);
847        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk, BankOffset);
848        break;
849
850
851    case PM1_CONTROL: /* 16-bit access */
852
853        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk, 0);
854        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk, 0);
855        break;
856
857
858    case PM1A_CONTROL: /* 16-bit access */
859
860        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk, 0);
861        break;
862
863
864    case PM1B_CONTROL: /* 16-bit access */
865
866        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk, 0);
867        break;
868
869
870    case PM2_CONTROL: /* 8-bit access */
871
872        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XPm2CntBlk, 0);
873        break;
874
875
876    case PM_TIMER: /* 32-bit access */
877
878        AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT->XPmTmrBlk, 0);
879        break;
880
881
882    case GPE0_STS_BLOCK: /* 8-bit access */
883
884        BankOffset = REGISTER_BIT_ID(RegisterId);
885        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe0Blk, BankOffset);
886        break;
887
888
889    case GPE0_EN_BLOCK: /* 8-bit access */
890
891        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe0BlkLen) + REGISTER_BIT_ID(RegisterId);
892        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe0Blk, BankOffset);
893        break;
894
895
896    case GPE1_STS_BLOCK: /* 8-bit access */
897
898        BankOffset = REGISTER_BIT_ID(RegisterId);
899        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe1Blk, BankOffset);
900        break;
901
902
903    case GPE1_EN_BLOCK: /* 8-bit access */
904
905        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe1BlkLen) + REGISTER_BIT_ID(RegisterId);
906        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe1Blk, BankOffset);
907        break;
908
909
910    case SMI_CMD_BLOCK: /* 8bit */
911
912        /* For 2.0, SMI_CMD is always in IO space */
913        /* TBD: what about 1.0? 0.71? */
914
915        AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, Value, 8);
916        break;
917
918
919    default:
920        Value = 0;
921        break;
922    }
923
924
925    if (ACPI_MTX_LOCK == UseLock)
926    {
927        AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
928    }
929
930    return_VOID;
931}
932
933
934/******************************************************************************
935 *
936 * FUNCTION:    AcpiHwLowLevelRead
937 *
938 * PARAMETERS:  Register            - GAS register structure
939 *              Offset              - Offset from the base address in the GAS
940 *              Width               - 8, 16, or 32
941 *
942 * RETURN:      Value read
943 *
944 * DESCRIPTION: Read from either memory, IO, or PCI config space.
945 *
946 ******************************************************************************/
947
948UINT32
949AcpiHwLowLevelRead (
950    UINT32                  Width,
951    ACPI_GENERIC_ADDRESS    *Reg,
952    UINT32                  Offset)
953{
954    UINT32                  Value = 0;
955    ACPI_PHYSICAL_ADDRESS   MemAddress;
956    ACPI_IO_ADDRESS         IoAddress;
957    ACPI_PCI_ID             PciId;
958    UINT16                  PciRegister;
959
960
961    FUNCTION_ENTRY ();
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    switch (Reg->AddressSpaceId)
980    {
981    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
982
983        MemAddress = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
984
985        AcpiOsReadMemory (MemAddress, &Value, Width);
986        break;
987
988
989    case ACPI_ADR_SPACE_SYSTEM_IO:
990
991        IoAddress = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
992
993        AcpiOsReadPort (IoAddress, &Value, Width);
994        break;
995
996
997    case ACPI_ADR_SPACE_PCI_CONFIG:
998
999        PciId.Segment  = 0;
1000        PciId.Bus      = 0;
1001        PciId.Device   = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (Reg->Address));
1002        PciId.Function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (Reg->Address));
1003        PciRegister    = (UINT16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address)) + Offset);
1004
1005        AcpiOsReadPciConfiguration  (&PciId, PciRegister, &Value, Width);
1006        break;
1007    }
1008
1009    return Value;
1010}
1011
1012
1013/******************************************************************************
1014 *
1015 * FUNCTION:    AcpiHwLowLevelWrite
1016 *
1017 * PARAMETERS:  Width               - 8, 16, or 32
1018 *              Value               - To be written
1019 *              Register            - GAS register structure
1020 *              Offset              - Offset from the base address in the GAS
1021 *
1022 *
1023 * RETURN:      Value read
1024 *
1025 * DESCRIPTION: Read from either memory, IO, or PCI config space.
1026 *
1027 ******************************************************************************/
1028
1029void
1030AcpiHwLowLevelWrite (
1031    UINT32                  Width,
1032    UINT32                  Value,
1033    ACPI_GENERIC_ADDRESS    *Reg,
1034    UINT32                  Offset)
1035{
1036    ACPI_PHYSICAL_ADDRESS   MemAddress;
1037    ACPI_IO_ADDRESS         IoAddress;
1038    ACPI_PCI_ID             PciId;
1039    UINT16                  PciRegister;
1040
1041
1042    FUNCTION_ENTRY ();
1043
1044
1045    /*
1046     * Must have a valid pointer to a GAS structure, and
1047     * a non-zero address within
1048     */
1049    if ((!Reg) ||
1050        (!ACPI_VALID_ADDRESS (Reg->Address)))
1051    {
1052        return;
1053    }
1054
1055
1056    /*
1057     * Three address spaces supported:
1058     * Memory, Io, or PCI config.
1059     */
1060    switch (Reg->AddressSpaceId)
1061    {
1062    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1063
1064        MemAddress = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
1065
1066        AcpiOsWriteMemory (MemAddress, Value, Width);
1067        break;
1068
1069
1070    case ACPI_ADR_SPACE_SYSTEM_IO:
1071
1072        IoAddress = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
1073
1074        AcpiOsWritePort (IoAddress, Value, Width);
1075        break;
1076
1077
1078    case ACPI_ADR_SPACE_PCI_CONFIG:
1079
1080        PciId.Segment  = 0;
1081        PciId.Bus      = 0;
1082        PciId.Device   = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (Reg->Address));
1083        PciId.Function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (Reg->Address));
1084        PciRegister    = (UINT16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address)) + Offset);
1085
1086        AcpiOsWritePciConfiguration (&PciId, PciRegister, Value, Width);
1087        break;
1088    }
1089}
1090