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