hwregs.c revision 71867
1
2/*******************************************************************************
3 *
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 *                       control and status registers.
6 *              $Revision: 88 $
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          HARDWARE
126        MODULE_NAME         ("hwregs")
127
128
129/* This matches the #defines in actypes.h. */
130
131NATIVE_CHAR                 *SleepStateTable[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_",
132                                                  "\\_S4_","\\_S5_","\\_S4B"};
133
134
135/*******************************************************************************
136 *
137 * FUNCTION:    AcpiHwGetBitShift
138 *
139 * PARAMETERS:  Mask            - Input mask to determine bit shift from.
140 *                                Must have at least 1 bit set.
141 *
142 * RETURN:      Bit location of the lsb of the mask
143 *
144 * DESCRIPTION: Returns the bit number for the low order bit that's set.
145 *
146 ******************************************************************************/
147
148UINT32
149AcpiHwGetBitShift (
150    UINT32                  Mask)
151{
152    UINT32                  Shift;
153
154
155    FUNCTION_TRACE ("HwGetBitShift");
156
157
158    for (Shift = 0; ((Mask >> Shift) & 1) == 0; Shift++)
159    { ; }
160
161    return_VALUE (Shift);
162}
163
164
165/*******************************************************************************
166 *
167 * FUNCTION:    AcpiHwClearAcpiStatus
168 *
169 * PARAMETERS:  none
170 *
171 * RETURN:      none
172 *
173 * DESCRIPTION: Clears all fixed and general purpose status bits
174 *
175 ******************************************************************************/
176
177void
178AcpiHwClearAcpiStatus (void)
179{
180    UINT16                  GpeLength;
181    UINT16                  Index;
182
183
184    FUNCTION_TRACE ("HwClearAcpiStatus");
185
186
187    DEBUG_PRINT (TRACE_IO, ("About to write %04X to %04X\n",
188                    ALL_FIXED_STS_BITS,
189                    (UINT16) ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1aEvtBlk.Address)));
190
191
192    AcpiCmAcquireMutex (ACPI_MTX_HARDWARE);
193
194    AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, PM1_STS, ALL_FIXED_STS_BITS);
195
196
197    if (ACPI_VALID_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address))
198    {
199        AcpiOsOut16 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address),
200                        (UINT16) ALL_FIXED_STS_BITS);
201    }
202
203    /* now clear the GPE Bits */
204
205    if (AcpiGbl_FADT->Gpe0BlkLen)
206    {
207        GpeLength = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe0BlkLen);
208
209        for (Index = 0; Index < GpeLength; Index++)
210        {
211            AcpiOsOut8 ((ACPI_IO_ADDRESS) (ACPI_GET_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) (ACPI_GET_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_INTEGER) ||
304             ((ObjDesc->Package.Elements[1])->Common.Type !=
305                ACPI_TYPE_INTEGER))
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])->Integer.Value;
319
320        *Slp_TypB = (UINT8) (ObjDesc->Package.Elements[1])->Integer.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 %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             * Therefore, pass the RegisterId, not just generic PM1_CONTROL,
552             * because we need to do different things. Yuck.
553             */
554
555            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
556                RegisterId, (UINT16) RegisterValue);
557        }
558        break;
559
560
561    case PM2_CONTROL:
562
563        switch (RegisterId)
564        {
565        case ARB_DIS:
566            Mask = ARB_DIS_MASK;
567            break;
568
569        default:
570            Mask = 0;
571            break;
572        }
573
574        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);
575
576        DEBUG_PRINT (TRACE_IO, ("PM2 control: Read %X from %p\n",
577                        RegisterValue, ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm2CntBlk.Address)));
578
579        if (ReadWrite == ACPI_WRITE)
580        {
581            RegisterValue  &= ~Mask;
582            Value          <<= AcpiHwGetBitShift (Mask);
583            Value          &= Mask;
584            RegisterValue  |= Value;
585
586            DEBUG_PRINT (TRACE_IO,
587                ("About to write %04X to %p\n", RegisterValue,
588                AcpiGbl_FADT->XPm2CntBlk.Address));
589
590            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
591                                PM2_CONTROL, (UINT8) (RegisterValue));
592        }
593        break;
594
595
596    case PM_TIMER:
597
598        Mask = TMR_VAL_MASK;
599        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
600                                            PM_TIMER);
601        DEBUG_PRINT (TRACE_IO, ("PM_TIMER: Read %X from %p\n",
602                        RegisterValue, ACPI_GET_ADDRESS (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
624        Mask = REGISTER_BIT_ID(RegisterId); /* gpe_bit_number */
625        RegisterId = REGISTER_BLOCK_ID(RegisterId) | (Mask >> 3);
626        Mask = AcpiGbl_DecodeTo8bit [Mask % 8];
627
628        /*
629         * The base address of the GPE 0 Register Block
630         * Plus 1/2 the length of the GPE 0 Register Block
631         * The enable Register is the Register following the Status Register
632         * and each Register is defined as 1/2 of the total Register Block
633         */
634
635        /*
636         * This sets the bit within EnableBit that needs to be written to
637         * the Register indicated in Mask to a 1, all others are 0
638         */
639
640        /* Now get the current Enable Bits in the selected Reg */
641
642        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, RegisterId);
643        DEBUG_PRINT (TRACE_IO, ("GPE Enable bits: Read %X from %X\n",
644                                RegisterValue, RegisterId));
645
646        if (ReadWrite == ACPI_WRITE)
647        {
648            RegisterValue  &= ~Mask;
649            Value          <<= AcpiHwGetBitShift (Mask);
650            Value          &= Mask;
651            RegisterValue  |= Value;
652
653            /* This write will put the Action state into the General Purpose */
654            /* Enable Register indexed by the value in Mask */
655
656            DEBUG_PRINT (TRACE_IO, ("About to write %04X to %04X\n",
657                                    RegisterValue, RegisterId));
658            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
659                                RegisterId, (UINT8) RegisterValue);
660            RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, RegisterId);
661        }
662        break;
663
664
665    case SMI_CMD_BLOCK:
666    case PROCESSOR_BLOCK:
667        /* not used */
668    default:
669
670        Mask = 0;
671        break;
672    }
673
674    if (ACPI_MTX_LOCK == UseLock) {
675        AcpiCmReleaseMutex (ACPI_MTX_HARDWARE);
676    }
677
678
679    RegisterValue &= Mask;
680    RegisterValue >>= AcpiHwGetBitShift (Mask);
681
682    DEBUG_PRINT (TRACE_IO, ("Register I/O: returning %X\n", RegisterValue));
683    return_VALUE (RegisterValue);
684}
685
686
687/******************************************************************************
688 *
689 * FUNCTION:    AcpiHwRegisterRead
690 *
691 * PARAMETERS:  UseLock                - Mutex hw access.
692 *              RegisterId             - RegisterID + Offset.
693 *
694 * RETURN:      Value read or written.
695 *
696 * DESCRIPTION: Acpi register read function.  Registers are read at the
697 *              given offset.
698 *
699 ******************************************************************************/
700
701UINT32
702AcpiHwRegisterRead (
703    BOOLEAN                 UseLock,
704    UINT32                  RegisterId)
705{
706    UINT32                  Value       = 0;
707    UINT32                  BankOffset;
708
709    FUNCTION_TRACE ("AcpiHwRegisterRead");
710
711    if (ACPI_MTX_LOCK == UseLock)
712    {
713        AcpiCmAcquireMutex (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    case GPE0_STS_BLOCK: /* 8-bit access */
754
755        Value =  AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe0Blk, 0);
756        break;
757
758
759    case GPE0_EN_BLOCK: /* 8-bit access */
760
761        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe0BlkLen);
762        Value =  AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe0Blk, BankOffset);
763        break;
764
765
766    case GPE1_STS_BLOCK: /* 8-bit access */
767
768        Value =  AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe1Blk, 0);
769        break;
770
771
772    case GPE1_EN_BLOCK: /* 8-bit access */
773
774        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe1BlkLen);
775        Value =  AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe1Blk, BankOffset);
776        break;
777
778
779    case SMI_CMD_BLOCK: /* 8bit */
780
781        Value = (UINT32) AcpiOsIn8 (AcpiGbl_FADT->SmiCmd);
782        break;
783
784
785    default:
786        Value = 0;
787        break;
788    }
789
790
791    if (ACPI_MTX_LOCK == UseLock)
792    {
793        AcpiCmReleaseMutex (ACPI_MTX_HARDWARE);
794    }
795
796    return_VALUE (Value);
797}
798
799
800/******************************************************************************
801 *
802 * FUNCTION:    AcpiHwRegisterWrite
803 *
804 * PARAMETERS:  UseLock                - Mutex hw access.
805 *              RegisterId             - RegisterID + Offset.
806 *
807 * RETURN:      Value read or written.
808 *
809 * DESCRIPTION: Acpi register Write function.  Registers are written at the
810 *              given offset.
811 *
812 ******************************************************************************/
813
814void
815AcpiHwRegisterWrite (
816    BOOLEAN                 UseLock,
817    UINT32                  RegisterId,
818    UINT32                  Value)
819{
820    UINT32                  BankOffset;
821
822    FUNCTION_TRACE ("AcpiHwRegisterWrite");
823
824
825    if (ACPI_MTX_LOCK == UseLock)
826    {
827        AcpiCmAcquireMutex (ACPI_MTX_HARDWARE);
828    }
829
830
831    switch (REGISTER_BLOCK_ID (RegisterId))
832    {
833    case PM1_STS: /* 16-bit access */
834
835        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk, 0);
836        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk, 0);
837        break;
838
839
840    case PM1_EN: /* 16-bit access*/
841
842        BankOffset = DIV_2 (AcpiGbl_FADT->Pm1EvtLen);
843        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk, BankOffset);
844        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk, BankOffset);
845        break;
846
847
848    case PM1_CONTROL: /* 16-bit access */
849
850        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk, 0);
851        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk, 0);
852        break;
853
854
855    case PM1A_CONTROL: /* 16-bit access */
856
857        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk, 0);
858        break;
859
860
861    case PM1B_CONTROL: /* 16-bit access */
862
863        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk, 0);
864        break;
865
866
867    case PM2_CONTROL: /* 8-bit access */
868
869        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XPm2CntBlk, 0);
870        break;
871
872
873    case PM_TIMER: /* 32-bit access */
874
875        AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT->XPmTmrBlk, 0);
876        break;
877
878
879    case GPE0_STS_BLOCK: /* 8-bit access */
880
881        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe0Blk, 0);
882        break;
883
884
885    case GPE0_EN_BLOCK: /* 8-bit access */
886
887        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe0BlkLen);
888        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe0Blk, BankOffset);
889        break;
890
891
892    case GPE1_STS_BLOCK: /* 8-bit access */
893
894        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe1Blk, 0);
895        break;
896
897
898    case GPE1_EN_BLOCK: /* 8-bit access */
899
900        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe1BlkLen);
901        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe1Blk, BankOffset);
902        break;
903
904
905    case SMI_CMD_BLOCK: /* 8bit */
906
907        /* For 2.0, SMI_CMD is always in IO space */
908        /* TBD: what about 1.0? 0.71? */
909
910       AcpiOsOut8 (AcpiGbl_FADT->SmiCmd, (UINT8) Value);
911        break;
912
913
914    default:
915        Value = 0;
916        break;
917    }
918
919
920    if (ACPI_MTX_LOCK == UseLock)
921    {
922        AcpiCmReleaseMutex (ACPI_MTX_HARDWARE);
923    }
924
925    return_VOID;
926}
927
928
929/******************************************************************************
930 *
931 * FUNCTION:    AcpiHwLowLevelRead
932 *
933 * PARAMETERS:  Register            - GAS register structure
934 *              Offset              - Offset from the base address in the GAS
935 *              Width               - 8, 16, or 32
936 *
937 * RETURN:      Value read
938 *
939 * DESCRIPTION: Read from either memory, IO, or PCI config space.
940 *
941 ******************************************************************************/
942
943UINT32
944AcpiHwLowLevelRead (
945    UINT32                  Width,
946    ACPI_GAS                *Reg,
947    UINT32                  Offset)
948{
949    UINT32                  Value = 0;
950    ACPI_PHYSICAL_ADDRESS   MemAddress;
951    ACPI_IO_ADDRESS         IoAddress;
952    UINT32                  PciRegister;
953    UINT32                  PciDevFunc;
954
955
956    /*
957     * Must have a valid pointer to a GAS structure, and
958     * a non-zero address within
959     */
960    if ((!Reg) ||
961        (!ACPI_VALID_ADDRESS (Reg->Address)))
962    {
963        return 0;
964    }
965
966
967    /*
968     * Three address spaces supported:
969     * Memory, Io, or PCI config.
970     */
971
972    switch (Reg->AddressSpaceId)
973    {
974    case ADDRESS_SPACE_SYSTEM_MEMORY:
975
976        MemAddress = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
977
978        switch (Width)
979        {
980        case 8:
981            Value = AcpiOsMemIn8  (MemAddress);
982            break;
983        case 16:
984            Value = AcpiOsMemIn16 (MemAddress);
985            break;
986        case 32:
987            Value = AcpiOsMemIn32 (MemAddress);
988            break;
989        }
990        break;
991
992
993    case ADDRESS_SPACE_SYSTEM_IO:
994
995        IoAddress = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
996
997        switch (Width)
998        {
999        case 8:
1000            Value = AcpiOsIn8  (IoAddress);
1001            break;
1002        case 16:
1003            Value = AcpiOsIn16 (IoAddress);
1004            break;
1005        case 32:
1006            Value = AcpiOsIn32 (IoAddress);
1007            break;
1008        }
1009        break;
1010
1011
1012    case ADDRESS_SPACE_PCI_CONFIG:
1013
1014        PciDevFunc  = ACPI_PCI_DEVFUN   (ACPI_GET_ADDRESS (Reg->Address));
1015        PciRegister = ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address)) + Offset;
1016
1017        switch (Width)
1018        {
1019        case 8:
1020            AcpiOsReadPciCfgByte  (0, PciDevFunc, PciRegister, (UINT8 *) &Value);
1021            break;
1022        case 16:
1023            AcpiOsReadPciCfgWord  (0, PciDevFunc, PciRegister, (UINT16 *) &Value);
1024            break;
1025        case 32:
1026            AcpiOsReadPciCfgDword (0, PciDevFunc, PciRegister, (UINT32 *) &Value);
1027            break;
1028        }
1029        break;
1030    }
1031
1032    return Value;
1033}
1034
1035
1036/******************************************************************************
1037 *
1038 * FUNCTION:    AcpiHwLowLevelWrite
1039 *
1040 * PARAMETERS:  Width               - 8, 16, or 32
1041 *              Value               - To be written
1042 *              Register            - GAS register structure
1043 *              Offset              - Offset from the base address in the GAS
1044 *
1045 *
1046 * RETURN:      Value read
1047 *
1048 * DESCRIPTION: Read from either memory, IO, or PCI config space.
1049 *
1050 ******************************************************************************/
1051
1052void
1053AcpiHwLowLevelWrite (
1054    UINT32                  Width,
1055    UINT32                  Value,
1056    ACPI_GAS                *Reg,
1057    UINT32                  Offset)
1058{
1059    ACPI_PHYSICAL_ADDRESS   MemAddress;
1060    ACPI_IO_ADDRESS         IoAddress;
1061    UINT32                  PciRegister;
1062    UINT32                  PciDevFunc;
1063
1064
1065    /*
1066     * Must have a valid pointer to a GAS structure, and
1067     * a non-zero address within
1068     */
1069    if ((!Reg) ||
1070        (!ACPI_VALID_ADDRESS (Reg->Address)))
1071    {
1072        return;
1073    }
1074
1075
1076    /*
1077     * Three address spaces supported:
1078     * Memory, Io, or PCI config.
1079     */
1080
1081    switch (Reg->AddressSpaceId)
1082    {
1083    case ADDRESS_SPACE_SYSTEM_MEMORY:
1084
1085        MemAddress = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
1086
1087        switch (Width)
1088        {
1089        case 8:
1090            AcpiOsMemOut8  (MemAddress, (UINT8) Value);
1091            break;
1092        case 16:
1093            AcpiOsMemOut16 (MemAddress, (UINT16) Value);
1094            break;
1095        case 32:
1096            AcpiOsMemOut32 (MemAddress, (UINT32) Value);
1097            break;
1098        }
1099        break;
1100
1101
1102    case ADDRESS_SPACE_SYSTEM_IO:
1103
1104        IoAddress = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
1105
1106        switch (Width)
1107        {
1108        case 8:
1109            AcpiOsOut8  (IoAddress, (UINT8) Value);
1110            break;
1111        case 16:
1112            AcpiOsOut16 (IoAddress, (UINT16) Value);
1113            break;
1114        case 32:
1115            AcpiOsOut32 (IoAddress, (UINT32) Value);
1116            break;
1117        }
1118        break;
1119
1120
1121    case ADDRESS_SPACE_PCI_CONFIG:
1122
1123        PciDevFunc  = ACPI_PCI_DEVFUN   (ACPI_GET_ADDRESS (Reg->Address));
1124        PciRegister = ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address)) + Offset;
1125
1126        switch (Width)
1127        {
1128        case 8:
1129            AcpiOsWritePciCfgByte  (0, PciDevFunc, PciRegister, (UINT8) Value);
1130            break;
1131        case 16:
1132            AcpiOsWritePciCfgWord  (0, PciDevFunc, PciRegister, (UINT16) Value);
1133            break;
1134        case 32:
1135            AcpiOsWritePciCfgDword (0, PciDevFunc, PciRegister, (UINT32) Value);
1136            break;
1137        }
1138        break;
1139    }
1140}
1141