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