2 /******************************************************************************
4 * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
7 *****************************************************************************/
10 * Copyright (C) 2000, 2001 R. Byron Moore
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #define _COMPONENT ACPI_HARDWARE
31 MODULE_NAME ("hwacpi")
34 /******************************************************************************
36 * FUNCTION: Acpi_hw_initialize
42 * DESCRIPTION: Initialize and validate various ACPI registers
44 ******************************************************************************/
50 ACPI_STATUS status
= AE_OK
;
54 /* We must have the ACPI tables by the time we get here */
57 acpi_gbl_restore_acpi_chipset
= FALSE
;
59 return (AE_NO_ACPI_TABLES
);
62 /* Must support *some* mode! */
64 if (!(System_flags & SYS_MODES_MASK))
66 Restore_acpi_chipset = FALSE;
74 switch (acpi_gbl_system_flags
& SYS_MODES_MASK
) {
75 /* Identify current ACPI/legacy mode */
79 acpi_gbl_original_mode
= SYS_MODE_ACPI
;
83 case (SYS_MODE_LEGACY
):
85 acpi_gbl_original_mode
= SYS_MODE_LEGACY
;
89 case (SYS_MODE_ACPI
| SYS_MODE_LEGACY
):
91 if (acpi_hw_get_mode () == SYS_MODE_ACPI
) {
92 acpi_gbl_original_mode
= SYS_MODE_ACPI
;
95 acpi_gbl_original_mode
= SYS_MODE_LEGACY
;
102 if (acpi_gbl_system_flags
& SYS_MODE_ACPI
) {
103 /* Target system supports ACPI mode */
106 * The purpose of this code is to save the initial state
107 * of the ACPI event enable registers. An exit function will be
108 * registered which will restore this state when the application
109 * exits. The exit function will also clear all of the ACPI event
110 * status bits prior to restoring the original mode.
112 * The location of the PM1a_evt_blk enable registers is defined as the
113 * base of PM1a_evt_blk + DIV_2(PM1a_evt_blk_length). Since the spec further
114 * fully defines the PM1a_evt_blk to be a total of 4 bytes, the offset
115 * for the enable registers is always 2 from the base. It is hard
116 * coded here. If this changes in the spec, this code will need to
117 * be modified. The PM1b_evt_blk behaves as expected.
120 acpi_gbl_pm1_enable_register_save
= (u16
) acpi_hw_register_read (ACPI_MTX_LOCK
, PM1_EN
);
124 * The GPEs behave similarly, except that the length of the register
125 * block is not fixed, so the buffer must be allocated with malloc
128 if (ACPI_VALID_ADDRESS (acpi_gbl_FADT
->Xgpe0blk
.address
) &&
129 acpi_gbl_FADT
->gpe0blk_len
) {
130 /* GPE0 specified in FADT */
132 acpi_gbl_gpe0enable_register_save
=
133 acpi_cm_allocate (DIV_2 (acpi_gbl_FADT
->gpe0blk_len
));
134 if (!acpi_gbl_gpe0enable_register_save
) {
135 return (AE_NO_MEMORY
);
138 /* Save state of GPE0 enable bits */
140 for (index
= 0; index
< DIV_2 (acpi_gbl_FADT
->gpe0blk_len
); index
++) {
141 acpi_gbl_gpe0enable_register_save
[index
] =
142 (u8
) acpi_hw_register_read (ACPI_MTX_LOCK
, GPE0_EN_BLOCK
| index
);
147 acpi_gbl_gpe0enable_register_save
= NULL
;
150 if (ACPI_VALID_ADDRESS (acpi_gbl_FADT
->Xgpe1_blk
.address
) &&
151 acpi_gbl_FADT
->gpe1_blk_len
) {
154 acpi_gbl_gpe1_enable_register_save
=
155 acpi_cm_allocate (DIV_2 (acpi_gbl_FADT
->gpe1_blk_len
));
156 if (!acpi_gbl_gpe1_enable_register_save
) {
157 return (AE_NO_MEMORY
);
160 /* save state of GPE1 enable bits */
162 for (index
= 0; index
< DIV_2 (acpi_gbl_FADT
->gpe1_blk_len
); index
++) {
163 acpi_gbl_gpe1_enable_register_save
[index
] =
164 (u8
) acpi_hw_register_read (ACPI_MTX_LOCK
, GPE1_EN_BLOCK
| index
);
169 acpi_gbl_gpe1_enable_register_save
= NULL
;
177 /******************************************************************************
179 * FUNCTION: Acpi_hw_set_mode
181 * PARAMETERS: Mode - SYS_MODE_ACPI or SYS_MODE_LEGACY
185 * DESCRIPTION: Transitions the system into the requested mode or does nothing
186 * if the system is already in that mode.
188 ******************************************************************************/
195 ACPI_STATUS status
= AE_NO_HARDWARE_RESPONSE
;
198 if (mode
== SYS_MODE_ACPI
) {
199 /* BIOS should have disabled ALL fixed and GP events */
201 acpi_os_out8 (acpi_gbl_FADT
->smi_cmd
, acpi_gbl_FADT
->acpi_enable
);
204 else if (mode
== SYS_MODE_LEGACY
) {
206 * BIOS should clear all fixed status bits and restore fixed event
207 * enable bits to default
210 acpi_os_out8 (acpi_gbl_FADT
->smi_cmd
, acpi_gbl_FADT
->acpi_disable
);
213 if (acpi_hw_get_mode () == mode
) {
221 /******************************************************************************
223 * FUNCTION: Acpi_hw_get_mode
227 * RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY
229 * DESCRIPTION: Return current operating state of system. Determined by
230 * querying the SCI_EN bit.
232 ******************************************************************************/
235 acpi_hw_get_mode (void)
239 if (acpi_hw_register_bit_access (ACPI_READ
, ACPI_MTX_LOCK
, SCI_EN
)) {
240 return (SYS_MODE_ACPI
);
243 return (SYS_MODE_LEGACY
);
247 /******************************************************************************
249 * FUNCTION: Acpi_hw_get_mode_capabilities
253 * RETURN: logical OR of SYS_MODE_ACPI and SYS_MODE_LEGACY determined at initial
256 * DESCRIPTION: Returns capablities of system
258 ******************************************************************************/
261 acpi_hw_get_mode_capabilities (void)
265 if (!(acpi_gbl_system_flags
& SYS_MODES_MASK
)) {
266 if (acpi_hw_get_mode () == SYS_MODE_LEGACY
) {
268 * Assume that if this call is being made, Acpi_init has been called
269 * and ACPI support has been established by the presence of the
270 * tables. Therefore since we're in SYS_MODE_LEGACY, the system
271 * must support both modes
274 acpi_gbl_system_flags
|= (SYS_MODE_ACPI
| SYS_MODE_LEGACY
);
278 /* TBD: [Investigate] !!! this may be unsafe... */
280 * system is is ACPI mode, so try to switch back to LEGACY to see if
283 acpi_hw_set_mode (SYS_MODE_LEGACY
);
285 if (acpi_hw_get_mode () == SYS_MODE_LEGACY
) {
286 /* Now in SYS_MODE_LEGACY, so both are supported */
288 acpi_gbl_system_flags
|= (SYS_MODE_ACPI
| SYS_MODE_LEGACY
);
289 acpi_hw_set_mode (SYS_MODE_ACPI
);
293 /* Still in SYS_MODE_ACPI so this must be an ACPI only system */
295 acpi_gbl_system_flags
|= SYS_MODE_ACPI
;
300 return (acpi_gbl_system_flags
& SYS_MODES_MASK
);