hwregs.c revision 99146
1
2/*******************************************************************************
3 *
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 *                       control and status registers.
6 *              $Revision: 121 $
7 *
8 ******************************************************************************/
9
10/******************************************************************************
11 *
12 * 1. Copyright Notice
13 *
14 * Some or all of this work - Copyright (c) 1999 - 2002, 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        ACPI_MODULE_NAME    ("hwregs")
127
128
129/*******************************************************************************
130 *
131 * FUNCTION:    AcpiHwClearAcpiStatus
132 *
133 * PARAMETERS:  none
134 *
135 * RETURN:      none
136 *
137 * DESCRIPTION: Clears all fixed and general purpose status bits
138 *
139 ******************************************************************************/
140
141void
142AcpiHwClearAcpiStatus (void)
143{
144    NATIVE_UINT             i;
145    NATIVE_UINT             GpeBlock;
146    ACPI_STATUS             Status;
147
148
149    ACPI_FUNCTION_TRACE ("HwClearAcpiStatus");
150
151
152    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
153        ACPI_BITMASK_ALL_FIXED_STATUS,
154        (UINT16) ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1aEvtBlk.Address)));
155
156
157    Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
158    if (ACPI_FAILURE (Status))
159    {
160        return_VOID;
161    }
162
163    AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS,
164            ACPI_BITMASK_ALL_FIXED_STATUS);
165
166    /* Clear the fixed events */
167
168    if (ACPI_VALID_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address))
169    {
170        AcpiHwLowLevelWrite (16, ACPI_BITMASK_ALL_FIXED_STATUS,
171                &AcpiGbl_FADT->XPm1bEvtBlk, 0);
172    }
173
174    /* Clear the GPE Bits */
175
176    for (GpeBlock = 0; GpeBlock < ACPI_MAX_GPE_BLOCKS; GpeBlock++)
177    {
178        for (i = 0; i < AcpiGbl_GpeBlockInfo[GpeBlock].RegisterCount; i++)
179        {
180            AcpiHwLowLevelWrite (8, 0xFF,
181                AcpiGbl_GpeBlockInfo[GpeBlock].BlockAddress, i);
182        }
183    }
184
185    (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
186    return_VOID;
187}
188
189
190/*******************************************************************************
191 *
192 * FUNCTION:    AcpiHwGetSleepTypeData
193 *
194 * PARAMETERS:  SleepState          - Numeric sleep state
195 *              *SleepTypeA         - Where SLP_TYPa is returned
196 *              *SleepTypeB         - Where SLP_TYPb is returned
197 *
198 * RETURN:      Status - ACPI status
199 *
200 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
201 *              state.
202 *
203 ******************************************************************************/
204
205ACPI_STATUS
206AcpiHwGetSleepTypeData (
207    UINT8                   SleepState,
208    UINT8                   *SleepTypeA,
209    UINT8                   *SleepTypeB)
210{
211    ACPI_STATUS             Status = AE_OK;
212    ACPI_OPERAND_OBJECT     *ObjDesc;
213
214
215    ACPI_FUNCTION_TRACE ("HwGetSleepTypeData");
216
217
218    /*
219     *  Validate parameters
220     */
221    if ((SleepState > ACPI_S_STATES_MAX) ||
222        !SleepTypeA || !SleepTypeB)
223    {
224        return_ACPI_STATUS (AE_BAD_PARAMETER);
225    }
226
227    /*
228     *  AcpiEvaluate the namespace object containing the values for this state
229     */
230    Status = AcpiNsEvaluateByName ((NATIVE_CHAR *) AcpiGbl_DbSleepStates[SleepState],
231                    NULL, &ObjDesc);
232    if (ACPI_FAILURE (Status))
233    {
234        return_ACPI_STATUS (Status);
235    }
236
237    if (!ObjDesc)
238    {
239        ACPI_REPORT_ERROR (("Missing Sleep State object\n"));
240        return_ACPI_STATUS (AE_NOT_EXIST);
241    }
242
243    /*
244     *  We got something, now ensure it is correct.  The object must
245     *  be a package and must have at least 2 numeric values as the
246     *  two elements
247     */
248
249    /* Even though AcpiEvaluateObject resolves package references,
250     * NsEvaluate doesn't. So, we do it here.
251     */
252    Status = AcpiUtResolvePackageReferences(ObjDesc);
253
254    if (ObjDesc->Package.Count < 2)
255    {
256        /* Must have at least two elements */
257
258        ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
259        Status = AE_AML_NO_OPERAND;
260    }
261    else if (((ObjDesc->Package.Elements[0])->Common.Type != ACPI_TYPE_INTEGER) ||
262             ((ObjDesc->Package.Elements[1])->Common.Type != ACPI_TYPE_INTEGER))
263    {
264        /* Must have two  */
265
266        ACPI_REPORT_ERROR (("Sleep State package elements are not both of type Number\n"));
267        Status = AE_AML_OPERAND_TYPE;
268    }
269    else
270    {
271        /*
272         *  Valid _Sx_ package size, type, and value
273         */
274        *SleepTypeA = (UINT8) (ObjDesc->Package.Elements[0])->Integer.Value;
275        *SleepTypeB = (UINT8) (ObjDesc->Package.Elements[1])->Integer.Value;
276    }
277
278    if (ACPI_FAILURE (Status))
279    {
280        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad Sleep object %p type %X\n",
281            ObjDesc, ObjDesc->Common.Type));
282    }
283
284    AcpiUtRemoveReference (ObjDesc);
285    return_ACPI_STATUS (Status);
286}
287
288
289/*******************************************************************************
290 *
291 * FUNCTION:    AcpiHwGetRegisterBitMask
292 *
293 * PARAMETERS:  RegisterId      - index of ACPI Register to access
294 *
295 * RETURN:      The bit mask to be used when accessing the register
296 *
297 * DESCRIPTION: Map RegisterId into a register bit mask.
298 *
299 ******************************************************************************/
300
301ACPI_BIT_REGISTER_INFO *
302AcpiHwGetBitRegisterInfo (
303    UINT32                  RegisterId)
304{
305    ACPI_FUNCTION_NAME ("HwGetBitRegisterInfo");
306
307
308    if (RegisterId > ACPI_BITREG_MAX)
309    {
310        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid BitRegister ID: %X\n", RegisterId));
311        return (NULL);
312    }
313
314    return (&AcpiGbl_BitRegisterInfo[RegisterId]);
315}
316
317
318/*******************************************************************************
319 *
320 * FUNCTION:    AcpiHwBitRegisterRead
321 *
322 * PARAMETERS:  RegisterId      - index of ACPI Register to access
323 *              UseLock         - Lock the hardware
324 *
325 * RETURN:      Value is read from specified Register.  Value returned is
326 *              normalized to bit0 (is shifted all the way right)
327 *
328 * DESCRIPTION: ACPI BitRegister read function.
329 *
330 ******************************************************************************/
331
332UINT32
333AcpiHwBitRegisterRead (
334    UINT32                  RegisterId,
335    UINT32                  Flags)
336{
337    UINT32                  RegisterValue = 0;
338    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
339
340
341    ACPI_FUNCTION_TRACE ("HwBitRegisterRead");
342
343
344    if (Flags & ACPI_MTX_LOCK)
345    {
346        if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_HARDWARE)))
347        {
348            return_VALUE (0);
349        }
350    }
351
352    /* Get the info structure corresponding to the requested ACPI Register */
353
354    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
355    if (!BitRegInfo)
356    {
357        return_ACPI_STATUS (AE_BAD_PARAMETER);
358    }
359
360    RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, BitRegInfo->ParentRegister);
361
362    if (Flags & ACPI_MTX_LOCK)
363    {
364        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
365    }
366
367    /* Normalize the value that was read */
368
369    RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask) >> BitRegInfo->BitPosition);
370
371    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "ACPI RegisterRead: got %X\n", RegisterValue));
372    return_VALUE (RegisterValue);
373}
374
375
376/*******************************************************************************
377 *
378 * FUNCTION:    AcpiHwBitRegisterWrite
379 *
380 * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
381 *              Value           - (only used on write) value to write to the
382 *                                Register, NOT pre-normalized to the bit pos.
383 *              Flags           - Lock the hardware or not
384 *
385 * RETURN:      Value written to from specified Register.  This value
386 *              is shifted all the way right.
387 *
388 * DESCRIPTION: ACPI Bit Register write function.
389 *
390 ******************************************************************************/
391
392UINT32
393AcpiHwBitRegisterWrite (
394    UINT32                  RegisterId,
395    UINT32                  Value,
396    UINT32                  Flags)
397{
398    UINT32                  RegisterValue = 0;
399    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
400
401
402    ACPI_FUNCTION_TRACE_U32 ("HwBitRegisterWrite", RegisterId);
403
404
405    if (Flags & ACPI_MTX_LOCK)
406    {
407        if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_HARDWARE)))
408        {
409            return_VALUE (0);
410        }
411    }
412
413    /* Get the info structure corresponding to the requested ACPI Register */
414
415    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
416    if (!BitRegInfo)
417    {
418        return_ACPI_STATUS (AE_BAD_PARAMETER);
419    }
420
421    /* Always do a register read first so we can insert the new bits  */
422
423    RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, BitRegInfo->ParentRegister);
424
425    /*
426     * Decode the Register ID
427     * Register id = Register block id | bit id
428     *
429     * Check bit id to fine locate Register offset.
430     * Check Mask to determine Register offset, and then read-write.
431     */
432    switch (BitRegInfo->ParentRegister)
433    {
434    case ACPI_REGISTER_PM1_STATUS:
435
436        /*
437         * Status Registers are different from the rest.  Clear by
438         * writing 1, writing 0 has no effect.  So, the only relevent
439         * information is the single bit we're interested in, all others should
440         * be written as 0 so they will be left unchanged
441         */
442        Value = ACPI_REGISTER_PREPARE_BITS (Value, BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
443        if (Value)
444        {
445            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS,
446                (UINT16) Value);
447            RegisterValue = 0;
448        }
449        break;
450
451
452    case ACPI_REGISTER_PM1_ENABLE:
453
454        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, BitRegInfo->AccessBitMask, Value);
455
456        AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE, (UINT16) RegisterValue);
457        break;
458
459
460    case ACPI_REGISTER_PM1_CONTROL:
461
462        /*
463         * Read the PM1 Control register.
464         * Note that at this level, the fact that there are actually TWO
465         * registers (A and B - and that B may not exist) is abstracted.
466         */
467        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", RegisterValue));
468
469        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, BitRegInfo->AccessBitMask, Value);
470
471        AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, RegisterId,
472                (UINT16) RegisterValue);
473        break;
474
475
476    case ACPI_REGISTER_PM2_CONTROL:
477
478        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM2_CONTROL);
479
480        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
481            RegisterValue, ACPI_HIDWORD (AcpiGbl_FADT->XPm2CntBlk.Address),
482            ACPI_LODWORD (AcpiGbl_FADT->XPm2CntBlk.Address)));
483
484        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, BitRegInfo->AccessBitMask, Value);
485
486        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
487            RegisterValue,
488            ACPI_HIDWORD (AcpiGbl_FADT->XPm2CntBlk.Address),
489            ACPI_LODWORD (AcpiGbl_FADT->XPm2CntBlk.Address)));
490
491        AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
492                            ACPI_REGISTER_PM2_CONTROL, (UINT8) (RegisterValue));
493        break;
494
495
496    default:
497        break;
498    }
499
500    if (Flags & ACPI_MTX_LOCK)
501    {
502        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
503    }
504
505    /* Normalize the value that was read */
506
507    RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask) >> BitRegInfo->BitPosition);
508
509    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "ACPI RegisterWrite actual %X\n", RegisterValue));
510    return_VALUE (RegisterValue);
511}
512
513
514/******************************************************************************
515 *
516 * FUNCTION:    AcpiHwRegisterRead
517 *
518 * PARAMETERS:  UseLock                - Mutex hw access.
519 *              RegisterId             - RegisterID + Offset.
520 *
521 * RETURN:      Value read or written.
522 *
523 * DESCRIPTION: Acpi register read function.  Registers are read at the
524 *              given offset.
525 *
526 ******************************************************************************/
527
528UINT32
529AcpiHwRegisterRead (
530    BOOLEAN                 UseLock,
531    UINT32                  RegisterId)
532{
533    UINT32                  Value = 0;
534    UINT32                  BankOffset;
535
536
537    ACPI_FUNCTION_TRACE ("HwRegisterRead");
538
539
540    if (ACPI_MTX_LOCK == UseLock)
541    {
542        if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_HARDWARE)))
543        {
544            return_VALUE (0);
545        }
546    }
547
548    switch (RegisterId)
549    {
550    case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
551
552        Value =  AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aEvtBlk, 0);
553        Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bEvtBlk, 0);
554        break;
555
556
557    case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access*/
558
559        BankOffset  = ACPI_DIV_2 (AcpiGbl_FADT->Pm1EvtLen);
560        Value =  AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aEvtBlk, BankOffset);
561        Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bEvtBlk, BankOffset);
562        break;
563
564
565    case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
566
567        Value =  AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aCntBlk, 0);
568        Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bCntBlk, 0);
569        break;
570
571
572    case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
573
574        Value =  AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XPm2CntBlk, 0);
575        break;
576
577
578    case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
579
580        Value =  AcpiHwLowLevelRead (32, &AcpiGbl_FADT->XPmTmrBlk, 0);
581        break;
582
583    case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
584
585        AcpiOsReadPort (AcpiGbl_FADT->SmiCmd, &Value, 8);
586        break;
587
588    default:
589        /* Value will be returned as 0 */
590        break;
591    }
592
593    if (ACPI_MTX_LOCK == UseLock)
594    {
595        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
596    }
597
598    return_VALUE (Value);
599}
600
601
602/******************************************************************************
603 *
604 * FUNCTION:    AcpiHwRegisterWrite
605 *
606 * PARAMETERS:  UseLock                - Mutex hw access.
607 *              RegisterId             - RegisterID + Offset.
608 *
609 * RETURN:      Value read or written.
610 *
611 * DESCRIPTION: Acpi register Write function.  Registers are written at the
612 *              given offset.
613 *
614 ******************************************************************************/
615
616void
617AcpiHwRegisterWrite (
618    BOOLEAN                 UseLock,
619    UINT32                  RegisterId,
620    UINT32                  Value)
621{
622    UINT32                  BankOffset;
623
624
625    ACPI_FUNCTION_TRACE ("HwRegisterWrite");
626
627
628    if (ACPI_MTX_LOCK == UseLock)
629    {
630        if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_HARDWARE)))
631        {
632            return_VOID;
633        }
634    }
635
636    switch (RegisterId)
637    {
638    case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
639
640        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk, 0);
641        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk, 0);
642        break;
643
644
645    case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access*/
646
647        BankOffset = ACPI_DIV_2 (AcpiGbl_FADT->Pm1EvtLen);
648        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk, BankOffset);
649        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk, BankOffset);
650        break;
651
652
653    case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
654
655        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk, 0);
656        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk, 0);
657        break;
658
659
660    case ACPI_REGISTER_PM1A_CONTROL:         /* 16-bit access */
661
662        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk, 0);
663        break;
664
665
666    case ACPI_REGISTER_PM1B_CONTROL:         /* 16-bit access */
667
668        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk, 0);
669        break;
670
671
672    case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
673
674        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XPm2CntBlk, 0);
675        break;
676
677
678    case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
679
680        AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT->XPmTmrBlk, 0);
681        break;
682
683
684    case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
685
686        /* SMI_CMD is currently always in IO space */
687
688        AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, Value, 8);
689        break;
690
691
692    default:
693        Value = 0;
694        break;
695    }
696
697    if (ACPI_MTX_LOCK == UseLock)
698    {
699        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
700    }
701
702    return_VOID;
703}
704
705
706/******************************************************************************
707 *
708 * FUNCTION:    AcpiHwLowLevelRead
709 *
710 * PARAMETERS:  Register            - GAS register structure
711 *              Offset              - Offset from the base address in the GAS
712 *              Width               - 8, 16, or 32
713 *
714 * RETURN:      Value read
715 *
716 * DESCRIPTION: Read from either memory, IO, or PCI config space.
717 *
718 ******************************************************************************/
719
720UINT32
721AcpiHwLowLevelRead (
722    UINT32                  Width,
723    ACPI_GENERIC_ADDRESS    *Reg,
724    UINT32                  Offset)
725{
726    UINT32                  Value = 0;
727    ACPI_PHYSICAL_ADDRESS   MemAddress;
728    ACPI_IO_ADDRESS         IoAddress;
729    ACPI_PCI_ID             PciId;
730    UINT16                  PciRegister;
731
732
733    ACPI_FUNCTION_ENTRY ();
734
735
736    /*
737     * Must have a valid pointer to a GAS structure, and
738     * a non-zero address within
739     */
740    if ((!Reg) ||
741        (!ACPI_VALID_ADDRESS (Reg->Address)))
742    {
743        return 0;
744    }
745
746    /*
747     * Three address spaces supported:
748     * Memory, Io, or PCI config.
749     */
750    switch (Reg->AddressSpaceId)
751    {
752    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
753
754        MemAddress = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
755
756        AcpiOsReadMemory (MemAddress, &Value, Width);
757        break;
758
759
760    case ACPI_ADR_SPACE_SYSTEM_IO:
761
762        IoAddress = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
763
764        AcpiOsReadPort (IoAddress, &Value, Width);
765        break;
766
767
768    case ACPI_ADR_SPACE_PCI_CONFIG:
769
770        PciId.Segment  = 0;
771        PciId.Bus      = 0;
772        PciId.Device   = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (Reg->Address));
773        PciId.Function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (Reg->Address));
774        PciRegister    = (UINT16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address)) + Offset);
775
776        AcpiOsReadPciConfiguration  (&PciId, PciRegister, &Value, Width);
777        break;
778    }
779
780    return Value;
781}
782
783
784/******************************************************************************
785 *
786 * FUNCTION:    AcpiHwLowLevelWrite
787 *
788 * PARAMETERS:  Width               - 8, 16, or 32
789 *              Value               - To be written
790 *              Register            - GAS register structure
791 *              Offset              - Offset from the base address in the GAS
792 *
793 *
794 * RETURN:      Value read
795 *
796 * DESCRIPTION: Read from either memory, IO, or PCI config space.
797 *
798 ******************************************************************************/
799
800void
801AcpiHwLowLevelWrite (
802    UINT32                  Width,
803    UINT32                  Value,
804    ACPI_GENERIC_ADDRESS    *Reg,
805    UINT32                  Offset)
806{
807    ACPI_PHYSICAL_ADDRESS   MemAddress;
808    ACPI_IO_ADDRESS         IoAddress;
809    ACPI_PCI_ID             PciId;
810    UINT16                  PciRegister;
811
812
813    ACPI_FUNCTION_ENTRY ();
814
815
816    /*
817     * Must have a valid pointer to a GAS structure, and
818     * a non-zero address within
819     */
820    if ((!Reg) ||
821        (!ACPI_VALID_ADDRESS (Reg->Address)))
822    {
823        return;
824    }
825
826    /*
827     * Three address spaces supported:
828     * Memory, Io, or PCI config.
829     */
830    switch (Reg->AddressSpaceId)
831    {
832    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
833
834        MemAddress = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
835
836        AcpiOsWriteMemory (MemAddress, Value, Width);
837        break;
838
839
840    case ACPI_ADR_SPACE_SYSTEM_IO:
841
842        IoAddress = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
843
844        AcpiOsWritePort (IoAddress, Value, Width);
845        break;
846
847
848    case ACPI_ADR_SPACE_PCI_CONFIG:
849
850        PciId.Segment  = 0;
851        PciId.Bus      = 0;
852        PciId.Device   = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (Reg->Address));
853        PciId.Function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (Reg->Address));
854        PciRegister    = (UINT16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address)) + Offset);
855
856        AcpiOsWritePciConfiguration (&PciId, PciRegister, Value, Width);
857        break;
858    }
859}
860