1 /******************************************************************************
2  *
3  * Module Name: evevent - Fixed Event handling and dispatch
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2004, R. Byron Moore
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include <acpi/acpi.h>
45 #include <acpi/acevents.h>
46 
47 #define _COMPONENT          ACPI_EVENTS
48 	 ACPI_MODULE_NAME    ("evevent")
49 
50 
51 /*******************************************************************************
52  *
53  * FUNCTION:    acpi_ev_initialize
54  *
55  * PARAMETERS:  None
56  *
57  * RETURN:      Status
58  *
59  * DESCRIPTION: Initialize global data structures for events.
60  *
61  ******************************************************************************/
62 
63 acpi_status
acpi_ev_initialize(void)64 acpi_ev_initialize (
65 	void)
66 {
67 	acpi_status                     status;
68 
69 
70 	ACPI_FUNCTION_TRACE ("ev_initialize");
71 
72 
73 	/* Make sure we have ACPI tables */
74 
75 	if (!acpi_gbl_DSDT) {
76 		ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No ACPI tables present!\n"));
77 		return_ACPI_STATUS (AE_NO_ACPI_TABLES);
78 	}
79 
80 	/*
81 	 * Initialize the Fixed and General Purpose Events. This is
82 	 * done prior to enabling SCIs to prevent interrupts from
83 	 * occurring before handers are installed.
84 	 */
85 	status = acpi_ev_fixed_event_initialize ();
86 	if (ACPI_FAILURE (status)) {
87 		ACPI_REPORT_ERROR ((
88 				"Unable to initialize fixed events, %s\n",
89 				acpi_format_exception (status)));
90 		return_ACPI_STATUS (status);
91 	}
92 
93 	status = acpi_ev_gpe_initialize ();
94 	if (ACPI_FAILURE (status)) {
95 		ACPI_REPORT_ERROR ((
96 				"Unable to initialize general purpose events, %s\n",
97 				acpi_format_exception (status)));
98 		return_ACPI_STATUS (status);
99 	}
100 
101 	return_ACPI_STATUS (status);
102 }
103 
104 
105 /*******************************************************************************
106  *
107  * FUNCTION:    acpi_ev_handler_initialize
108  *
109  * PARAMETERS:  None
110  *
111  * RETURN:      Status
112  *
113  * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock
114  *
115  ******************************************************************************/
116 
117 acpi_status
acpi_ev_handler_initialize(void)118 acpi_ev_handler_initialize (
119 	void)
120 {
121 	acpi_status                     status;
122 
123 
124 	ACPI_FUNCTION_TRACE ("ev_handler_initialize");
125 
126 
127 	/* Install the SCI handler */
128 
129 	status = acpi_ev_install_sci_handler ();
130 	if (ACPI_FAILURE (status)) {
131 		ACPI_REPORT_ERROR ((
132 				"Unable to install System Control Interrupt Handler, %s\n",
133 				acpi_format_exception (status)));
134 		return_ACPI_STATUS (status);
135 	}
136 
137 	/* Install the handler for the Global Lock */
138 
139 	status = acpi_ev_init_global_lock_handler ();
140 	if (ACPI_FAILURE (status)) {
141 		ACPI_REPORT_ERROR ((
142 				"Unable to initialize Global Lock handler, %s\n",
143 				acpi_format_exception (status)));
144 		return_ACPI_STATUS (status);
145 	}
146 
147 	acpi_gbl_events_initialized = TRUE;
148 	return_ACPI_STATUS (status);
149 }
150 
151 
152 /*******************************************************************************
153  *
154  * FUNCTION:    acpi_ev_fixed_event_initialize
155  *
156  * PARAMETERS:  None
157  *
158  * RETURN:      Status
159  *
160  * DESCRIPTION: Install the fixed event handlers and enable the fixed events.
161  *
162  ******************************************************************************/
163 
164 acpi_status
acpi_ev_fixed_event_initialize(void)165 acpi_ev_fixed_event_initialize (
166 	void)
167 {
168 	acpi_native_uint                i;
169 	acpi_status                     status;
170 
171 
172 	/*
173 	 * Initialize the structure that keeps track of fixed event handlers
174 	 * and enable the fixed events.
175 	 */
176 	for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
177 		acpi_gbl_fixed_event_handlers[i].handler = NULL;
178 		acpi_gbl_fixed_event_handlers[i].context = NULL;
179 
180 		/* Enable the fixed event */
181 
182 		if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) {
183 			status = acpi_set_register (acpi_gbl_fixed_event_info[i].enable_register_id,
184 					 0, ACPI_MTX_LOCK);
185 			if (ACPI_FAILURE (status)) {
186 				return (status);
187 			}
188 		}
189 	}
190 
191 	return (AE_OK);
192 }
193 
194 
195 /*******************************************************************************
196  *
197  * FUNCTION:    acpi_ev_fixed_event_detect
198  *
199  * PARAMETERS:  None
200  *
201  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
202  *
203  * DESCRIPTION: Checks the PM status register for fixed events
204  *
205  ******************************************************************************/
206 
207 u32
acpi_ev_fixed_event_detect(void)208 acpi_ev_fixed_event_detect (
209 	void)
210 {
211 	u32                             int_status = ACPI_INTERRUPT_NOT_HANDLED;
212 	u32                             fixed_status;
213 	u32                             fixed_enable;
214 	acpi_native_uint                i;
215 
216 
217 	ACPI_FUNCTION_NAME ("ev_fixed_event_detect");
218 
219 
220 	/*
221 	 * Read the fixed feature status and enable registers, as all the cases
222 	 * depend on their values.  Ignore errors here.
223 	 */
224 	(void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, &fixed_status);
225 	(void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
226 
227 	ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
228 		"Fixed Event Block: Enable %08X Status %08X\n",
229 		fixed_enable, fixed_status));
230 
231 	/*
232 	 * Check for all possible Fixed Events and dispatch those that are active
233 	 */
234 	for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
235 		/* Both the status and enable bits must be on for this event */
236 
237 		if ((fixed_status & acpi_gbl_fixed_event_info[i].status_bit_mask) &&
238 			(fixed_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) {
239 			/* Found an active (signalled) event */
240 
241 			int_status |= acpi_ev_fixed_event_dispatch ((u32) i);
242 		}
243 	}
244 
245 	return (int_status);
246 }
247 
248 
249 /*******************************************************************************
250  *
251  * FUNCTION:    acpi_ev_fixed_event_dispatch
252  *
253  * PARAMETERS:  Event               - Event type
254  *
255  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
256  *
257  * DESCRIPTION: Clears the status bit for the requested event, calls the
258  *              handler that previously registered for the event.
259  *
260  ******************************************************************************/
261 
262 u32
acpi_ev_fixed_event_dispatch(u32 event)263 acpi_ev_fixed_event_dispatch (
264 	u32                             event)
265 {
266 
267 
268 	ACPI_FUNCTION_ENTRY ();
269 
270 
271 	/* Clear the status bit */
272 
273 	(void) acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id,
274 			 1, ACPI_MTX_DO_NOT_LOCK);
275 
276 	/*
277 	 * Make sure we've got a handler.  If not, report an error.
278 	 * The event is disabled to prevent further interrupts.
279 	 */
280 	if (NULL == acpi_gbl_fixed_event_handlers[event].handler) {
281 		(void) acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
282 				0, ACPI_MTX_DO_NOT_LOCK);
283 
284 		ACPI_REPORT_ERROR (
285 			("No installed handler for fixed event [%08X]\n",
286 			event));
287 
288 		return (ACPI_INTERRUPT_NOT_HANDLED);
289 	}
290 
291 	/* Invoke the Fixed Event handler */
292 
293 	return ((acpi_gbl_fixed_event_handlers[event].handler)(
294 			  acpi_gbl_fixed_event_handlers[event].context));
295 }
296 
297 
298