hwregs.c revision 67754
1
2/*******************************************************************************
3 *
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 *                       control and status registers.
6 *              $Revision: 71 $
7 *
8 ******************************************************************************/
9
10/******************************************************************************
11 *
12 * 1. Copyright Notice
13 *
14 * Some or all of this work - Copyright (c) 1999, Intel Corp.  All rights
15 * reserved.
16 *
17 * 2. License
18 *
19 * 2.1. This is your license from Intel Corp. under its intellectual property
20 * rights.  You may have additional license terms from the party that provided
21 * you this software, covering your right to use that party's intellectual
22 * property rights.
23 *
24 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
25 * copy of the source code appearing in this file ("Covered Code") an
26 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
27 * base code distributed originally by Intel ("Original Intel Code") to copy,
28 * make derivatives, distribute, use and display any portion of the Covered
29 * Code in any form, with the right to sublicense such rights; and
30 *
31 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
32 * license (with the right to sublicense), under only those claims of Intel
33 * patents that are infringed by the Original Intel Code, to make, use, sell,
34 * offer to sell, and import the Covered Code and derivative works thereof
35 * solely to the minimum extent necessary to exercise the above copyright
36 * license, and in no event shall the patent license extend to any additions
37 * to or modifications of the Original Intel Code.  No other license or right
38 * is granted directly or by implication, estoppel or otherwise;
39 *
40 * The above copyright and patent license is granted only if the following
41 * conditions are met:
42 *
43 * 3. Conditions
44 *
45 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
46 * Redistribution of source code of any substantial portion of the Covered
47 * Code or modification with rights to further distribute source must include
48 * the above Copyright Notice, the above License, this list of Conditions,
49 * and the following Disclaimer and Export Compliance provision.  In addition,
50 * Licensee must cause all Covered Code to which Licensee contributes to
51 * contain a file documenting the changes Licensee made to create that Covered
52 * Code and the date of any change.  Licensee must include in that file the
53 * documentation of any changes made by any predecessor Licensee.  Licensee
54 * must include a prominent statement that the modification is derived,
55 * directly or indirectly, from Original Intel Code.
56 *
57 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
58 * Redistribution of source code of any substantial portion of the Covered
59 * Code or modification without rights to further distribute source must
60 * include the following Disclaimer and Export Compliance provision in the
61 * documentation and/or other materials provided with distribution.  In
62 * addition, Licensee may not authorize further sublicense of source of any
63 * portion of the Covered Code, and must include terms to the effect that the
64 * license from Licensee to its licensee is limited to the intellectual
65 * property embodied in the software Licensee provides to its licensee, and
66 * not to intellectual property embodied in modifications its licensee may
67 * make.
68 *
69 * 3.3. Redistribution of Executable. Redistribution in executable form of any
70 * substantial portion of the Covered Code or modification must reproduce the
71 * above Copyright Notice, and the following Disclaimer and Export Compliance
72 * provision in the documentation and/or other materials provided with the
73 * distribution.
74 *
75 * 3.4. Intel retains all right, title, and interest in and to the Original
76 * Intel Code.
77 *
78 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
79 * Intel shall be used in advertising or otherwise to promote the sale, use or
80 * other dealings in products derived from or relating to the Covered Code
81 * without prior written authorization from Intel.
82 *
83 * 4. Disclaimer and Export Compliance
84 *
85 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
86 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
87 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
88 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
89 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
90 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
91 * PARTICULAR PURPOSE.
92 *
93 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
94 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
95 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
96 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
97 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
98 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
99 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
100 * LIMITED REMEDY.
101 *
102 * 4.3. Licensee shall not export, either directly or indirectly, any of this
103 * software or system incorporating such software without first obtaining any
104 * required license or other approval from the U. S. Department of Commerce or
105 * any other agency or department of the United States Government.  In the
106 * event Licensee exports any such software from the United States or
107 * re-exports any such software from a foreign destination, Licensee shall
108 * ensure that the distribution and export/re-export of the software is in
109 * compliance with all laws, regulations, orders, or other restrictions of the
110 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
111 * any of its subsidiaries will export/re-export any technical data, process,
112 * software, or service, directly or indirectly, to any country for which the
113 * United States government or any agency thereof requires an export license,
114 * other governmental approval, or letter of assurance, without first obtaining
115 * such license, approval or letter.
116 *
117 *****************************************************************************/
118
119#define __HWREGS_C__
120
121#include "acpi.h"
122#include "achware.h"
123#include "acnamesp.h"
124
125#define _COMPONENT          HARDWARE
126        MODULE_NAME         ("hwregs")
127
128
129/* This matches the #defines in actypes.h. */
130
131NATIVE_CHAR *SleepStateTable[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_",
132                                 "\\_S4_","\\_S4B","\\_S5_"};
133
134
135/*******************************************************************************
136 *
137 * FUNCTION:    AcpiHwGetBitShift
138 *
139 * PARAMETERS:  Mask            - Input mask to determine bit shift from.
140 *                                Must have at least 1 bit set.
141 *
142 * RETURN:      Bit location of the lsb of the mask
143 *
144 * DESCRIPTION: Returns the bit number for the low order bit that's set.
145 *
146 ******************************************************************************/
147
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, (UINT16) AcpiGbl_FACP->Pm1aEvtBlk));
189
190
191    AcpiCmAcquireMutex (ACPI_MTX_HARDWARE);
192
193    AcpiOsOut16 (AcpiGbl_FACP->Pm1aEvtBlk, (UINT16) ALL_FIXED_STS_BITS);
194
195    if (AcpiGbl_FACP->Pm1bEvtBlk)
196    {
197        AcpiOsOut16 ((UINT16) AcpiGbl_FACP->Pm1bEvtBlk,
198                        (UINT16) ALL_FIXED_STS_BITS);
199    }
200
201    /* now clear the GPE Bits */
202
203    if (AcpiGbl_FACP->Gpe0BlkLen)
204    {
205        GpeLength = (UINT16) DIV_2 (AcpiGbl_FACP->Gpe0BlkLen);
206
207        for (Index = 0; Index < GpeLength; Index++)
208        {
209            AcpiOsOut8 ((AcpiGbl_FACP->Gpe0Blk + Index), (UINT8) 0xff);
210        }
211    }
212
213    if (AcpiGbl_FACP->Gpe1BlkLen)
214    {
215        GpeLength = (UINT16) DIV_2 (AcpiGbl_FACP->Gpe1BlkLen);
216
217        for (Index = 0; Index < GpeLength; Index++)
218        {
219            AcpiOsOut8 ((AcpiGbl_FACP->Gpe1Blk + Index), (UINT8) 0xff);
220        }
221    }
222
223    AcpiCmReleaseMutex (ACPI_MTX_HARDWARE);
224    return_VOID;
225}
226
227
228/*******************************************************************************
229 *
230 * FUNCTION:    AcpiHwObtainSleepTypeRegisterData
231 *
232 * PARAMETERS:  SleepState        - Numeric state requested
233 *              *Slp_TypA         - Pointer to byte to receive SLP_TYPa value
234 *              *Slp_TypB         - Pointer to byte to receive SLP_TYPb value
235 *
236 * RETURN:      Status - ACPI status
237 *
238 * DESCRIPTION: AcpiHwObtainSleepTypeRegisterData() obtains the SLP_TYP and
239 *              SLP_TYPb values for the sleep state requested.
240 *
241 ******************************************************************************/
242
243ACPI_STATUS
244AcpiHwObtainSleepTypeRegisterData (
245    UINT8                   SleepState,
246    UINT8                   *Slp_TypA,
247    UINT8                   *Slp_TypB)
248{
249    ACPI_STATUS             Status = AE_OK;
250    ACPI_OPERAND_OBJECT     *ObjDesc;
251
252
253    FUNCTION_TRACE ("HwObtainSleepTypeRegisterData");
254
255
256    /*
257     *  Validate parameters
258     */
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
270    Status = AcpiNsEvaluateByName (SleepStateTable[SleepState], 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    Status = AcpiCmResolvePackageReferences(ObjDesc);
289
290    if (ObjDesc->Package.Count < 2)
291    {
292        /* Must have at least two elements */
293
294        REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
295        Status = AE_ERROR;
296    }
297
298    else if (((ObjDesc->Package.Elements[0])->Common.Type !=
299                ACPI_TYPE_NUMBER) ||
300             ((ObjDesc->Package.Elements[1])->Common.Type !=
301                ACPI_TYPE_NUMBER))
302    {
303        /* Must have two  */
304
305        REPORT_ERROR (("Sleep State package elements are not both of type Number\n"));
306        Status = AE_ERROR;
307    }
308
309    else
310    {
311        /*
312         *  Valid _Sx_ package size, type, and value
313         */
314        *Slp_TypA = (UINT8) (ObjDesc->Package.Elements[0])->Number.Value;
315
316        *Slp_TypB = (UINT8) (ObjDesc->Package.Elements[1])->Number.Value;
317    }
318
319
320    if (ACPI_FAILURE (Status))
321    {
322        DEBUG_PRINT (ACPI_ERROR,
323            ("SleepTypeRegisterData: Bad Sleep object %p type %X\n",
324            ObjDesc, ObjDesc->Common.Type));
325    }
326
327    AcpiCmRemoveReference (ObjDesc);
328
329    return_ACPI_STATUS (Status);
330}
331
332
333/*******************************************************************************
334 *
335 * FUNCTION:    AcpiHwRegisterAccess
336 *
337 * PARAMETERS:  ReadWrite       - Either ACPI_READ or ACPI_WRITE.
338 *              UseLock         - Lock the hardware
339 *              RegisterId      - index of ACPI register to access
340 *              Value           - (only used on write) value to write to the
341 *                                 register.  Shifted all the way right.
342 *
343 * RETURN:      Value written to or read from specified register.  This value
344 *              is shifted all the way right.
345 *
346 * DESCRIPTION: Generic ACPI register read/write function.
347 *
348 ******************************************************************************/
349
350UINT32
351AcpiHwRegisterAccess (
352    NATIVE_UINT             ReadWrite,
353    BOOLEAN                 UseLock,
354    UINT32                  RegisterId,
355    ...)                    /* Value (only used on write) */
356{
357    UINT32                  RegisterValue = 0;
358    UINT32                  Mask = 0;
359    UINT32                  Value = 0;
360    ACPI_IO_ADDRESS         GpeReg = 0;
361
362
363    FUNCTION_TRACE ("HwRegisterIO");
364
365
366    if (ReadWrite == ACPI_WRITE)
367    {
368        va_list         marker;
369
370        va_start (marker, RegisterId);
371        Value = va_arg (marker, UINT32);
372        va_end (marker);
373    }
374
375    /*
376     * TBD: [Restructure] May want to split the AcpiEvent code and the
377     * Control code
378     */
379
380    /*
381     * Decode the Register ID
382     */
383
384    switch (RegisterId & REGISTER_BLOCK_MASK)
385    {
386    case PM1_EVT:
387
388        if (RegisterId < TMR_EN)
389        {
390            /* status register */
391
392            if (ACPI_MTX_LOCK == UseLock)
393            {
394                AcpiCmAcquireMutex (ACPI_MTX_HARDWARE);
395            }
396
397
398            RegisterValue = (UINT32) AcpiOsIn16 (AcpiGbl_FACP->Pm1aEvtBlk);
399            DEBUG_PRINT (TRACE_IO, ("PM1a status: Read 0x%X from 0x%X\n",
400                            RegisterValue, AcpiGbl_FACP->Pm1aEvtBlk));
401
402            if (AcpiGbl_FACP->Pm1bEvtBlk)
403            {
404                RegisterValue |= (UINT32) AcpiOsIn16 (AcpiGbl_FACP->Pm1bEvtBlk);
405                DEBUG_PRINT (TRACE_IO, ("PM1b status: Read 0x%X from 0x%X\n",
406                                RegisterValue, AcpiGbl_FACP->Pm1bEvtBlk));
407            }
408
409            switch (RegisterId)
410            {
411            case TMR_STS:
412                Mask = TMR_STS_MASK;
413                break;
414
415            case BM_STS:
416                Mask = BM_STS_MASK;
417                break;
418
419            case GBL_STS:
420                Mask = GBL_STS_MASK;
421                break;
422
423            case PWRBTN_STS:
424                Mask = PWRBTN_STS_MASK;
425                break;
426
427            case SLPBTN_STS:
428                Mask = SLPBTN_STS_MASK;
429                break;
430
431            case RTC_STS:
432                Mask = RTC_STS_MASK;
433                break;
434
435            case WAK_STS:
436                Mask = WAK_STS_MASK;
437                break;
438
439            default:
440                Mask = 0;
441                break;
442            }
443
444            if (ReadWrite == ACPI_WRITE)
445            {
446                /*
447                 * Status registers are different from the rest.  Clear by
448                 * writing 1, writing 0 has no effect.  So, the only relevent
449                 * information is the single bit we're interested in, all
450                 * others should be written as 0 so they will be left
451                 * unchanged
452                 */
453
454                Value <<= AcpiHwGetBitShift (Mask);
455                Value &= Mask;
456
457                if (Value)
458                {
459                    DEBUG_PRINT (TRACE_IO,
460                        ("About to write 0x%X to 0x%X\n", Value,
461                        AcpiGbl_FACP->Pm1aEvtBlk));
462
463                    AcpiOsOut16 (AcpiGbl_FACP->Pm1aEvtBlk, (UINT16) Value);
464
465                    if (AcpiGbl_FACP->Pm1bEvtBlk)
466                    {
467                        AcpiOsOut16 (AcpiGbl_FACP->Pm1bEvtBlk, (UINT16) Value);
468                    }
469
470                    RegisterValue = 0;
471                }
472            }
473
474            if (ACPI_MTX_LOCK == UseLock)
475            {
476                AcpiCmReleaseMutex (ACPI_MTX_HARDWARE);
477            }
478        }
479
480        else
481        {
482            /* enable register */
483
484            if (ACPI_MTX_LOCK == UseLock)
485            {
486                AcpiCmAcquireMutex (ACPI_MTX_HARDWARE);
487            }
488
489            RegisterValue = (UINT32) AcpiOsIn16 (AcpiGbl_FACP->Pm1aEvtBlk +
490                            DIV_2 (AcpiGbl_FACP->Pm1EvtLen));
491
492            DEBUG_PRINT (TRACE_IO, ("PM1a enable: Read 0x%X from 0x%X\n",
493                            RegisterValue, (AcpiGbl_FACP->Pm1aEvtBlk +
494                            DIV_2 (AcpiGbl_FACP->Pm1EvtLen))));
495
496            if (AcpiGbl_FACP->Pm1bEvtBlk)
497            {
498                RegisterValue |= (UINT32) AcpiOsIn16 (AcpiGbl_FACP->Pm1bEvtBlk +
499                                    DIV_2 (AcpiGbl_FACP->Pm1EvtLen));
500
501                DEBUG_PRINT (TRACE_IO, ("PM1b enable: Read 0x%X from 0x%X\n",
502                                RegisterValue, (AcpiGbl_FACP->Pm1bEvtBlk +
503                                DIV_2 (AcpiGbl_FACP->Pm1EvtLen))));
504            }
505
506            switch (RegisterId)
507            {
508            case TMR_EN:
509                Mask = TMR_EN_MASK;
510                break;
511
512            case GBL_EN:
513                Mask = GBL_EN_MASK;
514                break;
515
516            case PWRBTN_EN:
517                Mask = PWRBTN_EN_MASK;
518                break;
519
520            case SLPBTN_EN:
521                Mask = SLPBTN_EN_MASK;
522                break;
523
524            case RTC_EN:
525                Mask = RTC_EN_MASK;
526                break;
527
528            default:
529                Mask = 0;
530                break;
531            }
532
533            if (ReadWrite == ACPI_WRITE)
534            {
535                RegisterValue  &= ~Mask;
536                Value          <<= AcpiHwGetBitShift (Mask);
537                Value          &= Mask;
538                RegisterValue  |= Value;
539
540                DEBUG_PRINT (TRACE_IO,
541                    ("About to write %04X to %04X\n", RegisterValue,
542                    (AcpiGbl_FACP->Pm1aEvtBlk +
543                    DIV_2 (AcpiGbl_FACP->Pm1EvtLen))));
544
545                AcpiOsOut16 ((AcpiGbl_FACP->Pm1aEvtBlk +
546                            DIV_2 (AcpiGbl_FACP->Pm1EvtLen)),
547                            (UINT16) RegisterValue);
548
549                if (AcpiGbl_FACP->Pm1bEvtBlk)
550                {
551                    AcpiOsOut16 ((AcpiGbl_FACP->Pm1bEvtBlk +
552                                DIV_2 (AcpiGbl_FACP->Pm1EvtLen)),
553                                (UINT16) RegisterValue);
554                }
555            }
556            if(ACPI_MTX_LOCK == UseLock)
557            {
558                AcpiCmReleaseMutex (ACPI_MTX_HARDWARE);
559            }
560        }
561        break;
562
563
564    case PM1_CONTROL:
565
566        RegisterValue = 0;
567
568        if (ACPI_MTX_LOCK == UseLock)
569        {
570            AcpiCmAcquireMutex (ACPI_MTX_HARDWARE);
571        }
572
573        if (RegisterId != SLP_TYPE_B)
574        {
575            /*
576             * SLP_TYPx registers are written differently
577             * than any other control registers with
578             * respect to A and B registers.  The value
579             * for A may be different than the value for B
580             */
581
582            RegisterValue = (UINT32) AcpiOsIn16 (AcpiGbl_FACP->Pm1aCntBlk);
583            DEBUG_PRINT (TRACE_IO, ("PM1a control: Read 0x%X from 0x%X\n",
584                            RegisterValue, AcpiGbl_FACP->Pm1aCntBlk));
585        }
586
587        if (AcpiGbl_FACP->Pm1bCntBlk && RegisterId != (UINT32) SLP_TYPE_A)
588        {
589            RegisterValue |= (UINT32) AcpiOsIn16 (AcpiGbl_FACP->Pm1bCntBlk);
590            DEBUG_PRINT (TRACE_IO, ("PM1b control: Read 0x%X from 0x%X\n",
591                            RegisterValue, AcpiGbl_FACP->Pm1bCntBlk));
592        }
593
594        switch (RegisterId)
595        {
596        case SCI_EN:
597            Mask = SCI_EN_MASK;
598            break;
599
600        case BM_RLD:
601            Mask = BM_RLD_MASK;
602            break;
603
604        case GBL_RLS:
605            Mask = GBL_RLS_MASK;
606            break;
607
608        case SLP_TYPE_A:
609        case SLP_TYPE_B:
610            Mask = SLP_TYPE_X_MASK;
611            break;
612
613        case SLP_EN:
614            Mask = SLP_EN_MASK;
615            break;
616
617        default:
618            Mask = 0;
619            break;
620        }
621
622        if (ReadWrite == ACPI_WRITE)
623        {
624            RegisterValue  &= ~Mask;
625            Value          <<= AcpiHwGetBitShift (Mask);
626            Value          &= Mask;
627            RegisterValue  |= Value;
628
629            /*
630             * SLP_TYPE_x registers are written differently
631             * than any other control registers with
632             * respect to A and B registers.  The value
633             * for A may be different than the value for B
634             */
635
636            if (RegisterId != SLP_TYPE_B)
637            {
638                if (Mask == SLP_EN_MASK)
639                {
640                    disable();  /* disable interrupts */
641                }
642
643                AcpiOsOut16 (AcpiGbl_FACP->Pm1aCntBlk, (UINT16) RegisterValue);
644
645                if (Mask == SLP_EN_MASK)
646                {
647                    /*
648                     * Enable interrupts, the SCI handler is likely going to
649                     * be invoked as soon as interrupts are enabled, since gpe's
650                     * and most fixed resume events also generate SCI's.
651                     */
652                    enable();
653                }
654            }
655
656            if (AcpiGbl_FACP->Pm1bCntBlk && RegisterId != (UINT32) SLP_TYPE_A)
657            {
658                AcpiOsOut16 (AcpiGbl_FACP->Pm1bCntBlk, (UINT16) RegisterValue);
659            }
660        }
661
662        if (ACPI_MTX_LOCK == UseLock)
663        {
664            AcpiCmReleaseMutex (ACPI_MTX_HARDWARE);
665        }
666        break;
667
668
669    case PM2_CONTROL:
670
671        if (ACPI_MTX_LOCK == UseLock)
672        {
673            AcpiCmAcquireMutex (ACPI_MTX_HARDWARE);
674        }
675
676        RegisterValue = (UINT32) AcpiOsIn16 (AcpiGbl_FACP->Pm2CntBlk);
677        DEBUG_PRINT (TRACE_IO, ("PM2 control: Read 0x%X from 0x%X\n",
678                        RegisterValue, AcpiGbl_FACP->Pm2CntBlk));
679
680        switch (RegisterId)
681        {
682        case ARB_DIS:
683            Mask = ARB_DIS_MASK;
684            break;
685
686        default:
687            Mask = 0;
688            break;
689        }
690
691        if (ReadWrite == ACPI_WRITE)
692        {
693            RegisterValue  &= ~Mask;
694            Value          <<= AcpiHwGetBitShift (Mask);
695            Value          &= Mask;
696            RegisterValue  |= Value;
697
698            DEBUG_PRINT (TRACE_IO,
699                ("About to write %04X to %04X\n", RegisterValue,
700                AcpiGbl_FACP->Pm2CntBlk));
701
702            AcpiOsOut16 (AcpiGbl_FACP->Pm2CntBlk, (UINT16) RegisterValue);
703        }
704
705        if (ACPI_MTX_LOCK == UseLock)
706        {
707            AcpiCmReleaseMutex (ACPI_MTX_HARDWARE);
708        }
709        break;
710
711
712    case PM_TIMER:
713
714        RegisterValue = AcpiOsIn32 (AcpiGbl_FACP->PmTmrBlk);
715        DEBUG_PRINT (TRACE_IO, ("PM_TIMER: Read 0x%X from 0x%X\n",
716                        RegisterValue, AcpiGbl_FACP->PmTmrBlk));
717
718        Mask = ACPI_UINT32_MAX;
719        break;
720
721
722    case GPE1_EN_BLOCK:
723
724        GpeReg = (AcpiGbl_FACP->Gpe1Blk + AcpiGbl_FACP->Gpe1Base) +
725                    (GpeReg + (DIV_2 (AcpiGbl_FACP->Gpe1BlkLen)));
726
727
728    case GPE1_STS_BLOCK:
729
730        if (!GpeReg)
731        {
732            GpeReg = (AcpiGbl_FACP->Gpe1Blk + AcpiGbl_FACP->Gpe1Base);
733        }
734
735
736    case GPE0_EN_BLOCK:
737
738        if (!GpeReg)
739        {
740            GpeReg = AcpiGbl_FACP->Gpe0Blk + DIV_2 (AcpiGbl_FACP->Gpe0BlkLen);
741        }
742
743
744    case GPE0_STS_BLOCK:
745
746        if (!GpeReg)
747        {
748            GpeReg = AcpiGbl_FACP->Gpe0Blk;
749        }
750
751        /* Determine the bit to be accessed */
752
753        Mask = (((UINT32) RegisterId) & BIT_IN_REGISTER_MASK);
754        Mask = 1 << (Mask-1);
755
756        /*
757         * The base address of the GPE 0 Register Block
758         * Plus 1/2 the length of the GPE 0 Register Block
759         * The enable register is the register following the Status Register
760         * and each register is defined as 1/2 of the total Register Block
761         */
762
763        /*
764         * This sets the bit within EnableBit that needs to be written to
765         * the register indicated in Mask to a 1, all others are 0
766         */
767
768        if (Mask > LOW_BYTE)
769        {
770            /* Shift the value 1 byte to the right and add 1 to the register */
771
772            Mask >>= ONE_BYTE;
773            GpeReg++;
774        }
775
776        /* Now get the current Enable Bits in the selected Reg */
777
778        if(ACPI_MTX_LOCK == UseLock)
779        {
780            AcpiCmAcquireMutex (ACPI_MTX_HARDWARE);
781        }
782
783        RegisterValue = (UINT32) AcpiOsIn8 (GpeReg);
784        DEBUG_PRINT (TRACE_IO, ("GPE Enable bits: Read 0x%X from 0x%X\n",
785                                RegisterValue, GpeReg));
786
787        if (ReadWrite == ACPI_WRITE)
788        {
789            RegisterValue  &= ~Mask;
790            Value          <<= AcpiHwGetBitShift (Mask);
791            Value          &= Mask;
792            RegisterValue  |= Value;
793
794            /* This write will put the Action state into the General Purpose */
795
796            /* Enable Register indexed by the value in Mask */
797
798            DEBUG_PRINT (TRACE_IO, ("About to write %04X to %04X\n",
799                                    RegisterValue, GpeReg));
800
801            AcpiOsOut8 (GpeReg, (UINT8) RegisterValue);
802            RegisterValue = (UINT32) AcpiOsIn8 (GpeReg);
803        }
804
805        if(ACPI_MTX_LOCK == UseLock)
806        {
807            AcpiCmReleaseMutex (ACPI_MTX_HARDWARE);
808        }
809        break;
810
811
812    case PROCESSOR_BLOCK:
813    default:
814
815        Mask = 0;
816        break;
817    }
818
819
820    RegisterValue &= Mask;
821    RegisterValue >>= AcpiHwGetBitShift (Mask);
822
823    DEBUG_PRINT (TRACE_IO, ("Register I/O: returning 0x%X\n", RegisterValue));
824    return_VALUE (RegisterValue);
825}
826