diff options
Diffstat (limited to 'drivers/acpi/events/evevent.c')
-rw-r--r-- | drivers/acpi/events/evevent.c | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c new file mode 100644 index 000000000000..2a213604ae51 --- /dev/null +++ b/drivers/acpi/events/evevent.c | |||
@@ -0,0 +1,297 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: evevent - Fixed Event handling and dispatch | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2005, 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_events | ||
54 | * | ||
55 | * PARAMETERS: None | ||
56 | * | ||
57 | * RETURN: Status | ||
58 | * | ||
59 | * DESCRIPTION: Initialize global data structures for events. | ||
60 | * | ||
61 | ******************************************************************************/ | ||
62 | |||
63 | acpi_status | ||
64 | acpi_ev_initialize_events ( | ||
65 | void) | ||
66 | { | ||
67 | acpi_status status; | ||
68 | |||
69 | |||
70 | ACPI_FUNCTION_TRACE ("ev_initialize_events"); | ||
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_install_xrupt_handlers | ||
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 | ||
118 | acpi_ev_install_xrupt_handlers ( | ||
119 | void) | ||
120 | { | ||
121 | acpi_status status; | ||
122 | |||
123 | |||
124 | ACPI_FUNCTION_TRACE ("ev_install_xrupt_handlers"); | ||
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 | ||
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 | ||
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 | ||
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 | |||