sync with trunk r46493
[reactos.git] / drivers / bus / acpi / events / evsci.c
1 /*******************************************************************************
2 *
3 * Module Name: evsci - System Control Interrupt configuration and
4 * legacy to ACPI mode state transition functions
5 * $Revision: 1.1 $
6 *
7 ******************************************************************************/
8
9 /*
10 * Copyright (C) 2000, 2001 R. Byron Moore
11 *
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.
16 *
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.
21 *
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
25 */
26
27 #include <acpi.h>
28
29 #define _COMPONENT ACPI_EVENTS
30 MODULE_NAME ("evsci")
31
32
33 /*
34 * Elements correspond to counts for TMR, NOT_USED, GBL, PWR_BTN, SLP_BTN, RTC,
35 * and GENERAL respectively. These counts are modified by the ACPI interrupt
36 * handler.
37 *
38 * TBD: [Investigate] Note that GENERAL should probably be split out into
39 * one element for each bit in the GPE registers
40 */
41
42
43 /*******************************************************************************
44 *
45 * FUNCTION: Acpi_ev_sci_handler
46 *
47 * PARAMETERS: Context - Calling Context
48 *
49 * RETURN: Status code indicates whether interrupt was handled.
50 *
51 * DESCRIPTION: Interrupt handler that will figure out what function or
52 * control method to call to deal with a SCI. Installed
53 * using BU interrupt support.
54 *
55 ******************************************************************************/
56
57 static u32
58 acpi_ev_sci_handler (void *context)
59 {
60 u32 interrupt_handled = INTERRUPT_NOT_HANDLED;
61
62
63 /*
64 * Make sure that ACPI is enabled by checking SCI_EN. Note that we are
65 * required to treat the SCI interrupt as sharable, level, active low.
66 */
67 if (!acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_DO_NOT_LOCK, SCI_EN)) {
68 /* ACPI is not enabled; this interrupt cannot be for us */
69
70 return (INTERRUPT_NOT_HANDLED);
71 }
72
73 /*
74 * Fixed Acpi_events:
75 * -------------
76 * Check for and dispatch any Fixed Acpi_events that have occurred
77 */
78 interrupt_handled |= acpi_ev_fixed_event_detect ();
79
80 /*
81 * GPEs:
82 * -----
83 * Check for and dispatch any GPEs that have occurred
84 */
85 interrupt_handled |= acpi_ev_gpe_detect ();
86
87 return (interrupt_handled);
88 }
89
90
91 /******************************************************************************
92 *
93 * FUNCTION: Acpi_ev_install_sci_handler
94 *
95 * PARAMETERS: none
96 *
97 * RETURN: Status
98 *
99 * DESCRIPTION: Installs SCI handler.
100 *
101 ******************************************************************************/
102
103 u32
104 acpi_ev_install_sci_handler (void)
105 {
106 u32 except = AE_OK;
107
108
109 except = acpi_os_install_interrupt_handler ((u32) acpi_gbl_FADT->sci_int,
110 acpi_ev_sci_handler,
111 NULL);
112
113 return (except);
114 }
115
116
117 /******************************************************************************
118
119 *
120 * FUNCTION: Acpi_ev_remove_sci_handler
121 *
122 * PARAMETERS: none
123 *
124 * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not
125 * installed to begin with
126 *
127 * DESCRIPTION: Restores original status of all fixed event enable bits and
128 * removes SCI handler.
129 *
130 ******************************************************************************/
131
132 ACPI_STATUS
133 acpi_ev_remove_sci_handler (void)
134 {
135 #if 0
136 /* TBD:[Investigate] Figure this out!! Disable all events first ??? */
137
138 if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (TMR_FIXED_EVENT)) {
139 acpi_event_disable_event (TMR_FIXED_EVENT);
140 }
141
142 if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (GBL_FIXED_EVENT)) {
143 acpi_event_disable_event (GBL_FIXED_EVENT);
144 }
145
146 if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (PWR_BTN_FIXED_EVENT)) {
147 acpi_event_disable_event (PWR_BTN_FIXED_EVENT);
148 }
149
150 if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (SLP_BTN_FIXED_EVENT)) {
151 acpi_event_disable_event (SLP_BTN_FIXED_EVENT);
152 }
153
154 if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (RTC_FIXED_EVENT)) {
155 acpi_event_disable_event (RTC_FIXED_EVENT);
156 }
157
158 original_fixed_enable_bit_status = 0;
159
160 #endif
161
162 acpi_os_remove_interrupt_handler ((u32) acpi_gbl_FADT->sci_int,
163 acpi_ev_sci_handler);
164
165 return (AE_OK);
166 }
167
168
169 /*******************************************************************************
170 *
171 * FUNCTION: Acpi_ev_restore_acpi_state
172 *
173 * PARAMETERS: none
174 *
175 * RETURN: none
176 *
177 * DESCRIPTION: Restore the original ACPI state of the machine
178 *
179 ******************************************************************************/
180
181 void
182 acpi_ev_restore_acpi_state (void)
183 {
184 u32 index;
185
186
187 /* Restore the state of the chipset enable bits. */
188
189 if (acpi_gbl_restore_acpi_chipset == TRUE) {
190 /* Restore the fixed events */
191
192 if (acpi_hw_register_read (ACPI_MTX_LOCK, PM1_EN) !=
193 acpi_gbl_pm1_enable_register_save) {
194 acpi_hw_register_write (ACPI_MTX_LOCK, PM1_EN,
195 acpi_gbl_pm1_enable_register_save);
196 }
197
198
199 /* Ensure that all status bits are clear */
200
201 acpi_hw_clear_acpi_status ();
202
203
204 /* Now restore the GPEs */
205
206 for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) {
207 if (acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index) !=
208 acpi_gbl_gpe0enable_register_save[index]) {
209 acpi_hw_register_write (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index,
210 acpi_gbl_gpe0enable_register_save[index]);
211 }
212 }
213
214 /* GPE 1 present? */
215
216 if (acpi_gbl_FADT->gpe1_blk_len) {
217 for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) {
218 if (acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index) !=
219 acpi_gbl_gpe1_enable_register_save[index]) {
220 acpi_hw_register_write (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index,
221 acpi_gbl_gpe1_enable_register_save[index]);
222 }
223 }
224 }
225
226 if (acpi_hw_get_mode() != acpi_gbl_original_mode) {
227 acpi_hw_set_mode (acpi_gbl_original_mode);
228 }
229 }
230
231 return;
232 }
233
234
235 /******************************************************************************
236 *
237 * FUNCTION: Acpi_ev_terminate
238 *
239 * PARAMETERS: none
240 *
241 * RETURN: none
242 *
243 * DESCRIPTION: free memory allocated for table storage.
244 *
245 ******************************************************************************/
246
247 void
248 acpi_ev_terminate (void)
249 {
250
251
252 /*
253 * Free global tables, etc.
254 */
255
256 if (acpi_gbl_gpe_registers) {
257 acpi_cm_free (acpi_gbl_gpe_registers);
258 }
259
260 if (acpi_gbl_gpe_info) {
261 acpi_cm_free (acpi_gbl_gpe_info);
262 }
263
264 return;
265 }
266
267