hwacpi.c revision 69746
1/******************************************************************************
2 *
3 * Module Name: hwacpi - ACPI hardware functions - mode and timer
4 *              $Revision: 32 $
5 *
6 *****************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999, Intel Corp.  All rights
13 * reserved.
14 *
15 * 2. License
16 *
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights.  You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
20 * property rights.
21 *
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
28 *
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code.  No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision.  In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change.  Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee.  Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
54 *
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117#define __HWACPI_C__
118
119#include "acpi.h"
120#include "achware.h"
121
122
123#define _COMPONENT          HARDWARE
124        MODULE_NAME         ("hwacpi")
125
126
127/******************************************************************************
128 *
129 * FUNCTION:    AcpiHwInitialize
130 *
131 * PARAMETERS:  None
132 *
133 * RETURN:      Status
134 *
135 * DESCRIPTION: Initialize and validate various ACPI registers
136 *
137 ******************************************************************************/
138
139ACPI_STATUS
140AcpiHwInitialize (
141    void)
142{
143    ACPI_STATUS             Status = AE_OK;
144    UINT32                  Index;
145
146
147    FUNCTION_TRACE ("HwInitialize");
148
149
150    /* We must have the ACPI tables by the time we get here */
151
152    if (!AcpiGbl_FADT)
153    {
154        AcpiGbl_RestoreAcpiChipset = FALSE;
155
156        DEBUG_PRINT (ACPI_ERROR, ("HwInitialize: No FADT!\n"));
157
158        return_ACPI_STATUS (AE_NO_ACPI_TABLES);
159    }
160
161    /* Must support *some* mode! */
162/*
163    if (!(SystemFlags & SYS_MODES_MASK))
164    {
165        RestoreAcpiChipset = FALSE;
166
167        DEBUG_PRINT (ACPI_ERROR,
168            ("CmHardwareInitialize: Supported modes uninitialized!\n"));
169        return_ACPI_STATUS (AE_ERROR);
170    }
171
172*/
173
174
175    switch (AcpiGbl_SystemFlags & SYS_MODES_MASK)
176    {
177        /* Identify current ACPI/legacy mode   */
178
179    case (SYS_MODE_ACPI):
180
181        AcpiGbl_OriginalMode = SYS_MODE_ACPI;
182        DEBUG_PRINT (ACPI_INFO, ("System supports ACPI mode only.\n"));
183        break;
184
185
186    case (SYS_MODE_LEGACY):
187
188        AcpiGbl_OriginalMode = SYS_MODE_LEGACY;
189        DEBUG_PRINT (ACPI_INFO,
190            ("Tables loaded from buffer, hardware assumed to support LEGACY mode only.\n"));
191        break;
192
193
194    case (SYS_MODE_ACPI | SYS_MODE_LEGACY):
195
196        if (AcpiHwGetMode () == SYS_MODE_ACPI)
197        {
198            AcpiGbl_OriginalMode = SYS_MODE_ACPI;
199        }
200        else
201        {
202            AcpiGbl_OriginalMode = SYS_MODE_LEGACY;
203        }
204
205        DEBUG_PRINT (ACPI_INFO,
206            ("System supports both ACPI and LEGACY modes.\n"));
207
208        DEBUG_PRINT (ACPI_INFO,
209            ("System is currently in %s mode.\n",
210            (AcpiGbl_OriginalMode == SYS_MODE_ACPI) ? "ACPI" : "LEGACY"));
211        break;
212    }
213
214
215    if (AcpiGbl_SystemFlags & SYS_MODE_ACPI)
216    {
217        /* Target system supports ACPI mode */
218
219        /*
220         * The purpose of this code is to save the initial state
221         * of the ACPI event enable registers. An exit function will be
222         * registered which will restore this state when the application
223         * exits. The exit function will also clear all of the ACPI event
224         * status bits prior to restoring the original mode.
225         *
226         * The location of the PM1aEvtBlk enable registers is defined as the
227         * base of PM1aEvtBlk + DIV_2(PM1aEvtBlkLength). Since the spec further
228         * fully defines the PM1aEvtBlk to be a total of 4 bytes, the offset
229         * for the enable registers is always 2 from the base. It is hard
230         * coded here. If this changes in the spec, this code will need to
231         * be modified. The PM1bEvtBlk behaves as expected.
232         */
233
234        AcpiGbl_Pm1EnableRegisterSave = (UINT16) AcpiHwRegisterRead (ACPI_MTX_LOCK, PM1_EN);
235
236
237        /*
238         * The GPEs behave similarly, except that the length of the register
239         * block is not fixed, so the buffer must be allocated with malloc
240         */
241
242        if (AcpiGbl_FADT->XGpe0Blk.Address && AcpiGbl_FADT->Gpe0BlkLen)
243        {
244            /* GPE0 specified in FADT  */
245
246            AcpiGbl_Gpe0EnableRegisterSave =
247                AcpiCmAllocate (DIV_2 (AcpiGbl_FADT->Gpe0BlkLen));
248            if (!AcpiGbl_Gpe0EnableRegisterSave)
249            {
250                return_ACPI_STATUS (AE_NO_MEMORY);
251            }
252
253            /* Save state of GPE0 enable bits */
254
255            for (Index = 0; Index < DIV_2 (AcpiGbl_FADT->Gpe0BlkLen); Index++)
256            {
257                AcpiGbl_Gpe0EnableRegisterSave[Index] =
258                    (UINT8) AcpiHwRegisterRead (ACPI_MTX_LOCK, GPE0_EN_BLOCK | Index);
259            }
260        }
261
262        else
263        {
264            AcpiGbl_Gpe0EnableRegisterSave = NULL;
265        }
266
267        if (AcpiGbl_FADT->XGpe1Blk.Address && AcpiGbl_FADT->Gpe1BlkLen)
268        {
269            /* GPE1 defined */
270
271            AcpiGbl_Gpe1EnableRegisterSave =
272                AcpiCmAllocate (DIV_2 (AcpiGbl_FADT->Gpe1BlkLen));
273            if (!AcpiGbl_Gpe1EnableRegisterSave)
274            {
275                return_ACPI_STATUS (AE_NO_MEMORY);
276            }
277
278            /* save state of GPE1 enable bits */
279
280            for (Index = 0; Index < DIV_2 (AcpiGbl_FADT->Gpe1BlkLen); Index++)
281            {
282                AcpiGbl_Gpe1EnableRegisterSave[Index] =
283                    (UINT8) AcpiHwRegisterRead (ACPI_MTX_LOCK, GPE1_EN_BLOCK | Index);
284            }
285        }
286
287        else
288        {
289            AcpiGbl_Gpe1EnableRegisterSave = NULL;
290        }
291    }
292
293    return_ACPI_STATUS (Status);
294}
295
296
297/******************************************************************************
298 *
299 * FUNCTION:    AcpiHwSetMode
300 *
301 * PARAMETERS:  Mode            - SYS_MODE_ACPI or SYS_MODE_LEGACY
302 *
303 * RETURN:      Status
304 *
305 * DESCRIPTION: Transitions the system into the requested mode or does nothing
306 *              if the system is already in that mode.
307 *
308 ******************************************************************************/
309
310ACPI_STATUS
311AcpiHwSetMode (
312    UINT32                  Mode)
313{
314
315    ACPI_STATUS             Status = AE_ERROR;
316
317    FUNCTION_TRACE ("HwSetMode");
318
319
320    if (Mode == SYS_MODE_ACPI)
321    {
322        /* BIOS should have disabled ALL fixed and GP events */
323
324        AcpiOsOut8 (AcpiGbl_FADT->SmiCmd, AcpiGbl_FADT->AcpiEnable);
325        DEBUG_PRINT (ACPI_INFO, ("Attempting to enable ACPI mode\n"));
326    }
327
328    else if (Mode == SYS_MODE_LEGACY)
329    {
330        /*
331         * BIOS should clear all fixed status bits and restore fixed event
332         * enable bits to default
333         */
334
335        AcpiOsOut8 (AcpiGbl_FADT->SmiCmd, AcpiGbl_FADT->AcpiDisable);
336        DEBUG_PRINT (ACPI_INFO,
337                    ("Attempting to enable Legacy (non-ACPI) mode\n"));
338    }
339
340    if (AcpiHwGetMode () == Mode)
341    {
342        DEBUG_PRINT (ACPI_INFO, ("Mode %X successfully enabled\n", Mode));
343        Status = AE_OK;
344    }
345
346    return_ACPI_STATUS (Status);
347}
348
349
350/******************************************************************************
351 *
352 * FUNCTION:    AcpiHwGetMode
353 *
354 * PARAMETERS:  none
355 *
356 * RETURN:      SYS_MODE_ACPI or SYS_MODE_LEGACY
357 *
358 * DESCRIPTION: Return current operating state of system.  Determined by
359 *              querying the SCI_EN bit.
360 *
361 ******************************************************************************/
362
363UINT32
364AcpiHwGetMode (void)
365{
366
367    FUNCTION_TRACE ("HwGetMode");
368
369
370    if (AcpiHwRegisterBitAccess (ACPI_READ, ACPI_MTX_LOCK, SCI_EN))
371    {
372        return_VALUE (SYS_MODE_ACPI);
373    }
374    else
375    {
376        return_VALUE (SYS_MODE_LEGACY);
377    }
378}
379
380/******************************************************************************
381 *
382 * FUNCTION:    AcpiHwGetModeCapabilities
383 *
384 * PARAMETERS:  none
385 *
386 * RETURN:      logical OR of SYS_MODE_ACPI and SYS_MODE_LEGACY determined at initial
387 *              system state.
388 *
389 * DESCRIPTION: Returns capablities of system
390 *
391 ******************************************************************************/
392
393UINT32
394AcpiHwGetModeCapabilities (void)
395{
396
397    FUNCTION_TRACE ("HwGetModeCapabilities");
398
399
400    if (!(AcpiGbl_SystemFlags & SYS_MODES_MASK))
401    {
402        if (AcpiHwGetMode () == SYS_MODE_LEGACY)
403        {
404            /*
405             * Assume that if this call is being made, AcpiInit has been called
406             * and ACPI support has been established by the presence of the
407             * tables.  Therefore since we're in SYS_MODE_LEGACY, the system
408             * must support both modes
409             */
410
411            AcpiGbl_SystemFlags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
412        }
413
414        else
415        {
416            /* TBD: [Investigate] !!! this may be unsafe... */
417            /*
418             * system is is ACPI mode, so try to switch back to LEGACY to see if
419             * it is supported
420             */
421            AcpiHwSetMode (SYS_MODE_LEGACY);
422
423            if (AcpiHwGetMode () == SYS_MODE_LEGACY)
424            {
425                /* Now in SYS_MODE_LEGACY, so both are supported */
426
427                AcpiGbl_SystemFlags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
428                AcpiHwSetMode (SYS_MODE_ACPI);
429            }
430
431            else
432            {
433                /* Still in SYS_MODE_ACPI so this must be an ACPI only system */
434
435                AcpiGbl_SystemFlags |= SYS_MODE_ACPI;
436            }
437        }
438    }
439
440    return_VALUE (AcpiGbl_SystemFlags & SYS_MODES_MASK);
441}
442
443
444/******************************************************************************
445 *
446 * FUNCTION:    AcpiHwPmtTicks
447 *
448 * PARAMETERS:  none
449 *
450 * RETURN:      Current value of the ACPI PMT (timer)
451 *
452 * DESCRIPTION: Obtains current value of ACPI PMT
453 *
454 ******************************************************************************/
455
456UINT32
457AcpiHwPmtTicks (void)
458{
459    UINT32                   Ticks;
460
461    FUNCTION_TRACE ("AcpiPmtTicks");
462
463    Ticks = AcpiOsIn32 ((ACPI_IO_ADDRESS) AcpiGbl_FADT->XPmTmrBlk.Address);
464
465    return_VALUE (Ticks);
466}
467
468
469/******************************************************************************
470 *
471 * FUNCTION:    AcpiHwPmtResolution
472 *
473 * PARAMETERS:  none
474 *
475 * RETURN:      Number of bits of resolution in the PMT (either 24 or 32)
476 *
477 * DESCRIPTION: Obtains resolution of the ACPI PMT (either 24bit or 32bit)
478 *
479 ******************************************************************************/
480
481UINT32
482AcpiHwPmtResolution (void)
483{
484    FUNCTION_TRACE ("AcpiPmtResolution");
485
486    if (0 == AcpiGbl_FADT->TmrValExt)
487    {
488        return_VALUE (24);
489    }
490
491    return_VALUE (32);
492}
493
494