Contents of /alx-src/tags/kernel26-2.6.12-alx-r9/drivers/acpi/utils.c
Parent Directory
|
Revision Log
Revision 630 -
(show annotations)
(download)
Wed Mar 4 11:03:09 2009 UTC (15 years, 3 months ago) by niro
File MIME type: text/plain
File size: 10987 byte(s)
Wed Mar 4 11:03:09 2009 UTC (15 years, 3 months ago) by niro
File MIME type: text/plain
File size: 10987 byte(s)
Tag kernel26-2.6.12-alx-r9
1 | /* |
2 | * acpi_utils.c - ACPI Utility Functions ($Revision: 10 $) |
3 | * |
4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> |
5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> |
6 | * |
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
8 | * |
9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by |
11 | * the Free Software Foundation; either version 2 of the License, or (at |
12 | * your option) any later version. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, but |
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | * General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU General Public License along |
20 | * with this program; if not, write to the Free Software Foundation, Inc., |
21 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
22 | * |
23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
24 | */ |
25 | |
26 | #include <linux/kernel.h> |
27 | #include <linux/module.h> |
28 | #include <linux/init.h> |
29 | #include <linux/types.h> |
30 | #include <acpi/acpi_bus.h> |
31 | #include <acpi/acpi_drivers.h> |
32 | |
33 | |
34 | #define _COMPONENT ACPI_BUS_COMPONENT |
35 | ACPI_MODULE_NAME ("acpi_utils") |
36 | |
37 | |
38 | /* -------------------------------------------------------------------------- |
39 | Object Evaluation Helpers |
40 | -------------------------------------------------------------------------- */ |
41 | |
42 | #ifdef ACPI_DEBUG_OUTPUT |
43 | #define acpi_util_eval_error(h,p,s) {\ |
44 | char prefix[80] = {'\0'};\ |
45 | struct acpi_buffer buffer = {sizeof(prefix), prefix};\ |
46 | acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\ |
47 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",\ |
48 | (char *) prefix, p, acpi_format_exception(s))); } |
49 | #else |
50 | #define acpi_util_eval_error(h,p,s) |
51 | #endif |
52 | |
53 | |
54 | acpi_status |
55 | acpi_extract_package ( |
56 | union acpi_object *package, |
57 | struct acpi_buffer *format, |
58 | struct acpi_buffer *buffer) |
59 | { |
60 | u32 size_required = 0; |
61 | u32 tail_offset = 0; |
62 | char *format_string = NULL; |
63 | u32 format_count = 0; |
64 | u32 i = 0; |
65 | u8 *head = NULL; |
66 | u8 *tail = NULL; |
67 | |
68 | ACPI_FUNCTION_TRACE("acpi_extract_package"); |
69 | |
70 | if (!package || (package->type != ACPI_TYPE_PACKAGE) || (package->package.count < 1)) { |
71 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'package' argument\n")); |
72 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
73 | } |
74 | |
75 | if (!format || !format->pointer || (format->length < 1)) { |
76 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'format' argument\n")); |
77 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
78 | } |
79 | |
80 | if (!buffer) { |
81 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'buffer' argument\n")); |
82 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
83 | } |
84 | |
85 | format_count = (format->length/sizeof(char)) - 1; |
86 | if (format_count > package->package.count) { |
87 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Format specifies more objects [%d] than exist in package [%d].", format_count, package->package.count)); |
88 | return_ACPI_STATUS(AE_BAD_DATA); |
89 | } |
90 | |
91 | format_string = (char*)format->pointer; |
92 | |
93 | /* |
94 | * Calculate size_required. |
95 | */ |
96 | for (i=0; i<format_count; i++) { |
97 | |
98 | union acpi_object *element = &(package->package.elements[i]); |
99 | |
100 | if (!element) { |
101 | return_ACPI_STATUS(AE_BAD_DATA); |
102 | } |
103 | |
104 | switch (element->type) { |
105 | |
106 | case ACPI_TYPE_INTEGER: |
107 | switch (format_string[i]) { |
108 | case 'N': |
109 | size_required += sizeof(acpi_integer); |
110 | tail_offset += sizeof(acpi_integer); |
111 | break; |
112 | case 'S': |
113 | size_required += sizeof(char*) + sizeof(acpi_integer) + sizeof(char); |
114 | tail_offset += sizeof(char*); |
115 | break; |
116 | default: |
117 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid package element [%d]: got number, expecing [%c].\n", i, format_string[i])); |
118 | return_ACPI_STATUS(AE_BAD_DATA); |
119 | break; |
120 | } |
121 | break; |
122 | |
123 | case ACPI_TYPE_STRING: |
124 | case ACPI_TYPE_BUFFER: |
125 | switch (format_string[i]) { |
126 | case 'S': |
127 | size_required += sizeof(char*) + (element->string.length * sizeof(char)) + sizeof(char); |
128 | tail_offset += sizeof(char*); |
129 | break; |
130 | case 'B': |
131 | size_required += sizeof(u8*) + (element->buffer.length * sizeof(u8)); |
132 | tail_offset += sizeof(u8*); |
133 | break; |
134 | default: |
135 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid package element [%d] got string/buffer, expecing [%c].\n", i, format_string[i])); |
136 | return_ACPI_STATUS(AE_BAD_DATA); |
137 | break; |
138 | } |
139 | break; |
140 | |
141 | case ACPI_TYPE_PACKAGE: |
142 | default: |
143 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unsupported element at index=%d\n", i)); |
144 | /* TBD: handle nested packages... */ |
145 | return_ACPI_STATUS(AE_SUPPORT); |
146 | break; |
147 | } |
148 | } |
149 | |
150 | /* |
151 | * Validate output buffer. |
152 | */ |
153 | if (buffer->length < size_required) { |
154 | buffer->length = size_required; |
155 | return_ACPI_STATUS(AE_BUFFER_OVERFLOW); |
156 | } |
157 | else if (buffer->length != size_required || !buffer->pointer) { |
158 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
159 | } |
160 | |
161 | head = buffer->pointer; |
162 | tail = buffer->pointer + tail_offset; |
163 | |
164 | /* |
165 | * Extract package data. |
166 | */ |
167 | for (i=0; i<format_count; i++) { |
168 | |
169 | u8 **pointer = NULL; |
170 | union acpi_object *element = &(package->package.elements[i]); |
171 | |
172 | if (!element) { |
173 | return_ACPI_STATUS(AE_BAD_DATA); |
174 | } |
175 | |
176 | switch (element->type) { |
177 | |
178 | case ACPI_TYPE_INTEGER: |
179 | switch (format_string[i]) { |
180 | case 'N': |
181 | *((acpi_integer*)head) = element->integer.value; |
182 | head += sizeof(acpi_integer); |
183 | break; |
184 | case 'S': |
185 | pointer = (u8**)head; |
186 | *pointer = tail; |
187 | *((acpi_integer*)tail) = element->integer.value; |
188 | head += sizeof(acpi_integer*); |
189 | tail += sizeof(acpi_integer); |
190 | /* NULL terminate string */ |
191 | *tail = (char)0; |
192 | tail += sizeof(char); |
193 | break; |
194 | default: |
195 | /* Should never get here */ |
196 | break; |
197 | } |
198 | break; |
199 | |
200 | case ACPI_TYPE_STRING: |
201 | case ACPI_TYPE_BUFFER: |
202 | switch (format_string[i]) { |
203 | case 'S': |
204 | pointer = (u8**)head; |
205 | *pointer = tail; |
206 | memcpy(tail, element->string.pointer, element->string.length); |
207 | head += sizeof(char*); |
208 | tail += element->string.length * sizeof(char); |
209 | /* NULL terminate string */ |
210 | *tail = (char)0; |
211 | tail += sizeof(char); |
212 | break; |
213 | case 'B': |
214 | pointer = (u8**)head; |
215 | *pointer = tail; |
216 | memcpy(tail, element->buffer.pointer, element->buffer.length); |
217 | head += sizeof(u8*); |
218 | tail += element->buffer.length * sizeof(u8); |
219 | break; |
220 | default: |
221 | /* Should never get here */ |
222 | break; |
223 | } |
224 | break; |
225 | |
226 | case ACPI_TYPE_PACKAGE: |
227 | /* TBD: handle nested packages... */ |
228 | default: |
229 | /* Should never get here */ |
230 | break; |
231 | } |
232 | } |
233 | |
234 | return_ACPI_STATUS(AE_OK); |
235 | } |
236 | EXPORT_SYMBOL(acpi_extract_package); |
237 | |
238 | |
239 | acpi_status |
240 | acpi_evaluate_integer ( |
241 | acpi_handle handle, |
242 | acpi_string pathname, |
243 | struct acpi_object_list *arguments, |
244 | unsigned long *data) |
245 | { |
246 | acpi_status status = AE_OK; |
247 | union acpi_object *element; |
248 | struct acpi_buffer buffer = {0,NULL}; |
249 | |
250 | ACPI_FUNCTION_TRACE("acpi_evaluate_integer"); |
251 | |
252 | if (!data) |
253 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
254 | |
255 | element = kmalloc(sizeof(union acpi_object), GFP_KERNEL); |
256 | if(!element) |
257 | return_ACPI_STATUS(AE_NO_MEMORY); |
258 | |
259 | memset(element, 0, sizeof(union acpi_object)); |
260 | buffer.length = sizeof(union acpi_object); |
261 | buffer.pointer = element; |
262 | status = acpi_evaluate_object(handle, pathname, arguments, &buffer); |
263 | if (ACPI_FAILURE(status)) { |
264 | acpi_util_eval_error(handle, pathname, status); |
265 | return_ACPI_STATUS(status); |
266 | } |
267 | |
268 | if (element->type != ACPI_TYPE_INTEGER) { |
269 | acpi_util_eval_error(handle, pathname, AE_BAD_DATA); |
270 | return_ACPI_STATUS(AE_BAD_DATA); |
271 | } |
272 | |
273 | *data = element->integer.value; |
274 | kfree(element); |
275 | |
276 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data)); |
277 | |
278 | return_ACPI_STATUS(AE_OK); |
279 | } |
280 | EXPORT_SYMBOL(acpi_evaluate_integer); |
281 | |
282 | |
283 | #if 0 |
284 | acpi_status |
285 | acpi_evaluate_string ( |
286 | acpi_handle handle, |
287 | acpi_string pathname, |
288 | acpi_object_list *arguments, |
289 | acpi_string *data) |
290 | { |
291 | acpi_status status = AE_OK; |
292 | acpi_object *element = NULL; |
293 | acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
294 | |
295 | ACPI_FUNCTION_TRACE("acpi_evaluate_string"); |
296 | |
297 | if (!data) |
298 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
299 | |
300 | status = acpi_evaluate_object(handle, pathname, arguments, &buffer); |
301 | if (ACPI_FAILURE(status)) { |
302 | acpi_util_eval_error(handle, pathname, status); |
303 | return_ACPI_STATUS(status); |
304 | } |
305 | |
306 | element = (acpi_object *) buffer.pointer; |
307 | |
308 | if ((element->type != ACPI_TYPE_STRING) |
309 | || (element->type != ACPI_TYPE_BUFFER) |
310 | || !element->string.length) { |
311 | acpi_util_eval_error(handle, pathname, AE_BAD_DATA); |
312 | return_ACPI_STATUS(AE_BAD_DATA); |
313 | } |
314 | |
315 | *data = kmalloc(element->string.length + 1, GFP_KERNEL); |
316 | if (!data) { |
317 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Memory allocation error\n")); |
318 | return_VALUE(-ENOMEM); |
319 | } |
320 | memset(*data, 0, element->string.length + 1); |
321 | |
322 | memcpy(*data, element->string.pointer, element->string.length); |
323 | |
324 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data)); |
325 | |
326 | acpi_os_free(buffer.pointer); |
327 | |
328 | return_ACPI_STATUS(AE_OK); |
329 | } |
330 | #endif |
331 | |
332 | |
333 | acpi_status |
334 | acpi_evaluate_reference ( |
335 | acpi_handle handle, |
336 | acpi_string pathname, |
337 | struct acpi_object_list *arguments, |
338 | struct acpi_handle_list *list) |
339 | { |
340 | acpi_status status = AE_OK; |
341 | union acpi_object *package = NULL; |
342 | union acpi_object *element = NULL; |
343 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
344 | u32 i = 0; |
345 | |
346 | ACPI_FUNCTION_TRACE("acpi_evaluate_reference"); |
347 | |
348 | if (!list) { |
349 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
350 | } |
351 | |
352 | /* Evaluate object. */ |
353 | |
354 | status = acpi_evaluate_object(handle, pathname, arguments, &buffer); |
355 | if (ACPI_FAILURE(status)) |
356 | goto end; |
357 | |
358 | package = (union acpi_object *) buffer.pointer; |
359 | |
360 | if ((buffer.length == 0) || !package) { |
361 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
362 | "No return object (len %X ptr %p)\n", |
363 | (unsigned)buffer.length, package)); |
364 | status = AE_BAD_DATA; |
365 | acpi_util_eval_error(handle, pathname, status); |
366 | goto end; |
367 | } |
368 | if (package->type != ACPI_TYPE_PACKAGE) { |
369 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
370 | "Expecting a [Package], found type %X\n", |
371 | package->type)); |
372 | status = AE_BAD_DATA; |
373 | acpi_util_eval_error(handle, pathname, status); |
374 | goto end; |
375 | } |
376 | if (!package->package.count) { |
377 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
378 | "[Package] has zero elements (%p)\n", |
379 | package)); |
380 | status = AE_BAD_DATA; |
381 | acpi_util_eval_error(handle, pathname, status); |
382 | goto end; |
383 | } |
384 | |
385 | if (package->package.count > ACPI_MAX_HANDLES) { |
386 | return_ACPI_STATUS(AE_NO_MEMORY); |
387 | } |
388 | list->count = package->package.count; |
389 | |
390 | /* Extract package data. */ |
391 | |
392 | for (i = 0; i < list->count; i++) { |
393 | |
394 | element = &(package->package.elements[i]); |
395 | |
396 | if (element->type != ACPI_TYPE_ANY) { |
397 | status = AE_BAD_DATA; |
398 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
399 | "Expecting a [Reference] package element, found type %X\n", |
400 | element->type)); |
401 | acpi_util_eval_error(handle, pathname, status); |
402 | break; |
403 | } |
404 | |
405 | /* Get the acpi_handle. */ |
406 | |
407 | list->handles[i] = element->reference.handle; |
408 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n", |
409 | list->handles[i])); |
410 | } |
411 | |
412 | end: |
413 | if (ACPI_FAILURE(status)) { |
414 | list->count = 0; |
415 | //kfree(list->handles); |
416 | } |
417 | |
418 | acpi_os_free(buffer.pointer); |
419 | |
420 | return_ACPI_STATUS(status); |
421 | } |
422 | EXPORT_SYMBOL(acpi_evaluate_reference); |
423 |