hwacpi.c revision 67754
1/******************************************************************************
2 *
3 * Module Name: hwacpi - ACPI hardware functions - mode and timer
4 *              $Revision: 24 $
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_FACP)
153    {
154        AcpiGbl_RestoreAcpiChipset = FALSE;
155
156        DEBUG_PRINT (ACPI_ERROR, ("HwInitialize: No FACP!\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 block of 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 + PM1aEvtBlkLength / 2. 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 =
235            AcpiOsIn16 ((AcpiGbl_FACP->Pm1aEvtBlk + 2));
236        if (AcpiGbl_FACP->Pm1bEvtBlk)
237        {
238            AcpiGbl_Pm1EnableRegisterSave |=
239                AcpiOsIn16 ((AcpiGbl_FACP->Pm1bEvtBlk + 2));
240        }
241
242
243        /*
244         * The GPEs behave similarly, except that the length of the register
245         * block is not fixed, so the buffer must be allocated with malloc
246         */
247
248        if (AcpiGbl_FACP->Gpe0Blk && AcpiGbl_FACP->Gpe0BlkLen)
249        {
250            /* GPE0 specified in FACP  */
251
252            AcpiGbl_Gpe0EnableRegisterSave =
253                AcpiCmAllocate (DIV_2 (AcpiGbl_FACP->Gpe0BlkLen));
254            if (!AcpiGbl_Gpe0EnableRegisterSave)
255            {
256                return_ACPI_STATUS (AE_NO_MEMORY);
257            }
258
259            /* Save state of GPE0 enable bits */
260
261            for (Index = 0; Index < DIV_2 (AcpiGbl_FACP->Gpe0BlkLen); Index++)
262            {
263                AcpiGbl_Gpe0EnableRegisterSave[Index] =
264                    AcpiOsIn8 (AcpiGbl_FACP->Gpe0Blk +
265                    DIV_2 (AcpiGbl_FACP->Gpe0BlkLen));
266            }
267        }
268
269        else
270        {
271            AcpiGbl_Gpe0EnableRegisterSave = NULL;
272        }
273
274        if (AcpiGbl_FACP->Gpe1Blk && AcpiGbl_FACP->Gpe1BlkLen)
275        {
276            /* GPE1 defined */
277
278            AcpiGbl_Gpe1EnableRegisterSave =
279                AcpiCmAllocate (DIV_2 (AcpiGbl_FACP->Gpe1BlkLen));
280            if (!AcpiGbl_Gpe1EnableRegisterSave)
281            {
282                return_ACPI_STATUS (AE_NO_MEMORY);
283            }
284
285            /* save state of GPE1 enable bits */
286
287            for (Index = 0; Index < DIV_2 (AcpiGbl_FACP->Gpe1BlkLen); Index++)
288            {
289                AcpiGbl_Gpe1EnableRegisterSave[Index] =
290                    AcpiOsIn8 (AcpiGbl_FACP->Gpe1Blk +
291                    DIV_2 (AcpiGbl_FACP->Gpe1BlkLen));
292            }
293        }
294
295        else
296        {
297            AcpiGbl_Gpe1EnableRegisterSave = NULL;
298        }
299    }
300
301    return_ACPI_STATUS (Status);
302}
303
304
305/******************************************************************************
306 *
307 * FUNCTION:    AcpiHwSetMode
308 *
309 * PARAMETERS:  Mode            - SYS_MODE_ACPI or SYS_MODE_LEGACY
310 *
311 * RETURN:      Status
312 *
313 * DESCRIPTION: Transitions the system into the requested mode or does nothing
314 *              if the system is already in that mode.
315 *
316 ******************************************************************************/
317
318ACPI_STATUS
319AcpiHwSetMode (
320    UINT32                  Mode)
321{
322
323    ACPI_STATUS             Status = AE_ERROR;
324
325    FUNCTION_TRACE ("HwSetMode");
326
327
328    if (Mode == SYS_MODE_ACPI)
329    {
330        /* BIOS should have disabled ALL fixed and GP events */
331
332        AcpiOsOut8 (AcpiGbl_FACP->SmiCmd, AcpiGbl_FACP->AcpiEnable);
333        DEBUG_PRINT (ACPI_INFO, ("Attempting to enable ACPI mode\n"));
334    }
335
336    else if (Mode == SYS_MODE_LEGACY)
337    {
338        /*
339         * BIOS should clear all fixed status bits and restore fixed event
340         * enable bits to default
341         */
342
343        AcpiOsOut8 (AcpiGbl_FACP->SmiCmd, AcpiGbl_FACP->AcpiDisable);
344        DEBUG_PRINT (ACPI_INFO,
345                    ("Attempting to enable Legacy (non-ACPI) mode\n"));
346    }
347
348    if (AcpiHwGetMode () == Mode)
349    {
350        DEBUG_PRINT (ACPI_INFO, ("Mode %d successfully enabled\n", Mode));
351        Status = AE_OK;
352    }
353
354    return_ACPI_STATUS (Status);
355}
356
357
358/******************************************************************************
359 *
360 * FUNCTION:    AcpiHwGetMode
361 *
362 * PARAMETERS:  none
363 *
364 * RETURN:      SYS_MODE_ACPI or SYS_MODE_LEGACY
365 *
366 * DESCRIPTION: Return current operating state of system.  Determined by
367 *              querying the SCI_EN bit.
368 *
369 ******************************************************************************/
370
371UINT32
372AcpiHwGetMode (void)
373{
374
375    FUNCTION_TRACE ("HwGetMode");
376
377
378    if (AcpiHwRegisterAccess (ACPI_READ, ACPI_MTX_LOCK, SCI_EN))
379    {
380        return_VALUE (SYS_MODE_ACPI);
381    }
382    else
383    {
384        return_VALUE (SYS_MODE_LEGACY);
385    }
386}
387
388/******************************************************************************
389 *
390 * FUNCTION:    AcpiHwGetModeCapabilities
391 *
392 * PARAMETERS:  none
393 *
394 * RETURN:      logical OR of SYS_MODE_ACPI and SYS_MODE_LEGACY determined at initial
395 *              system state.
396 *
397 * DESCRIPTION: Returns capablities of system
398 *
399 ******************************************************************************/
400
401UINT32
402AcpiHwGetModeCapabilities (void)
403{
404
405    FUNCTION_TRACE ("HwGetModeCapabilities");
406
407
408    if (!(AcpiGbl_SystemFlags & SYS_MODES_MASK))
409    {
410        if (AcpiHwGetMode () == SYS_MODE_LEGACY)
411        {
412            /*
413             * Assume that if this call is being made, AcpiInit has been called
414             * and ACPI support has been established by the presence of the
415             * tables.  Therefore since we're in SYS_MODE_LEGACY, the system
416             * must support both modes
417             */
418
419            AcpiGbl_SystemFlags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
420        }
421
422        else
423        {
424            /* TBD: [Investigate] !!! this may be unsafe... */
425            /*
426             * system is is ACPI mode, so try to switch back to LEGACY to see if
427             * it is supported
428             */
429            AcpiHwSetMode (SYS_MODE_LEGACY);
430
431            if (AcpiHwGetMode () == SYS_MODE_LEGACY)
432            {
433                /* Now in SYS_MODE_LEGACY, so both are supported */
434
435                AcpiGbl_SystemFlags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
436                AcpiHwSetMode (SYS_MODE_ACPI);
437            }
438
439            else
440            {
441                /* Still in SYS_MODE_ACPI so this must be an ACPI only system */
442
443                AcpiGbl_SystemFlags |= SYS_MODE_ACPI;
444            }
445        }
446    }
447
448    return_VALUE (AcpiGbl_SystemFlags & SYS_MODES_MASK);
449}
450
451
452/******************************************************************************
453 *
454 * FUNCTION:    AcpiHwPmtTicks
455 *
456 * PARAMETERS:  none
457 *
458 * RETURN:      Current value of the ACPI PMT (timer)
459 *
460 * DESCRIPTION: Obtains current value of ACPI PMT
461 *
462 ******************************************************************************/
463
464UINT32
465AcpiHwPmtTicks (void)
466{
467    UINT32                   Ticks;
468
469    FUNCTION_TRACE ("AcpiPmtTicks");
470
471    Ticks = AcpiOsIn32 (AcpiGbl_FACP->PmTmrBlk);
472
473    return_VALUE (Ticks);
474}
475
476
477/******************************************************************************
478 *
479 * FUNCTION:    AcpiHwPmtResolution
480 *
481 * PARAMETERS:  none
482 *
483 * RETURN:      Number of bits of resolution in the PMT (either 24 or 32)
484 *
485 * DESCRIPTION: Obtains resolution of the ACPI PMT (either 24bit or 32bit)
486 *
487 ******************************************************************************/
488
489UINT32
490AcpiHwPmtResolution (void)
491{
492    FUNCTION_TRACE ("AcpiPmtResolution");
493
494    if (0 == AcpiGbl_FACP->TmrValExt)
495    {
496        return_VALUE (24);
497    }
498
499    return_VALUE (32);
500}
501
502