Merge with 2.4.0-test3-pre4.
[linux-2.6/linux-mips.git] / drivers / acpi / common / cmcopy.c
blobc5a828c622c0bc2d4281cd1d2ba8a052107c46d9
1 /******************************************************************************
3 * Module Name: cmcopy - Internal to external object translation utilities
5 *****************************************************************************/
7 /*
8 * Copyright (C) 2000 R. Byron Moore
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "acpi.h"
27 #include "interp.h"
28 #include "namesp.h"
31 #define _COMPONENT MISCELLANEOUS
32 MODULE_NAME ("cmcopy");
35 typedef struct search_st
37 ACPI_OBJECT_INTERNAL *internal_obj;
38 u32 index;
39 ACPI_OBJECT *external_obj;
41 } PKG_SEARCH_INFO;
44 /* Used to traverse nested packages */
46 PKG_SEARCH_INFO level[MAX_PACKAGE_DEPTH];
48 /******************************************************************************
50 * FUNCTION: Acpi_cm_build_external_simple_object
52 * PARAMETERS: *Internal_obj - Pointer to the object we are examining
53 * *Buffer - Where the object is returned
54 * *Space_used - Where the data length is returned
56 * RETURN: Status - the status of the call
58 * DESCRIPTION: This function is called to place a simple object in a user
59 * buffer.
61 * The buffer is assumed to have sufficient space for the object.
63 ******************************************************************************/
65 ACPI_STATUS
66 acpi_cm_build_external_simple_object (
67 ACPI_OBJECT_INTERNAL *internal_obj,
68 ACPI_OBJECT *external_obj,
69 u8 *data_space,
70 u32 *buffer_space_used)
72 u32 length = 0;
73 char *source_ptr = NULL;
77 * Check for NULL object case (could be an uninitialized
78 * package element
81 if (!internal_obj) {
82 *buffer_space_used = 0;
83 return (AE_OK);
86 /* Always clear the external object */
88 MEMSET (external_obj, 0, sizeof (ACPI_OBJECT));
91 * In general, the external object will be the same type as
92 * the internal object
95 external_obj->type = internal_obj->common.type;
97 /* However, only a limited number of external types are supported */
99 switch (external_obj->type)
102 case ACPI_TYPE_STRING:
104 length = internal_obj->string.length;
105 external_obj->string.length = internal_obj->string.length;
106 external_obj->string.pointer = (char *) data_space;
107 source_ptr = internal_obj->string.pointer;
108 break;
111 case ACPI_TYPE_BUFFER:
113 length = internal_obj->buffer.length;
114 external_obj->buffer.length = internal_obj->buffer.length;
115 external_obj->buffer.pointer = data_space;
116 source_ptr = (char *) internal_obj->buffer.pointer;
117 break;
120 case ACPI_TYPE_NUMBER:
122 external_obj->number.value= internal_obj->number.value;
123 break;
126 case INTERNAL_TYPE_REFERENCE:
129 * This is an object reference. We use the object type of "Any"
130 * to indicate a reference object containing a handle to an ACPI
131 * named object.
134 external_obj->type = ACPI_TYPE_ANY;
135 external_obj->reference.handle = internal_obj->reference.nte;
136 break;
139 case ACPI_TYPE_PROCESSOR:
141 external_obj->processor.proc_id =
142 internal_obj->processor.proc_id;
144 external_obj->processor.pblk_address =
145 internal_obj->processor.pblk_address;
147 external_obj->processor.pblk_length =
148 internal_obj->processor.pblk_length;
149 break;
151 case ACPI_TYPE_POWER:
153 external_obj->power_resource.system_level =
154 internal_obj->power_resource.system_level;
156 external_obj->power_resource.resource_order =
157 internal_obj->power_resource.resource_order;
158 break;
160 default:
161 return (AE_CTRL_RETURN_VALUE);
162 break;
166 /* Copy data if necessary (strings or buffers) */
168 if (length) {
170 * Copy the return data to the caller's buffer
172 MEMCPY ((void *) data_space, (void *) source_ptr, length);
176 *buffer_space_used = (u32) ROUND_UP_TO_NATIVE_WORD (length);
178 return (AE_OK);
182 /******************************************************************************
184 * FUNCTION: Acpi_cm_build_external_package_object
186 * PARAMETERS: *Internal_obj - Pointer to the object we are returning
187 * *Buffer - Where the object is returned
188 * *Space_used - Where the object length is returned
190 * RETURN: Status - the status of the call
192 * DESCRIPTION: This function is called to place a package object in a user
193 * buffer. A package object by definition contains other objects.
195 * The buffer is assumed to have sufficient space for the object.
196 * The caller must have verified the buffer length needed using the
197 * Acpi_cm_get_object_size function before calling this function.
199 ******************************************************************************/
201 ACPI_STATUS
202 acpi_cm_build_external_package_object (
203 ACPI_OBJECT_INTERNAL *internal_obj,
204 u8 *buffer,
205 u32 *space_used)
207 u8 *free_space;
208 ACPI_OBJECT *external_obj;
209 u32 current_depth = 0;
210 ACPI_STATUS status;
211 u32 length = 0;
212 u32 this_index;
213 u32 object_space;
214 ACPI_OBJECT_INTERNAL *this_internal_obj;
215 ACPI_OBJECT *this_external_obj;
216 PKG_SEARCH_INFO *level_ptr;
220 * First package at head of the buffer
222 external_obj = (ACPI_OBJECT *) buffer;
225 * Free space begins right after the first package
227 free_space = buffer + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
231 * Initialize the working variables
234 MEMSET ((void *) level, 0, sizeof (level));
236 level[0].internal_obj = internal_obj;
237 level[0].external_obj = external_obj;
238 level[0].index = 0;
239 level_ptr = &level[0];
240 current_depth = 0;
242 external_obj->type = internal_obj->common.type;
243 external_obj->package.count = internal_obj->package.count;
244 external_obj->package.elements = (ACPI_OBJECT *) free_space;
248 * Build an array of ACPI_OBJECTS in the buffer
249 * and move the free space past it
252 free_space += external_obj->package.count *
253 ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
256 while (1) {
257 this_index = level_ptr->index;
258 this_internal_obj =
259 (ACPI_OBJECT_INTERNAL *)
260 level_ptr->internal_obj->package.elements[this_index];
261 this_external_obj =
262 (ACPI_OBJECT *)
263 &level_ptr->external_obj->package.elements[this_index];
267 * Check for 1) Null object -- OK, this can happen if package
268 * element is never initialized
269 * 2) Not an internal object - can be an NTE instead
270 * 3) Any internal object other than a package.
272 * The more complex package case is handled later
275 if ((!this_internal_obj) ||
276 (!VALID_DESCRIPTOR_TYPE (
277 this_internal_obj, ACPI_DESC_TYPE_INTERNAL)) ||
278 (!IS_THIS_OBJECT_TYPE (
279 this_internal_obj, ACPI_TYPE_PACKAGE)))
282 * This is a simple or null object -- get the size
285 status =
286 acpi_cm_build_external_simple_object (this_internal_obj,
287 this_external_obj,
288 free_space,
289 &object_space);
290 if (ACPI_FAILURE (status)) {
291 return (status);
294 free_space += object_space;
295 length += object_space;
297 level_ptr->index++;
298 while (level_ptr->index >=
299 level_ptr->internal_obj->package.count)
302 * We've handled all of the objects at this
303 * level. This means that we have just
304 * completed a package. That package may
305 * have contained one or more packages
306 * itself
308 if (current_depth == 0) {
310 * We have handled all of the objects
311 * in the top level package just add
312 * the length of the package objects
313 * and get out
315 *space_used = length;
316 return (AE_OK);
320 * go back up a level and move the index
321 * past the just completed package object.
323 current_depth--;
324 level_ptr = &level[current_depth];
325 level_ptr->index++;
330 else {
332 * This object is a package
333 * -- we must go one level deeper
335 if (current_depth >= MAX_PACKAGE_DEPTH-1) {
337 * Too many nested levels of packages
338 * for us to handle
340 return (AE_LIMIT);
344 * Build the package object
346 this_external_obj->type = ACPI_TYPE_PACKAGE;
347 this_external_obj->package.count =
348 this_internal_obj->package.count;
349 this_external_obj->package.elements =
350 (ACPI_OBJECT *) free_space;
353 * Save space for the array of objects (Package elements)
354 * update the buffer length counter
356 object_space = (u32) ROUND_UP_TO_NATIVE_WORD (
357 this_external_obj->package.count *
358 sizeof (ACPI_OBJECT));
360 free_space += object_space;
361 length += object_space;
363 current_depth++;
364 level_ptr = &level[current_depth];
365 level_ptr->internal_obj = this_internal_obj;
366 level_ptr->external_obj = this_external_obj;
367 level_ptr->index = 0;
371 return (AE_OK);
375 /******************************************************************************
377 * FUNCTION: Acpi_cm_build_external_object
379 * PARAMETERS: *Internal_obj - The internal object to be converted
380 * *Buffer_ptr - Where the object is returned
382 * RETURN: Status - the status of the call
384 * DESCRIPTION: This function is called to build an API object to be returned to
385 * the caller.
387 ******************************************************************************/
389 ACPI_STATUS
390 acpi_cm_build_external_object (
391 ACPI_OBJECT_INTERNAL *internal_obj,
392 ACPI_BUFFER *ret_buffer)
394 ACPI_STATUS status;
397 if (IS_THIS_OBJECT_TYPE (internal_obj, ACPI_TYPE_PACKAGE)) {
399 * Package objects contain other objects (which can be objects)
400 * buildpackage does it all
402 status =
403 acpi_cm_build_external_package_object (internal_obj,
404 ret_buffer->pointer,
405 &ret_buffer->length);
408 else {
410 * Build a simple object (no nested objects)
412 status =
413 acpi_cm_build_external_simple_object (internal_obj,
414 (ACPI_OBJECT *) ret_buffer->pointer,
415 ((u8 *) ret_buffer->pointer +
416 ROUND_UP_TO_NATIVE_WORD (
417 sizeof (ACPI_OBJECT))),
418 &ret_buffer->length);
420 * build simple does not include the object size in the length
421 * so we add it in here
423 ret_buffer->length += sizeof (ACPI_OBJECT);
426 return (status);
430 /******************************************************************************
432 * FUNCTION: Acpi_cm_build_internal_simple_object
434 * PARAMETERS: *External_obj - The external object to be converted
435 * *Internal_obj - Where the internal object is returned
437 * RETURN: Status - the status of the call
439 * DESCRIPTION: This function copies an external object to an internal one.
440 * NOTE: Pointers can be copied, we don't need to copy data.
441 * (The pointers have to be valid in our address space no matter
442 * what we do with them!)
444 ******************************************************************************/
446 ACPI_STATUS
447 acpi_cm_build_internal_simple_object (
448 ACPI_OBJECT *external_obj,
449 ACPI_OBJECT_INTERNAL *internal_obj)
453 internal_obj->common.type = (u8) external_obj->type;
455 switch (external_obj->type)
458 case ACPI_TYPE_STRING:
460 internal_obj->string.length = external_obj->string.length;
461 internal_obj->string.pointer = external_obj->string.pointer;
462 break;
465 case ACPI_TYPE_BUFFER:
467 internal_obj->buffer.length = external_obj->buffer.length;
468 internal_obj->buffer.pointer = external_obj->buffer.pointer;
469 break;
472 case ACPI_TYPE_NUMBER:
474 * Number is included in the object itself
476 internal_obj->number.value = external_obj->number.value;
477 break;
480 default:
481 return (AE_CTRL_RETURN_VALUE);
482 break;
486 return (AE_OK);
490 /******************************************************************************
492 * FUNCTION: Acpi_cm_build_internal_package_object
494 * PARAMETERS: *Internal_obj - Pointer to the object we are returning
495 * *Buffer - Where the object is returned
496 * *Space_used - Where the length of the object is returned
498 * RETURN: Status - the status of the call
500 * DESCRIPTION: This function is called to place a package object in a user
501 * buffer. A package object by definition contains other objects.
503 * The buffer is assumed to have sufficient space for the object.
504 * The caller must have verified the buffer length needed using the
505 * Acpi_cm_get_object_size function before calling this function.
507 ******************************************************************************/
509 ACPI_STATUS
510 acpi_cm_build_internal_package_object (
511 ACPI_OBJECT_INTERNAL *internal_obj,
512 u8 *buffer,
513 u32 *space_used)
515 u8 *free_space;
516 ACPI_OBJECT *external_obj;
517 u32 current_depth = 0;
518 ACPI_STATUS status = AE_OK;
519 u32 length = 0;
520 u32 this_index;
521 u32 object_space = 0;
522 ACPI_OBJECT_INTERNAL *this_internal_obj;
523 ACPI_OBJECT *this_external_obj;
524 PKG_SEARCH_INFO *level_ptr;
528 * First package at head of the buffer
530 external_obj = (ACPI_OBJECT *)buffer;
533 * Free space begins right after the first package
535 free_space = buffer + sizeof(ACPI_OBJECT);
539 * Initialize the working variables
542 MEMSET ((void *) level, 0, sizeof(level));
544 level[0].internal_obj = internal_obj;
545 level[0].external_obj = external_obj;
546 level_ptr = &level[0];
547 current_depth = 0;
549 external_obj->type = internal_obj->common.type;
550 external_obj->package.count = internal_obj->package.count;
551 external_obj->package.elements = (ACPI_OBJECT *)free_space;
555 * Build an array of ACPI_OBJECTS in the buffer
556 * and move the free space past it
559 free_space += external_obj->package.count * sizeof(ACPI_OBJECT);
562 while (1) {
563 this_index = level_ptr->index;
565 this_internal_obj = (ACPI_OBJECT_INTERNAL *)
566 &level_ptr->internal_obj->package.elements[this_index];
568 this_external_obj = (ACPI_OBJECT *)
569 &level_ptr->external_obj->package.elements[this_index];
571 if (IS_THIS_OBJECT_TYPE (this_internal_obj, ACPI_TYPE_PACKAGE)) {
573 * If this object is a package then we go one deeper
575 if (current_depth >= MAX_PACKAGE_DEPTH-1) {
577 * Too many nested levels of packages for us to handle
579 return (AE_LIMIT);
583 * Build the package object
585 this_external_obj->type = ACPI_TYPE_PACKAGE;
586 this_external_obj->package.count = this_internal_obj->package.count;
587 this_external_obj->package.elements = (ACPI_OBJECT *) free_space;
590 * Save space for the array of objects (Package elements)
591 * update the buffer length counter
593 object_space = this_external_obj->package.count *
594 sizeof (ACPI_OBJECT);
596 free_space += object_space;
597 length += object_space;
599 current_depth++;
600 level_ptr = &level[current_depth];
601 level_ptr->internal_obj = this_internal_obj;
602 level_ptr->external_obj = this_external_obj;
603 level_ptr->index = 0;
605 } /* if object is a package */
607 else {
608 /* Status = Acpi_cm_build_simple_object(This_internal_obj,
609 This_external_obj, Free_space,
610 &Object_space);
612 if (status != AE_OK) {
614 * Failure get out
616 return (status);
619 free_space += object_space;
620 length += object_space;
622 level_ptr->index++;
623 while (level_ptr->index >=
624 level_ptr->internal_obj->package.count)
627 * We've handled all of the objects at
628 * this level, This means that we have
629 * just completed a package. That package
630 * may have contained one or more packages
631 * itself
633 if (current_depth == 0) {
635 * We have handled all of the objects
636 * in the top level package just add
637 * the length of the package objects
638 * and get out
640 *space_used = length;
641 return (AE_OK);
645 * go back up a level and move the index
646 * past the just completed package object.
648 current_depth--;
649 level_ptr = &level[current_depth];
650 level_ptr->index++;
652 } /* else object is NOT a package */
653 } /* while (1) */
657 * We'll never get here, but the compiler whines about
658 * return value
660 return (AE_OK);
664 /******************************************************************************
666 * FUNCTION: Acpi_cm_build_internal_object
668 * PARAMETERS: *Internal_obj - The external object to be converted
669 * *Buffer_ptr - Where the internal object is returned
671 * RETURN: Status - the status of the call
673 * DESCRIPTION: Converts an external object to an internal object.
675 ******************************************************************************/
677 ACPI_STATUS
678 acpi_cm_build_internal_object (
679 ACPI_OBJECT *external_obj,
680 ACPI_OBJECT_INTERNAL *internal_obj)
682 ACPI_STATUS status;
685 if (external_obj->type == ACPI_TYPE_PACKAGE) {
687 * Package objects contain other objects (which can be objects)
688 * buildpackage does it all
691 Status = Acpi_cm_build_internal_package_object(Internal_obj,
692 Ret_buffer->Pointer,
693 &Ret_buffer->Length);
695 return (AE_NOT_IMPLEMENTED);
698 else {
700 * Build a simple object (no nested objects)
702 status = acpi_cm_build_internal_simple_object (external_obj, internal_obj);
704 * build simple does not include the object size in the length
705 * so we add it in here
709 return (status);