import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / drivers / acpi / ospm / ec / ecgpe.c
1 /*****************************************************************************
2  *
3  * Module Name: ecgpe.c
4  *   $Revision: 1.1.1.1 $
5  *
6  *****************************************************************************/
7
8 /*
9  *  Copyright (C) 2000, 2001 Andrew Grover
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26
27 #include <acpi.h>
28 #include "ec.h"
29
30 #define _COMPONENT              ACPI_EC
31         MODULE_NAME             ("ecgpe")
32
33
34 /****************************************************************************
35  *
36  * FUNCTION:    ec_query_handler
37  *
38  * PARAMETERS:
39  *
40  * RETURN:
41  *
42  * DESCRIPTION:
43  *
44  ****************************************************************************/
45
46 void
47 ec_query_handler (
48         void                    *context)
49 {
50         EC_CONTEXT              *ec = (EC_CONTEXT*)context;
51         static char             object_name[5] = {'_','Q','0','0','\0'};
52         const char              hex[] = {'0','1','2','3','4','5','6','7','8',
53                                         '9','A','B','C','D','E','F'};
54
55         FUNCTION_TRACE("ec_query_handler");
56
57         if (!ec) {
58                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
59                 return_VOID;
60         }
61
62         /*
63          * Evaluate _Qxx:
64          * --------------
65          * Evaluate corresponding _Qxx method.  Note that a zero query value
66          * indicates a spurious EC_SCI (no such thing as _Q00).
67          */
68         object_name[2] = hex[((ec->query_data >> 4) & 0x0F)];
69         object_name[3] = hex[(ec->query_data & 0x0F)];
70
71         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Evaluating [%s] for ec [%02x].\n", object_name, ec->device_handle));
72
73         bm_evaluate_object(ec->acpi_handle, object_name, NULL, NULL);
74
75         return_VOID;
76 }
77
78
79 /****************************************************************************
80  *
81  * FUNCTION:    ec_gpe_handler
82  *
83  * PARAMETERS:
84  *
85  * RETURN:
86  *
87  * DESCRIPTION:
88  *
89  ****************************************************************************/
90
91 void
92 ec_gpe_handler (
93         void                    *context)
94 {
95         acpi_status             status = AE_OK;
96         EC_CONTEXT              *ec = (EC_CONTEXT*)context;
97         EC_STATUS               ec_status = 0;
98
99         FUNCTION_TRACE("ec_gpe_handler");
100
101         if (!ec) {
102                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
103                 return_VOID;
104         }
105
106         /* TBD: synchronize w/ transaction (ectransx). */
107
108         /*
109          * EC_SCI?
110          * -------
111          * Check the EC_SCI bit to see if this is an EC_SCI event.  If not (e.g.
112          * OBF/IBE) just return, as we already poll to detect these events.
113          */
114         acpi_os_read_port(ec->status_port, &ec_status, 8);
115         if (!(ec_status & EC_FLAG_SCI)) {
116                 return_VOID;
117         }
118
119         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "EC_SCI event detected on ec [%02x] - running query.\n", ec->device_handle));
120
121         /*
122          * Run Query:
123          * ----------
124          * Query the EC to find out which _Qxx method we need to evaluate.
125          * Note that successful completion of the query causes the EC_SCI
126          * bit to be cleared (and thus clearing the interrupt source).
127          */
128         status = ec_io_write(ec, ec->command_port, EC_COMMAND_QUERY,
129                 EC_EVENT_OUTPUT_BUFFER_FULL);
130         if (ACPI_FAILURE(status)) {
131                 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to send 'query command' to EC.\n"));
132                 return_VOID;
133         }
134
135         status = ec_io_read(ec, ec->data_port, &(ec->query_data),
136                 EC_EVENT_NONE);
137         if (ACPI_FAILURE(status)) {
138                 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Error reading query data.\n"));
139                 return_VOID;
140         }
141
142         /* TBD: un-synchronize w/ transaction (ectransx). */
143
144         /*
145          * Spurious EC_SCI?
146          * ----------------
147          */
148         if (!ec->query_data) {
149                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Spurious EC SCI detected.\n"));
150                 return_VOID;
151         }
152
153         /*
154          * Defer _Qxx Execution:
155          * ---------------------
156          * Can't evaluate this method now 'cause we're at interrupt-level.
157          */
158         status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
159                 ec_query_handler, ec);
160         if (ACPI_FAILURE(status)) {
161                 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to defer _Qxx method evaluation.\n"));
162                 return_VOID;
163         }
164
165         return_VOID;
166 }
167
168
169 /****************************************************************************
170  *
171  * FUNCTION:    ec_install_gpe_handler
172  *
173  * PARAMETERS:
174  *
175  * RETURN:
176  *
177  * DESCRIPTION:
178  *
179  ****************************************************************************/
180
181 acpi_status
182 ec_install_gpe_handler (
183         EC_CONTEXT              *ec)
184 {
185         acpi_status             status = AE_OK;
186
187         FUNCTION_TRACE("ec_install_gpe_handler");
188
189         if (!ec) {
190                 return_ACPI_STATUS(AE_BAD_PARAMETER);
191         }
192
193         /*
194          * Evaluate _GPE:
195          * --------------
196          * Evaluate the "_GPE" object (required) to find out which GPE bit
197          * is used by this EC to signal events (SCIs).
198          */
199         status = bm_evaluate_simple_integer(ec->acpi_handle,
200                 "_GPE", &(ec->gpe_bit));
201         if (ACPI_FAILURE(status)) {
202                 return_ACPI_STATUS(status);
203         }
204
205         /*
206          * Install GPE Handler:
207          * --------------------
208          * Install a handler for this EC's GPE bit.
209          */
210         status = acpi_install_gpe_handler(ec->gpe_bit, ACPI_EVENT_EDGE_TRIGGERED,
211                 &ec_gpe_handler, ec);
212         if (ACPI_FAILURE(status)) {
213                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "acpi_install_gpe_handler() failed for GPE bit [%02x] with status [%08x].\n", ec->gpe_bit, status));
214                 ec->gpe_bit = EC_GPE_UNKNOWN;
215                 return_ACPI_STATUS(status);
216         }
217
218         return_ACPI_STATUS(status);
219 }
220
221
222 /****************************************************************************
223  *
224  * FUNCTION:    ec_remove_gpe_handler
225  *
226  * PARAMETERS:
227  *
228  * RETURN:
229  *
230  * DESCRIPTION:
231  *
232  ****************************************************************************/
233
234 acpi_status
235 ec_remove_gpe_handler (
236         EC_CONTEXT              *ec)
237 {
238         acpi_status             status = AE_OK;
239
240         FUNCTION_TRACE("ec_remove_gpe_handler");
241
242         if (!ec) {
243                 return_ACPI_STATUS(AE_BAD_PARAMETER);
244         }
245
246         status = acpi_remove_gpe_handler(ec->gpe_bit, &ec_gpe_handler);
247
248         return_ACPI_STATUS(status);
249 }