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