2 * acpi_utils.c - ACPI Utility Functions ($Revision: 10 $)
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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.
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.
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/slab.h>
29 #include <linux/init.h>
30 #include <linux/types.h>
31 #include <linux/hardirq.h>
32 #include <linux/acpi.h>
33 #include <acpi/acpi_bus.h>
34 #include <acpi/acpi_drivers.h>
38 #define _COMPONENT ACPI_BUS_COMPONENT
39 ACPI_MODULE_NAME("utils");
41 /* --------------------------------------------------------------------------
42 Object Evaluation Helpers
43 -------------------------------------------------------------------------- */
45 acpi_util_eval_error(acpi_handle h
, acpi_string p
, acpi_status s
)
47 #ifdef ACPI_DEBUG_OUTPUT
48 char prefix
[80] = {'\0'};
49 struct acpi_buffer buffer
= {sizeof(prefix
), prefix
};
50 acpi_get_name(h
, ACPI_FULL_PATHNAME
, &buffer
);
51 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Evaluate [%s.%s]: %s\n",
52 (char *) prefix
, p
, acpi_format_exception(s
)));
59 acpi_extract_package(union acpi_object
*package
,
60 struct acpi_buffer
*format
, struct acpi_buffer
*buffer
)
62 u32 size_required
= 0;
64 char *format_string
= NULL
;
71 if (!package
|| (package
->type
!= ACPI_TYPE_PACKAGE
)
72 || (package
->package
.count
< 1)) {
73 printk(KERN_WARNING PREFIX
"Invalid package argument\n");
74 return AE_BAD_PARAMETER
;
77 if (!format
|| !format
->pointer
|| (format
->length
< 1)) {
78 printk(KERN_WARNING PREFIX
"Invalid format argument\n");
79 return AE_BAD_PARAMETER
;
83 printk(KERN_WARNING PREFIX
"Invalid buffer argument\n");
84 return AE_BAD_PARAMETER
;
87 format_count
= (format
->length
/ sizeof(char)) - 1;
88 if (format_count
> package
->package
.count
) {
89 printk(KERN_WARNING PREFIX
"Format specifies more objects [%d]"
90 " than exist in package [%d].\n",
91 format_count
, package
->package
.count
);
95 format_string
= format
->pointer
;
98 * Calculate size_required.
100 for (i
= 0; i
< format_count
; i
++) {
102 union acpi_object
*element
= &(package
->package
.elements
[i
]);
108 switch (element
->type
) {
110 case ACPI_TYPE_INTEGER
:
111 switch (format_string
[i
]) {
113 size_required
+= sizeof(u64
);
114 tail_offset
+= sizeof(u64
);
118 sizeof(char *) + sizeof(u64
) +
120 tail_offset
+= sizeof(char *);
123 printk(KERN_WARNING PREFIX
"Invalid package element"
124 " [%d]: got number, expecing"
126 i
, format_string
[i
]);
132 case ACPI_TYPE_STRING
:
133 case ACPI_TYPE_BUFFER
:
134 switch (format_string
[i
]) {
138 (element
->string
.length
* sizeof(char)) +
140 tail_offset
+= sizeof(char *);
145 (element
->buffer
.length
* sizeof(u8
));
146 tail_offset
+= sizeof(u8
*);
149 printk(KERN_WARNING PREFIX
"Invalid package element"
150 " [%d] got string/buffer,"
152 i
, format_string
[i
]);
158 case ACPI_TYPE_PACKAGE
:
160 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
161 "Found unsupported element at index=%d\n",
163 /* TBD: handle nested packages... */
170 * Validate output buffer.
172 if (buffer
->length
< size_required
) {
173 buffer
->length
= size_required
;
174 return AE_BUFFER_OVERFLOW
;
175 } else if (buffer
->length
!= size_required
|| !buffer
->pointer
) {
176 return AE_BAD_PARAMETER
;
179 head
= buffer
->pointer
;
180 tail
= buffer
->pointer
+ tail_offset
;
183 * Extract package data.
185 for (i
= 0; i
< format_count
; i
++) {
188 union acpi_object
*element
= &(package
->package
.elements
[i
]);
194 switch (element
->type
) {
196 case ACPI_TYPE_INTEGER
:
197 switch (format_string
[i
]) {
200 element
->integer
.value
;
204 pointer
= (u8
**) head
;
207 element
->integer
.value
;
208 head
+= sizeof(u64
*);
210 /* NULL terminate string */
212 tail
+= sizeof(char);
215 /* Should never get here */
220 case ACPI_TYPE_STRING
:
221 case ACPI_TYPE_BUFFER
:
222 switch (format_string
[i
]) {
224 pointer
= (u8
**) head
;
226 memcpy(tail
, element
->string
.pointer
,
227 element
->string
.length
);
228 head
+= sizeof(char *);
229 tail
+= element
->string
.length
* sizeof(char);
230 /* NULL terminate string */
232 tail
+= sizeof(char);
235 pointer
= (u8
**) head
;
237 memcpy(tail
, element
->buffer
.pointer
,
238 element
->buffer
.length
);
239 head
+= sizeof(u8
*);
240 tail
+= element
->buffer
.length
* sizeof(u8
);
243 /* Should never get here */
248 case ACPI_TYPE_PACKAGE
:
249 /* TBD: handle nested packages... */
251 /* Should never get here */
259 EXPORT_SYMBOL(acpi_extract_package
);
262 acpi_evaluate_integer(acpi_handle handle
,
263 acpi_string pathname
,
264 struct acpi_object_list
*arguments
, unsigned long long *data
)
266 acpi_status status
= AE_OK
;
267 union acpi_object element
;
268 struct acpi_buffer buffer
= { 0, NULL
};
271 return AE_BAD_PARAMETER
;
273 buffer
.length
= sizeof(union acpi_object
);
274 buffer
.pointer
= &element
;
275 status
= acpi_evaluate_object(handle
, pathname
, arguments
, &buffer
);
276 if (ACPI_FAILURE(status
)) {
277 acpi_util_eval_error(handle
, pathname
, status
);
281 if (element
.type
!= ACPI_TYPE_INTEGER
) {
282 acpi_util_eval_error(handle
, pathname
, AE_BAD_DATA
);
286 *data
= element
.integer
.value
;
288 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Return value [%llu]\n", *data
));
293 EXPORT_SYMBOL(acpi_evaluate_integer
);
296 acpi_evaluate_reference(acpi_handle handle
,
297 acpi_string pathname
,
298 struct acpi_object_list
*arguments
,
299 struct acpi_handle_list
*list
)
301 acpi_status status
= AE_OK
;
302 union acpi_object
*package
= NULL
;
303 union acpi_object
*element
= NULL
;
304 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
309 return AE_BAD_PARAMETER
;
312 /* Evaluate object. */
314 status
= acpi_evaluate_object(handle
, pathname
, arguments
, &buffer
);
315 if (ACPI_FAILURE(status
))
318 package
= buffer
.pointer
;
320 if ((buffer
.length
== 0) || !package
) {
321 printk(KERN_ERR PREFIX
"No return object (len %X ptr %p)\n",
322 (unsigned)buffer
.length
, package
);
323 status
= AE_BAD_DATA
;
324 acpi_util_eval_error(handle
, pathname
, status
);
327 if (package
->type
!= ACPI_TYPE_PACKAGE
) {
328 printk(KERN_ERR PREFIX
"Expecting a [Package], found type %X\n",
330 status
= AE_BAD_DATA
;
331 acpi_util_eval_error(handle
, pathname
, status
);
334 if (!package
->package
.count
) {
335 printk(KERN_ERR PREFIX
"[Package] has zero elements (%p)\n",
337 status
= AE_BAD_DATA
;
338 acpi_util_eval_error(handle
, pathname
, status
);
342 if (package
->package
.count
> ACPI_MAX_HANDLES
) {
345 list
->count
= package
->package
.count
;
347 /* Extract package data. */
349 for (i
= 0; i
< list
->count
; i
++) {
351 element
= &(package
->package
.elements
[i
]);
353 if (element
->type
!= ACPI_TYPE_LOCAL_REFERENCE
) {
354 status
= AE_BAD_DATA
;
355 printk(KERN_ERR PREFIX
356 "Expecting a [Reference] package element, found type %X\n",
358 acpi_util_eval_error(handle
, pathname
, status
);
362 if (!element
->reference
.handle
) {
363 printk(KERN_WARNING PREFIX
"Invalid reference in"
364 " package %s\n", pathname
);
365 status
= AE_NULL_ENTRY
;
368 /* Get the acpi_handle. */
370 list
->handles
[i
] = element
->reference
.handle
;
371 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Found reference [%p]\n",
376 if (ACPI_FAILURE(status
)) {
378 //kfree(list->handles);
381 kfree(buffer
.pointer
);
386 EXPORT_SYMBOL(acpi_evaluate_reference
);
389 acpi_get_physical_device_location(acpi_handle handle
, struct acpi_pld_info
**pld
)
392 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
393 union acpi_object
*output
;
395 status
= acpi_evaluate_object(handle
, "_PLD", NULL
, &buffer
);
397 if (ACPI_FAILURE(status
))
400 output
= buffer
.pointer
;
402 if (!output
|| output
->type
!= ACPI_TYPE_PACKAGE
403 || !output
->package
.count
404 || output
->package
.elements
[0].type
!= ACPI_TYPE_BUFFER
405 || output
->package
.elements
[0].buffer
.length
< ACPI_PLD_REV1_BUFFER_SIZE
) {
410 status
= acpi_decode_pld_buffer(
411 output
->package
.elements
[0].buffer
.pointer
,
412 output
->package
.elements
[0].buffer
.length
,
416 kfree(buffer
.pointer
);
419 EXPORT_SYMBOL(acpi_get_physical_device_location
);
422 * acpi_evaluate_hotplug_ost: Evaluate _OST for hotplug operations
423 * @handle: ACPI device handle
424 * @source_event: source event code
425 * @status_code: status code
426 * @status_buf: optional detailed information (NULL if none)
428 * Evaluate _OST for hotplug operations. All ACPI hotplug handlers
429 * must call this function when evaluating _OST for hotplug operations.
430 * When the platform does not support _OST, this function has no effect.
433 acpi_evaluate_hotplug_ost(acpi_handle handle
, u32 source_event
,
434 u32 status_code
, struct acpi_buffer
*status_buf
)
436 #ifdef ACPI_HOTPLUG_OST
437 union acpi_object params
[3] = {
438 {.type
= ACPI_TYPE_INTEGER
,},
439 {.type
= ACPI_TYPE_INTEGER
,},
440 {.type
= ACPI_TYPE_BUFFER
,}
442 struct acpi_object_list arg_list
= {3, params
};
445 params
[0].integer
.value
= source_event
;
446 params
[1].integer
.value
= status_code
;
447 if (status_buf
!= NULL
) {
448 params
[2].buffer
.pointer
= status_buf
->pointer
;
449 params
[2].buffer
.length
= status_buf
->length
;
451 params
[2].buffer
.pointer
= NULL
;
452 params
[2].buffer
.length
= 0;
455 status
= acpi_evaluate_object(handle
, "_OST", &arg_list
, NULL
);
461 EXPORT_SYMBOL(acpi_evaluate_hotplug_ost
);
464 * acpi_handle_printk: Print message with ACPI prefix and object path
466 * This function is called through acpi_handle_<level> macros and prints
467 * a message with ACPI prefix and object path. This function acquires
468 * the global namespace mutex to obtain an object path. In interrupt
469 * context, it shows the object path as <n/a>.
472 acpi_handle_printk(const char *level
, acpi_handle handle
, const char *fmt
, ...)
474 struct va_format vaf
;
476 struct acpi_buffer buffer
= {
477 .length
= ACPI_ALLOCATE_BUFFER
,
486 if (in_interrupt() ||
487 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &buffer
) != AE_OK
)
490 path
= buffer
.pointer
;
492 printk("%sACPI: %s: %pV", level
, path
, &vaf
);
495 kfree(buffer
.pointer
);
497 EXPORT_SYMBOL(acpi_handle_printk
);
500 * acpi_has_method: Check whether @handle has a method named @name
501 * @handle: ACPI device handle
502 * @name: name of object or method
504 * Check whether @handle has a method named @name.
506 bool acpi_has_method(acpi_handle handle
, char *name
)
510 return ACPI_SUCCESS(acpi_get_handle(handle
, name
, &tmp
));
512 EXPORT_SYMBOL(acpi_has_method
);
514 acpi_status
acpi_execute_simple_method(acpi_handle handle
, char *method
,
517 union acpi_object obj
= { .type
= ACPI_TYPE_INTEGER
};
518 struct acpi_object_list arg_list
= { .count
= 1, .pointer
= &obj
, };
520 obj
.integer
.value
= arg
;
522 return acpi_evaluate_object(handle
, method
, &arg_list
, NULL
);
524 EXPORT_SYMBOL(acpi_execute_simple_method
);
527 * acpi_evaluate_ej0: Evaluate _EJ0 method for hotplug operations
528 * @handle: ACPI device handle
530 * Evaluate device's _EJ0 method for hotplug operations.
532 acpi_status
acpi_evaluate_ej0(acpi_handle handle
)
536 status
= acpi_execute_simple_method(handle
, "_EJ0", 1);
537 if (status
== AE_NOT_FOUND
)
538 acpi_handle_warn(handle
, "No _EJ0 support for device\n");
539 else if (ACPI_FAILURE(status
))
540 acpi_handle_warn(handle
, "Eject failed (0x%x)\n", status
);
546 * acpi_evaluate_lck: Evaluate _LCK method to lock/unlock device
547 * @handle: ACPI device handle
548 * @lock: lock device if non-zero, otherwise unlock device
550 * Evaluate device's _LCK method if present to lock/unlock device
552 acpi_status
acpi_evaluate_lck(acpi_handle handle
, int lock
)
556 status
= acpi_execute_simple_method(handle
, "_LCK", !!lock
);
557 if (ACPI_FAILURE(status
) && status
!= AE_NOT_FOUND
) {
559 acpi_handle_warn(handle
,
560 "Locking device failed (0x%x)\n", status
);
562 acpi_handle_warn(handle
,
563 "Unlocking device failed (0x%x)\n", status
);