diff options
Diffstat (limited to 'drivers/acpi/events/evxfevnt.c')
-rw-r--r-- | drivers/acpi/events/evxfevnt.c | 778 |
1 files changed, 778 insertions, 0 deletions
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c new file mode 100644 index 000000000000..fa8d5f25be62 --- /dev/null +++ b/drivers/acpi/events/evxfevnt.c | |||
@@ -0,0 +1,778 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable | ||
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 <linux/module.h> | ||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/acevents.h> | ||
48 | #include <acpi/acnamesp.h> | ||
49 | |||
50 | #define _COMPONENT ACPI_EVENTS | ||
51 | ACPI_MODULE_NAME ("evxfevnt") | ||
52 | |||
53 | |||
54 | /******************************************************************************* | ||
55 | * | ||
56 | * FUNCTION: acpi_enable | ||
57 | * | ||
58 | * PARAMETERS: None | ||
59 | * | ||
60 | * RETURN: Status | ||
61 | * | ||
62 | * DESCRIPTION: Transfers the system into ACPI mode. | ||
63 | * | ||
64 | ******************************************************************************/ | ||
65 | |||
66 | acpi_status | ||
67 | acpi_enable (void) | ||
68 | { | ||
69 | acpi_status status = AE_OK; | ||
70 | |||
71 | |||
72 | ACPI_FUNCTION_TRACE ("acpi_enable"); | ||
73 | |||
74 | |||
75 | /* Make sure we have the FADT*/ | ||
76 | |||
77 | if (!acpi_gbl_FADT) { | ||
78 | ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n")); | ||
79 | return_ACPI_STATUS (AE_NO_ACPI_TABLES); | ||
80 | } | ||
81 | |||
82 | if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) { | ||
83 | ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "System is already in ACPI mode\n")); | ||
84 | } | ||
85 | else { | ||
86 | /* Transition to ACPI mode */ | ||
87 | |||
88 | status = acpi_hw_set_mode (ACPI_SYS_MODE_ACPI); | ||
89 | if (ACPI_FAILURE (status)) { | ||
90 | ACPI_REPORT_ERROR (("Could not transition to ACPI mode.\n")); | ||
91 | return_ACPI_STATUS (status); | ||
92 | } | ||
93 | |||
94 | ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Transition to ACPI mode successful\n")); | ||
95 | } | ||
96 | |||
97 | return_ACPI_STATUS (status); | ||
98 | } | ||
99 | |||
100 | |||
101 | /******************************************************************************* | ||
102 | * | ||
103 | * FUNCTION: acpi_disable | ||
104 | * | ||
105 | * PARAMETERS: None | ||
106 | * | ||
107 | * RETURN: Status | ||
108 | * | ||
109 | * DESCRIPTION: Transfers the system into LEGACY mode. | ||
110 | * | ||
111 | ******************************************************************************/ | ||
112 | |||
113 | acpi_status | ||
114 | acpi_disable (void) | ||
115 | { | ||
116 | acpi_status status = AE_OK; | ||
117 | |||
118 | |||
119 | ACPI_FUNCTION_TRACE ("acpi_disable"); | ||
120 | |||
121 | |||
122 | if (!acpi_gbl_FADT) { | ||
123 | ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n")); | ||
124 | return_ACPI_STATUS (AE_NO_ACPI_TABLES); | ||
125 | } | ||
126 | |||
127 | if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) { | ||
128 | ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "System is already in legacy (non-ACPI) mode\n")); | ||
129 | } | ||
130 | else { | ||
131 | /* Transition to LEGACY mode */ | ||
132 | |||
133 | status = acpi_hw_set_mode (ACPI_SYS_MODE_LEGACY); | ||
134 | |||
135 | if (ACPI_FAILURE (status)) { | ||
136 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not exit ACPI mode to legacy mode")); | ||
137 | return_ACPI_STATUS (status); | ||
138 | } | ||
139 | |||
140 | ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI mode disabled\n")); | ||
141 | } | ||
142 | |||
143 | return_ACPI_STATUS (status); | ||
144 | } | ||
145 | |||
146 | |||
147 | /******************************************************************************* | ||
148 | * | ||
149 | * FUNCTION: acpi_enable_event | ||
150 | * | ||
151 | * PARAMETERS: Event - The fixed eventto be enabled | ||
152 | * Flags - Reserved | ||
153 | * | ||
154 | * RETURN: Status | ||
155 | * | ||
156 | * DESCRIPTION: Enable an ACPI event (fixed) | ||
157 | * | ||
158 | ******************************************************************************/ | ||
159 | |||
160 | acpi_status | ||
161 | acpi_enable_event ( | ||
162 | u32 event, | ||
163 | u32 flags) | ||
164 | { | ||
165 | acpi_status status = AE_OK; | ||
166 | u32 value; | ||
167 | |||
168 | |||
169 | ACPI_FUNCTION_TRACE ("acpi_enable_event"); | ||
170 | |||
171 | |||
172 | /* Decode the Fixed Event */ | ||
173 | |||
174 | if (event > ACPI_EVENT_MAX) { | ||
175 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * Enable the requested fixed event (by writing a one to the | ||
180 | * enable register bit) | ||
181 | */ | ||
182 | status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id, | ||
183 | 1, ACPI_MTX_LOCK); | ||
184 | if (ACPI_FAILURE (status)) { | ||
185 | return_ACPI_STATUS (status); | ||
186 | } | ||
187 | |||
188 | /* Make sure that the hardware responded */ | ||
189 | |||
190 | status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id, | ||
191 | &value, ACPI_MTX_LOCK); | ||
192 | if (ACPI_FAILURE (status)) { | ||
193 | return_ACPI_STATUS (status); | ||
194 | } | ||
195 | |||
196 | if (value != 1) { | ||
197 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
198 | "Could not enable %s event\n", acpi_ut_get_event_name (event))); | ||
199 | return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); | ||
200 | } | ||
201 | |||
202 | return_ACPI_STATUS (status); | ||
203 | } | ||
204 | EXPORT_SYMBOL(acpi_enable_event); | ||
205 | |||
206 | |||
207 | /******************************************************************************* | ||
208 | * | ||
209 | * FUNCTION: acpi_set_gpe_type | ||
210 | * | ||
211 | * PARAMETERS: gpe_device - Parent GPE Device | ||
212 | * gpe_number - GPE level within the GPE block | ||
213 | * Type - New GPE type | ||
214 | * | ||
215 | * RETURN: Status | ||
216 | * | ||
217 | * DESCRIPTION: Enable an ACPI event (general purpose) | ||
218 | * | ||
219 | ******************************************************************************/ | ||
220 | |||
221 | acpi_status | ||
222 | acpi_set_gpe_type ( | ||
223 | acpi_handle gpe_device, | ||
224 | u32 gpe_number, | ||
225 | u8 type) | ||
226 | { | ||
227 | acpi_status status = AE_OK; | ||
228 | struct acpi_gpe_event_info *gpe_event_info; | ||
229 | |||
230 | |||
231 | ACPI_FUNCTION_TRACE ("acpi_set_gpe_type"); | ||
232 | |||
233 | |||
234 | /* Ensure that we have a valid GPE number */ | ||
235 | |||
236 | gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number); | ||
237 | if (!gpe_event_info) { | ||
238 | status = AE_BAD_PARAMETER; | ||
239 | goto unlock_and_exit; | ||
240 | } | ||
241 | |||
242 | if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) { | ||
243 | return_ACPI_STATUS (AE_OK); | ||
244 | } | ||
245 | |||
246 | /* Set the new type (will disable GPE if currently enabled) */ | ||
247 | |||
248 | status = acpi_ev_set_gpe_type (gpe_event_info, type); | ||
249 | |||
250 | unlock_and_exit: | ||
251 | return_ACPI_STATUS (status); | ||
252 | } | ||
253 | EXPORT_SYMBOL(acpi_set_gpe_type); | ||
254 | |||
255 | |||
256 | /******************************************************************************* | ||
257 | * | ||
258 | * FUNCTION: acpi_enable_gpe | ||
259 | * | ||
260 | * PARAMETERS: gpe_device - Parent GPE Device | ||
261 | * gpe_number - GPE level within the GPE block | ||
262 | * Flags - Just enable, or also wake enable? | ||
263 | * Called from ISR or not | ||
264 | * | ||
265 | * RETURN: Status | ||
266 | * | ||
267 | * DESCRIPTION: Enable an ACPI event (general purpose) | ||
268 | * | ||
269 | ******************************************************************************/ | ||
270 | |||
271 | acpi_status | ||
272 | acpi_enable_gpe ( | ||
273 | acpi_handle gpe_device, | ||
274 | u32 gpe_number, | ||
275 | u32 flags) | ||
276 | { | ||
277 | acpi_status status = AE_OK; | ||
278 | struct acpi_gpe_event_info *gpe_event_info; | ||
279 | |||
280 | |||
281 | ACPI_FUNCTION_TRACE ("acpi_enable_gpe"); | ||
282 | |||
283 | |||
284 | /* Use semaphore lock if not executing at interrupt level */ | ||
285 | |||
286 | if (flags & ACPI_NOT_ISR) { | ||
287 | status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); | ||
288 | if (ACPI_FAILURE (status)) { | ||
289 | return_ACPI_STATUS (status); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | /* Ensure that we have a valid GPE number */ | ||
294 | |||
295 | gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number); | ||
296 | if (!gpe_event_info) { | ||
297 | status = AE_BAD_PARAMETER; | ||
298 | goto unlock_and_exit; | ||
299 | } | ||
300 | |||
301 | /* Perform the enable */ | ||
302 | |||
303 | status = acpi_ev_enable_gpe (gpe_event_info, TRUE); | ||
304 | |||
305 | unlock_and_exit: | ||
306 | if (flags & ACPI_NOT_ISR) { | ||
307 | (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); | ||
308 | } | ||
309 | return_ACPI_STATUS (status); | ||
310 | } | ||
311 | EXPORT_SYMBOL(acpi_enable_gpe); | ||
312 | |||
313 | |||
314 | /******************************************************************************* | ||
315 | * | ||
316 | * FUNCTION: acpi_disable_gpe | ||
317 | * | ||
318 | * PARAMETERS: gpe_device - Parent GPE Device | ||
319 | * gpe_number - GPE level within the GPE block | ||
320 | * Flags - Just disable, or also wake disable? | ||
321 | * Called from ISR or not | ||
322 | * | ||
323 | * RETURN: Status | ||
324 | * | ||
325 | * DESCRIPTION: Disable an ACPI event (general purpose) | ||
326 | * | ||
327 | ******************************************************************************/ | ||
328 | |||
329 | acpi_status | ||
330 | acpi_disable_gpe ( | ||
331 | acpi_handle gpe_device, | ||
332 | u32 gpe_number, | ||
333 | u32 flags) | ||
334 | { | ||
335 | acpi_status status = AE_OK; | ||
336 | struct acpi_gpe_event_info *gpe_event_info; | ||
337 | |||
338 | |||
339 | ACPI_FUNCTION_TRACE ("acpi_disable_gpe"); | ||
340 | |||
341 | |||
342 | /* Use semaphore lock if not executing at interrupt level */ | ||
343 | |||
344 | if (flags & ACPI_NOT_ISR) { | ||
345 | status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); | ||
346 | if (ACPI_FAILURE (status)) { | ||
347 | return_ACPI_STATUS (status); | ||
348 | } | ||
349 | } | ||
350 | |||
351 | /* Ensure that we have a valid GPE number */ | ||
352 | |||
353 | gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number); | ||
354 | if (!gpe_event_info) { | ||
355 | status = AE_BAD_PARAMETER; | ||
356 | goto unlock_and_exit; | ||
357 | } | ||
358 | |||
359 | status = acpi_ev_disable_gpe (gpe_event_info); | ||
360 | |||
361 | unlock_and_exit: | ||
362 | if (flags & ACPI_NOT_ISR) { | ||
363 | (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); | ||
364 | } | ||
365 | return_ACPI_STATUS (status); | ||
366 | } | ||
367 | |||
368 | |||
369 | /******************************************************************************* | ||
370 | * | ||
371 | * FUNCTION: acpi_disable_event | ||
372 | * | ||
373 | * PARAMETERS: Event - The fixed eventto be enabled | ||
374 | * Flags - Reserved | ||
375 | * | ||
376 | * RETURN: Status | ||
377 | * | ||
378 | * DESCRIPTION: Disable an ACPI event (fixed) | ||
379 | * | ||
380 | ******************************************************************************/ | ||
381 | |||
382 | acpi_status | ||
383 | acpi_disable_event ( | ||
384 | u32 event, | ||
385 | u32 flags) | ||
386 | { | ||
387 | acpi_status status = AE_OK; | ||
388 | u32 value; | ||
389 | |||
390 | |||
391 | ACPI_FUNCTION_TRACE ("acpi_disable_event"); | ||
392 | |||
393 | |||
394 | /* Decode the Fixed Event */ | ||
395 | |||
396 | if (event > ACPI_EVENT_MAX) { | ||
397 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
398 | } | ||
399 | |||
400 | /* | ||
401 | * Disable the requested fixed event (by writing a zero to the | ||
402 | * enable register bit) | ||
403 | */ | ||
404 | status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id, | ||
405 | 0, ACPI_MTX_LOCK); | ||
406 | if (ACPI_FAILURE (status)) { | ||
407 | return_ACPI_STATUS (status); | ||
408 | } | ||
409 | |||
410 | status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id, | ||
411 | &value, ACPI_MTX_LOCK); | ||
412 | if (ACPI_FAILURE (status)) { | ||
413 | return_ACPI_STATUS (status); | ||
414 | } | ||
415 | |||
416 | if (value != 0) { | ||
417 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
418 | "Could not disable %s events\n", acpi_ut_get_event_name (event))); | ||
419 | return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); | ||
420 | } | ||
421 | |||
422 | return_ACPI_STATUS (status); | ||
423 | } | ||
424 | EXPORT_SYMBOL(acpi_disable_event); | ||
425 | |||
426 | |||
427 | /******************************************************************************* | ||
428 | * | ||
429 | * FUNCTION: acpi_clear_event | ||
430 | * | ||
431 | * PARAMETERS: Event - The fixed event to be cleared | ||
432 | * | ||
433 | * RETURN: Status | ||
434 | * | ||
435 | * DESCRIPTION: Clear an ACPI event (fixed) | ||
436 | * | ||
437 | ******************************************************************************/ | ||
438 | |||
439 | acpi_status | ||
440 | acpi_clear_event ( | ||
441 | u32 event) | ||
442 | { | ||
443 | acpi_status status = AE_OK; | ||
444 | |||
445 | |||
446 | ACPI_FUNCTION_TRACE ("acpi_clear_event"); | ||
447 | |||
448 | |||
449 | /* Decode the Fixed Event */ | ||
450 | |||
451 | if (event > ACPI_EVENT_MAX) { | ||
452 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
453 | } | ||
454 | |||
455 | /* | ||
456 | * Clear the requested fixed event (By writing a one to the | ||
457 | * status register bit) | ||
458 | */ | ||
459 | status = acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id, | ||
460 | 1, ACPI_MTX_LOCK); | ||
461 | |||
462 | return_ACPI_STATUS (status); | ||
463 | } | ||
464 | EXPORT_SYMBOL(acpi_clear_event); | ||
465 | |||
466 | |||
467 | /******************************************************************************* | ||
468 | * | ||
469 | * FUNCTION: acpi_clear_gpe | ||
470 | * | ||
471 | * PARAMETERS: gpe_device - Parent GPE Device | ||
472 | * gpe_number - GPE level within the GPE block | ||
473 | * Flags - Called from an ISR or not | ||
474 | * | ||
475 | * RETURN: Status | ||
476 | * | ||
477 | * DESCRIPTION: Clear an ACPI event (general purpose) | ||
478 | * | ||
479 | ******************************************************************************/ | ||
480 | |||
481 | acpi_status | ||
482 | acpi_clear_gpe ( | ||
483 | acpi_handle gpe_device, | ||
484 | u32 gpe_number, | ||
485 | u32 flags) | ||
486 | { | ||
487 | acpi_status status = AE_OK; | ||
488 | struct acpi_gpe_event_info *gpe_event_info; | ||
489 | |||
490 | |||
491 | ACPI_FUNCTION_TRACE ("acpi_clear_gpe"); | ||
492 | |||
493 | |||
494 | /* Use semaphore lock if not executing at interrupt level */ | ||
495 | |||
496 | if (flags & ACPI_NOT_ISR) { | ||
497 | status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); | ||
498 | if (ACPI_FAILURE (status)) { | ||
499 | return_ACPI_STATUS (status); | ||
500 | } | ||
501 | } | ||
502 | |||
503 | /* Ensure that we have a valid GPE number */ | ||
504 | |||
505 | gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number); | ||
506 | if (!gpe_event_info) { | ||
507 | status = AE_BAD_PARAMETER; | ||
508 | goto unlock_and_exit; | ||
509 | } | ||
510 | |||
511 | status = acpi_hw_clear_gpe (gpe_event_info); | ||
512 | |||
513 | unlock_and_exit: | ||
514 | if (flags & ACPI_NOT_ISR) { | ||
515 | (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); | ||
516 | } | ||
517 | return_ACPI_STATUS (status); | ||
518 | } | ||
519 | |||
520 | |||
521 | #ifdef ACPI_FUTURE_USAGE | ||
522 | |||
523 | /******************************************************************************* | ||
524 | * | ||
525 | * FUNCTION: acpi_get_event_status | ||
526 | * | ||
527 | * PARAMETERS: Event - The fixed event | ||
528 | * Event Status - Where the current status of the event will | ||
529 | * be returned | ||
530 | * | ||
531 | * RETURN: Status | ||
532 | * | ||
533 | * DESCRIPTION: Obtains and returns the current status of the event | ||
534 | * | ||
535 | ******************************************************************************/ | ||
536 | |||
537 | acpi_status | ||
538 | acpi_get_event_status ( | ||
539 | u32 event, | ||
540 | acpi_event_status *event_status) | ||
541 | { | ||
542 | acpi_status status = AE_OK; | ||
543 | |||
544 | |||
545 | ACPI_FUNCTION_TRACE ("acpi_get_event_status"); | ||
546 | |||
547 | |||
548 | if (!event_status) { | ||
549 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
550 | } | ||
551 | |||
552 | /* Decode the Fixed Event */ | ||
553 | |||
554 | if (event > ACPI_EVENT_MAX) { | ||
555 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
556 | } | ||
557 | |||
558 | /* Get the status of the requested fixed event */ | ||
559 | |||
560 | status = acpi_get_register (acpi_gbl_fixed_event_info[event].status_register_id, | ||
561 | event_status, ACPI_MTX_LOCK); | ||
562 | |||
563 | return_ACPI_STATUS (status); | ||
564 | } | ||
565 | |||
566 | |||
567 | /******************************************************************************* | ||
568 | * | ||
569 | * FUNCTION: acpi_get_gpe_status | ||
570 | * | ||
571 | * PARAMETERS: gpe_device - Parent GPE Device | ||
572 | * gpe_number - GPE level within the GPE block | ||
573 | * Flags - Called from an ISR or not | ||
574 | * Event Status - Where the current status of the event will | ||
575 | * be returned | ||
576 | * | ||
577 | * RETURN: Status | ||
578 | * | ||
579 | * DESCRIPTION: Get status of an event (general purpose) | ||
580 | * | ||
581 | ******************************************************************************/ | ||
582 | |||
583 | acpi_status | ||
584 | acpi_get_gpe_status ( | ||
585 | acpi_handle gpe_device, | ||
586 | u32 gpe_number, | ||
587 | u32 flags, | ||
588 | acpi_event_status *event_status) | ||
589 | { | ||
590 | acpi_status status = AE_OK; | ||
591 | struct acpi_gpe_event_info *gpe_event_info; | ||
592 | |||
593 | |||
594 | ACPI_FUNCTION_TRACE ("acpi_get_gpe_status"); | ||
595 | |||
596 | |||
597 | /* Use semaphore lock if not executing at interrupt level */ | ||
598 | |||
599 | if (flags & ACPI_NOT_ISR) { | ||
600 | status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); | ||
601 | if (ACPI_FAILURE (status)) { | ||
602 | return_ACPI_STATUS (status); | ||
603 | } | ||
604 | } | ||
605 | |||
606 | /* Ensure that we have a valid GPE number */ | ||
607 | |||
608 | gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number); | ||
609 | if (!gpe_event_info) { | ||
610 | status = AE_BAD_PARAMETER; | ||
611 | goto unlock_and_exit; | ||
612 | } | ||
613 | |||
614 | /* Obtain status on the requested GPE number */ | ||
615 | |||
616 | status = acpi_hw_get_gpe_status (gpe_event_info, event_status); | ||
617 | |||
618 | unlock_and_exit: | ||
619 | if (flags & ACPI_NOT_ISR) { | ||
620 | (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); | ||
621 | } | ||
622 | return_ACPI_STATUS (status); | ||
623 | } | ||
624 | #endif /* ACPI_FUTURE_USAGE */ | ||
625 | |||
626 | |||
627 | /******************************************************************************* | ||
628 | * | ||
629 | * FUNCTION: acpi_install_gpe_block | ||
630 | * | ||
631 | * PARAMETERS: gpe_device - Handle to the parent GPE Block Device | ||
632 | * gpe_block_address - Address and space_iD | ||
633 | * register_count - Number of GPE register pairs in the block | ||
634 | * interrupt_level - H/W interrupt for the block | ||
635 | * | ||
636 | * RETURN: Status | ||
637 | * | ||
638 | * DESCRIPTION: Create and Install a block of GPE registers | ||
639 | * | ||
640 | ******************************************************************************/ | ||
641 | |||
642 | acpi_status | ||
643 | acpi_install_gpe_block ( | ||
644 | acpi_handle gpe_device, | ||
645 | struct acpi_generic_address *gpe_block_address, | ||
646 | u32 register_count, | ||
647 | u32 interrupt_level) | ||
648 | { | ||
649 | acpi_status status; | ||
650 | union acpi_operand_object *obj_desc; | ||
651 | struct acpi_namespace_node *node; | ||
652 | struct acpi_gpe_block_info *gpe_block; | ||
653 | |||
654 | |||
655 | ACPI_FUNCTION_TRACE ("acpi_install_gpe_block"); | ||
656 | |||
657 | |||
658 | if ((!gpe_device) || | ||
659 | (!gpe_block_address) || | ||
660 | (!register_count)) { | ||
661 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
662 | } | ||
663 | |||
664 | status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); | ||
665 | if (ACPI_FAILURE (status)) { | ||
666 | return (status); | ||
667 | } | ||
668 | |||
669 | node = acpi_ns_map_handle_to_node (gpe_device); | ||
670 | if (!node) { | ||
671 | status = AE_BAD_PARAMETER; | ||
672 | goto unlock_and_exit; | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * For user-installed GPE Block Devices, the gpe_block_base_number | ||
677 | * is always zero | ||
678 | */ | ||
679 | status = acpi_ev_create_gpe_block (node, gpe_block_address, register_count, | ||
680 | 0, interrupt_level, &gpe_block); | ||
681 | if (ACPI_FAILURE (status)) { | ||
682 | goto unlock_and_exit; | ||
683 | } | ||
684 | |||
685 | /* Get the device_object attached to the node */ | ||
686 | |||
687 | obj_desc = acpi_ns_get_attached_object (node); | ||
688 | if (!obj_desc) { | ||
689 | /* No object, create a new one */ | ||
690 | |||
691 | obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_DEVICE); | ||
692 | if (!obj_desc) { | ||
693 | status = AE_NO_MEMORY; | ||
694 | goto unlock_and_exit; | ||
695 | } | ||
696 | |||
697 | status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_DEVICE); | ||
698 | |||
699 | /* Remove local reference to the object */ | ||
700 | |||
701 | acpi_ut_remove_reference (obj_desc); | ||
702 | |||
703 | if (ACPI_FAILURE (status)) { | ||
704 | goto unlock_and_exit; | ||
705 | } | ||
706 | } | ||
707 | |||
708 | /* Install the GPE block in the device_object */ | ||
709 | |||
710 | obj_desc->device.gpe_block = gpe_block; | ||
711 | |||
712 | |||
713 | unlock_and_exit: | ||
714 | (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); | ||
715 | return_ACPI_STATUS (status); | ||
716 | } | ||
717 | EXPORT_SYMBOL(acpi_install_gpe_block); | ||
718 | |||
719 | |||
720 | /******************************************************************************* | ||
721 | * | ||
722 | * FUNCTION: acpi_remove_gpe_block | ||
723 | * | ||
724 | * PARAMETERS: gpe_device - Handle to the parent GPE Block Device | ||
725 | * | ||
726 | * RETURN: Status | ||
727 | * | ||
728 | * DESCRIPTION: Remove a previously installed block of GPE registers | ||
729 | * | ||
730 | ******************************************************************************/ | ||
731 | |||
732 | acpi_status | ||
733 | acpi_remove_gpe_block ( | ||
734 | acpi_handle gpe_device) | ||
735 | { | ||
736 | union acpi_operand_object *obj_desc; | ||
737 | acpi_status status; | ||
738 | struct acpi_namespace_node *node; | ||
739 | |||
740 | |||
741 | ACPI_FUNCTION_TRACE ("acpi_remove_gpe_block"); | ||
742 | |||
743 | |||
744 | if (!gpe_device) { | ||
745 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
746 | } | ||
747 | |||
748 | status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); | ||
749 | if (ACPI_FAILURE (status)) { | ||
750 | return (status); | ||
751 | } | ||
752 | |||
753 | node = acpi_ns_map_handle_to_node (gpe_device); | ||
754 | if (!node) { | ||
755 | status = AE_BAD_PARAMETER; | ||
756 | goto unlock_and_exit; | ||
757 | } | ||
758 | |||
759 | /* Get the device_object attached to the node */ | ||
760 | |||
761 | obj_desc = acpi_ns_get_attached_object (node); | ||
762 | if (!obj_desc || | ||
763 | !obj_desc->device.gpe_block) { | ||
764 | return_ACPI_STATUS (AE_NULL_OBJECT); | ||
765 | } | ||
766 | |||
767 | /* Delete the GPE block (but not the device_object) */ | ||
768 | |||
769 | status = acpi_ev_delete_gpe_block (obj_desc->device.gpe_block); | ||
770 | if (ACPI_SUCCESS (status)) { | ||
771 | obj_desc->device.gpe_block = NULL; | ||
772 | } | ||
773 | |||
774 | unlock_and_exit: | ||
775 | (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); | ||
776 | return_ACPI_STATUS (status); | ||
777 | } | ||
778 | EXPORT_SYMBOL(acpi_remove_gpe_block); | ||