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