- Kai Germaschewski: ISDN update (including Makefiles)
[davej-history.git] / drivers / acpi / interpreter / ammonad.c
blobac721583e115f2db647e92f4c57f139c15067e48
2 /******************************************************************************
4 * Module Name: ammonad - ACPI AML (p-code) execution for monadic operators
5 * $Revision: 85 $
7 *****************************************************************************/
9 /*
10 * Copyright (C) 2000 R. Byron Moore
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "acpi.h"
29 #include "acparser.h"
30 #include "acdispat.h"
31 #include "acinterp.h"
32 #include "amlcode.h"
33 #include "acnamesp.h"
36 #define _COMPONENT INTERPRETER
37 MODULE_NAME ("ammonad")
40 /*******************************************************************************
42 * FUNCTION: Acpi_aml_get_object_reference
44 * PARAMETERS: Obj_desc - Create a reference to this object
45 * Ret_desc - Where to store the reference
47 * RETURN: Status
49 * DESCRIPTION: Obtain and return a "reference" to the target object
50 * Common code for the Ref_of_op and the Cond_ref_of_op.
52 ******************************************************************************/
54 static ACPI_STATUS
55 acpi_aml_get_object_reference (
56 ACPI_OPERAND_OBJECT *obj_desc,
57 ACPI_OPERAND_OBJECT **ret_desc,
58 ACPI_WALK_STATE *walk_state)
60 ACPI_STATUS status = AE_OK;
63 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) {
64 if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) {
65 *ret_desc = NULL;
66 status = AE_TYPE;
67 goto cleanup;
71 * Not a Name -- an indirect name pointer would have
72 * been converted to a direct name pointer in Acpi_aml_resolve_operands
74 switch (obj_desc->reference.op_code)
76 case AML_LOCAL_OP:
78 *ret_desc = (void *) acpi_ds_method_data_get_nte (MTH_TYPE_LOCAL,
79 (obj_desc->reference.offset), walk_state);
80 break;
83 case AML_ARG_OP:
85 *ret_desc = (void *) acpi_ds_method_data_get_nte (MTH_TYPE_ARG,
86 (obj_desc->reference.offset), walk_state);
87 break;
90 default:
92 *ret_desc = NULL;
93 status = AE_AML_INTERNAL;
94 goto cleanup;
99 else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
100 /* Must be a named object; Just return the Node */
102 *ret_desc = obj_desc;
105 else {
106 *ret_desc = NULL;
107 status = AE_TYPE;
111 cleanup:
113 return (status);
117 /*******************************************************************************
119 * FUNCTION: Acpi_aml_exec_monadic1
121 * PARAMETERS: Opcode - The opcode to be executed
123 * RETURN: Status
125 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on
126 * object stack
128 ******************************************************************************/
130 ACPI_STATUS
131 acpi_aml_exec_monadic1 (
132 u16 opcode,
133 ACPI_WALK_STATE *walk_state)
135 ACPI_OPERAND_OBJECT *obj_desc;
136 ACPI_STATUS status;
139 /* Resolve all operands */
141 status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state);
142 /* Get all operands */
144 status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state);
145 if (ACPI_FAILURE (status)) {
146 goto cleanup;
150 /* Examine the opcode */
152 switch (opcode)
155 /* Def_release := Release_op Mutex_object */
157 case AML_RELEASE_OP:
159 status = acpi_aml_system_release_mutex (obj_desc);
160 break;
163 /* Def_reset := Reset_op Acpi_event_object */
165 case AML_RESET_OP:
167 status = acpi_aml_system_reset_event (obj_desc);
168 break;
171 /* Def_signal := Signal_op Acpi_event_object */
173 case AML_SIGNAL_OP:
175 status = acpi_aml_system_signal_event (obj_desc);
176 break;
179 /* Def_sleep := Sleep_op Msec_time */
181 case AML_SLEEP_OP:
183 acpi_aml_system_do_suspend ((u32) obj_desc->number.value);
184 break;
187 /* Def_stall := Stall_op Usec_time */
189 case AML_STALL_OP:
191 acpi_aml_system_do_stall ((u32) obj_desc->number.value);
192 break;
195 /* Unknown opcode */
197 default:
199 REPORT_ERROR (("Acpi_aml_exec_monadic1: Unknown monadic opcode %X\n",
200 opcode));
201 status = AE_AML_BAD_OPCODE;
202 break;
204 } /* switch */
207 cleanup:
209 /* Always delete the operand */
211 acpi_cm_remove_reference (obj_desc);
213 return (AE_OK);
217 /*******************************************************************************
219 * FUNCTION: Acpi_aml_exec_monadic2_r
221 * PARAMETERS: Opcode - The opcode to be executed
223 * RETURN: Status
225 * DESCRIPTION: Execute Type 2 monadic operator with numeric operand and
226 * result operand on operand stack
228 ******************************************************************************/
230 ACPI_STATUS
231 acpi_aml_exec_monadic2_r (
232 u16 opcode,
233 ACPI_WALK_STATE *walk_state,
234 ACPI_OPERAND_OBJECT **return_desc)
236 ACPI_OPERAND_OBJECT *obj_desc;
237 ACPI_OPERAND_OBJECT *res_desc;
238 ACPI_OPERAND_OBJECT *ret_desc = NULL;
239 ACPI_OPERAND_OBJECT *ret_desc2 = NULL;
240 u32 res_val;
241 ACPI_STATUS status;
242 u32 d0;
243 u32 d1;
244 u32 d2;
245 u32 d3;
248 /* Resolve all operands */
250 status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state);
251 /* Get all operands */
253 status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state);
254 status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state);
255 if (ACPI_FAILURE (status)) {
256 goto cleanup;
260 /* Create a return object of type NUMBER for most opcodes */
262 switch (opcode)
264 case AML_BIT_NOT_OP:
265 case AML_FIND_SET_LEFT_BIT_OP:
266 case AML_FIND_SET_RIGHT_BIT_OP:
267 case AML_FROM_BCD_OP:
268 case AML_TO_BCD_OP:
269 case AML_COND_REF_OF_OP:
271 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
272 if (!ret_desc) {
273 status = AE_NO_MEMORY;
274 goto cleanup;
277 break;
281 switch (opcode)
283 /* Def_not := Not_op Operand Result */
285 case AML_BIT_NOT_OP:
287 ret_desc->number.value = ~obj_desc->number.value;
288 break;
291 /* Def_find_set_left_bit := Find_set_left_bit_op Operand Result */
293 case AML_FIND_SET_LEFT_BIT_OP:
295 ret_desc->number.value = obj_desc->number.value;
298 * Acpi specification describes Integer type as a little
299 * endian unsigned value, so this boundry condition is valid.
301 for (res_val = 0; ret_desc->number.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
302 ret_desc->number.value >>= 1;
305 ret_desc->number.value = res_val;
306 break;
309 /* Def_find_set_right_bit := Find_set_right_bit_op Operand Result */
311 case AML_FIND_SET_RIGHT_BIT_OP:
313 ret_desc->number.value = obj_desc->number.value;
316 * Acpi specification describes Integer type as a little
317 * endian unsigned value, so this boundry condition is valid.
319 for (res_val = 0; ret_desc->number.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
320 ret_desc->number.value <<= 1;
323 /* Since returns must be 1-based, subtract from 33 (65) */
325 ret_desc->number.value = res_val == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - res_val;
326 break;
329 /* Def_from_bDC := From_bCDOp BCDValue Result */
331 case AML_FROM_BCD_OP:
333 /* TBD: for ACPI 2.0, expand to 64 bits */
335 d0 = (u32) (obj_desc->number.value & 15);
336 d1 = (u32) (obj_desc->number.value >> 4 & 15);
337 d2 = (u32) (obj_desc->number.value >> 8 & 15);
338 d3 = (u32) (obj_desc->number.value >> 12 & 15);
340 if (d0 > 9 || d1 > 9 || d2 > 9 || d3 > 9) {
341 status = AE_AML_NUMERIC_OVERFLOW;
342 goto cleanup;
345 ret_desc->number.value = d0 + d1 * 10 + d2 * 100 + d3 * 1000;
346 break;
349 /* Def_to_bDC := To_bCDOp Operand Result */
351 case AML_TO_BCD_OP:
353 /* TBD: for ACPI 2.0, expand to 64 bits */
355 if (obj_desc->number.value > 9999) {
356 status = AE_AML_NUMERIC_OVERFLOW;
357 goto cleanup;
360 ret_desc->number.value
361 = ACPI_MODULO (obj_desc->number.value, 10)
362 + (ACPI_MODULO (ACPI_DIVIDE (obj_desc->number.value, 10), 10) << 4)
363 + (ACPI_MODULO (ACPI_DIVIDE (obj_desc->number.value, 100), 10) << 8)
364 + (ACPI_MODULO (ACPI_DIVIDE (obj_desc->number.value, 1000), 10) << 12);
366 break;
369 /* Def_cond_ref_of := Cond_ref_of_op Source_object Result */
371 case AML_COND_REF_OF_OP:
374 * This op is a little strange because the internal return value is
375 * different than the return value stored in the result descriptor
376 * (There are really two return values)
379 if ((ACPI_NAMESPACE_NODE *) obj_desc == acpi_gbl_root_node) {
381 * This means that the object does not exist in the namespace,
382 * return FALSE
385 ret_desc->number.value = 0;
388 * Must delete the result descriptor since there is no reference
389 * being returned
392 acpi_cm_remove_reference (res_desc);
393 goto cleanup;
396 /* Get the object reference and store it */
398 status = acpi_aml_get_object_reference (obj_desc, &ret_desc2, walk_state);
399 if (ACPI_FAILURE (status)) {
400 goto cleanup;
403 status = acpi_aml_exec_store (ret_desc2, res_desc, walk_state);
405 /* The object exists in the namespace, return TRUE */
407 ret_desc->number.value = ACPI_INTEGER_MAX
408 goto cleanup;
409 break;
412 case AML_STORE_OP:
415 * A store operand is typically a number, string, buffer or lvalue
416 * TBD: [Unhandled] What about a store to a package?
420 * Do the store, and be careful about deleting the source object,
421 * since the object itself may have been stored.
424 status = acpi_aml_exec_store (obj_desc, res_desc, walk_state);
425 if (ACPI_FAILURE (status)) {
426 /* On failure, just delete the Obj_desc */
428 acpi_cm_remove_reference (obj_desc);
431 else {
433 * Normally, we would remove a reference on the Obj_desc parameter;
434 * But since it is being used as the internal return object
435 * (meaning we would normally increment it), the two cancel out,
436 * and we simply don't do anything.
438 *return_desc = obj_desc;
441 obj_desc = NULL;
442 return (status);
444 break;
447 case AML_DEBUG_OP:
449 /* Reference, returning an Reference */
451 return (AE_OK);
452 break;
456 * These are obsolete opcodes
459 /* Def_shift_left_bit := Shift_left_bit_op Source Bit_num */
460 /* Def_shift_right_bit := Shift_right_bit_op Source Bit_num */
462 case AML_SHIFT_LEFT_BIT_OP:
463 case AML_SHIFT_RIGHT_BIT_OP:
465 status = AE_SUPPORT;
466 goto cleanup;
467 break;
470 default:
472 REPORT_ERROR (("Acpi_aml_exec_monadic2_r: Unknown monadic opcode %X\n",
473 opcode));
474 status = AE_AML_BAD_OPCODE;
475 goto cleanup;
479 status = acpi_aml_exec_store (ret_desc, res_desc, walk_state);
482 cleanup:
483 /* Always delete the operand object */
485 acpi_cm_remove_reference (obj_desc);
487 /* Delete return object(s) on error */
489 if (ACPI_FAILURE (status)) {
490 acpi_cm_remove_reference (res_desc); /* Result descriptor */
491 if (ret_desc) {
492 acpi_cm_remove_reference (ret_desc);
493 ret_desc = NULL;
497 /* Set the return object and exit */
499 *return_desc = ret_desc;
500 return (status);
504 /*******************************************************************************
506 * FUNCTION: Acpi_aml_exec_monadic2
508 * PARAMETERS: Opcode - The opcode to be executed
510 * RETURN: Status
512 * DESCRIPTION: Execute Type 2 monadic operator with numeric operand:
513 * Deref_of_op, Ref_of_op, Size_of_op, Type_op, Increment_op,
514 * Decrement_op, LNot_op,
516 ******************************************************************************/
518 ACPI_STATUS
519 acpi_aml_exec_monadic2 (
520 u16 opcode,
521 ACPI_WALK_STATE *walk_state,
522 ACPI_OPERAND_OBJECT **return_desc)
524 ACPI_OPERAND_OBJECT *obj_desc;
525 ACPI_OPERAND_OBJECT *tmp_desc;
526 ACPI_OPERAND_OBJECT *ret_desc = NULL;
527 ACPI_STATUS resolve_status;
528 ACPI_STATUS status;
529 u32 type;
530 ACPI_INTEGER value;
533 /* Attempt to resolve the operands */
535 resolve_status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state);
536 /* Always get all operands */
538 status = acpi_ds_obj_stack_pop_object (&obj_desc, walk_state);
541 /* Now we can check the status codes */
543 if (ACPI_FAILURE (resolve_status)) {
544 goto cleanup;
547 if (ACPI_FAILURE (status)) {
548 goto cleanup;
552 /* Get the operand and decode the opcode */
555 switch (opcode)
558 /* Def_lNot := LNot_op Operand */
560 case AML_LNOT_OP:
562 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
563 if (!ret_desc) {
564 status = AE_NO_MEMORY;
565 goto cleanup;
568 ret_desc->number.value = !obj_desc->number.value;
569 break;
572 /* Def_decrement := Decrement_op Target */
573 /* Def_increment := Increment_op Target */
575 case AML_DECREMENT_OP:
576 case AML_INCREMENT_OP:
579 * Since we are expecting an Reference on the top of the stack, it
580 * can be either an Node or an internal object.
582 * TBD: [Future] This may be the prototype code for all cases where
583 * an Reference is expected!! 10/99
586 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
587 ret_desc = obj_desc;
590 else {
592 * Duplicate the Reference in a new object so that we can resolve it
593 * without destroying the original Reference object
596 ret_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE);
597 if (!ret_desc) {
598 status = AE_NO_MEMORY;
599 goto cleanup;
602 ret_desc->reference.op_code = obj_desc->reference.op_code;
603 ret_desc->reference.offset = obj_desc->reference.offset;
604 ret_desc->reference.object = obj_desc->reference.object;
609 * Convert the Ret_desc Reference to a Number
610 * (This deletes the original Ret_desc)
613 status = acpi_aml_resolve_operands (AML_LNOT_OP, &ret_desc, walk_state);
614 if (ACPI_FAILURE (status)) {
615 goto cleanup;
618 /* Do the actual increment or decrement */
620 if (AML_INCREMENT_OP == opcode) {
621 ret_desc->number.value++;
623 else {
624 ret_desc->number.value--;
627 /* Store the result back in the original descriptor */
629 status = acpi_aml_exec_store (ret_desc, obj_desc, walk_state);
631 /* Objdesc was just deleted (because it is an Reference) */
633 obj_desc = NULL;
635 break;
638 /* Def_object_type := Object_type_op Source_object */
640 case AML_TYPE_OP:
642 if (INTERNAL_TYPE_REFERENCE == obj_desc->common.type) {
644 * Not a Name -- an indirect name pointer would have
645 * been converted to a direct name pointer in Resolve_operands
647 switch (obj_desc->reference.op_code)
649 case AML_ZERO_OP:
650 case AML_ONE_OP:
651 case AML_ONES_OP:
653 /* Constants are of type Number */
655 type = ACPI_TYPE_NUMBER;
656 break;
659 case AML_DEBUG_OP:
661 /* Per 1.0b spec, Debug object is of type Debug_object */
663 type = ACPI_TYPE_DEBUG_OBJECT;
664 break;
667 case AML_INDEX_OP:
669 /* Get the type of this reference (index into another object) */
671 type = obj_desc->reference.target_type;
672 if (type == ACPI_TYPE_PACKAGE) {
674 * The main object is a package, we want to get the type
675 * of the individual package element that is referenced by
676 * the index.
678 type = (*(obj_desc->reference.where))->common.type;
681 break;
684 case AML_LOCAL_OP:
686 type = acpi_ds_method_data_get_type (MTH_TYPE_LOCAL,
687 (obj_desc->reference.offset), walk_state);
688 break;
691 case AML_ARG_OP:
693 type = acpi_ds_method_data_get_type (MTH_TYPE_ARG,
694 (obj_desc->reference.offset), walk_state);
695 break;
698 default:
700 REPORT_ERROR (("Acpi_aml_exec_monadic2/Type_op: Internal error - Unknown Reference subtype %X\n",
701 obj_desc->reference.op_code));
702 status = AE_AML_INTERNAL;
703 goto cleanup;
707 else {
709 * It's not a Reference, so it must be a direct name pointer.
711 type = acpi_ns_get_type ((ACPI_HANDLE) obj_desc);
714 /* Allocate a descriptor to hold the type. */
716 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
717 if (!ret_desc) {
718 status = AE_NO_MEMORY;
719 goto cleanup;
722 ret_desc->number.value = type;
723 break;
726 /* Def_size_of := Size_of_op Source_object */
728 case AML_SIZE_OF_OP:
730 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
731 obj_desc = acpi_ns_get_attached_object (obj_desc);
734 if (!obj_desc) {
735 value = 0;
738 else {
739 switch (obj_desc->common.type)
742 case ACPI_TYPE_BUFFER:
744 value = obj_desc->buffer.length;
745 break;
748 case ACPI_TYPE_STRING:
750 value = obj_desc->string.length;
751 break;
754 case ACPI_TYPE_PACKAGE:
756 value = obj_desc->package.count;
757 break;
759 case INTERNAL_TYPE_REFERENCE:
761 value = 4;
762 break;
764 default:
766 status = AE_AML_OPERAND_TYPE;
767 goto cleanup;
772 * Now that we have the size of the object, create a result
773 * object to hold the value
776 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
777 if (!ret_desc) {
778 status = AE_NO_MEMORY;
779 goto cleanup;
782 ret_desc->number.value = value;
783 break;
786 /* Def_ref_of := Ref_of_op Source_object */
788 case AML_REF_OF_OP:
790 status = acpi_aml_get_object_reference (obj_desc, &ret_desc, walk_state);
791 if (ACPI_FAILURE (status)) {
792 goto cleanup;
794 break;
797 /* Def_deref_of := Deref_of_op Obj_reference */
799 case AML_DEREF_OF_OP:
802 /* Check for a method local or argument */
804 if (!VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
806 * Must resolve/dereference the local/arg reference first
808 switch (obj_desc->reference.op_code)
810 /* Set Obj_desc to the value of the local/arg */
812 case AML_LOCAL_OP:
814 acpi_ds_method_data_get_value (MTH_TYPE_LOCAL,
815 (obj_desc->reference.offset), walk_state, &tmp_desc);
818 * Delete our reference to the input object and
819 * point to the object just retrieved
821 acpi_cm_remove_reference (obj_desc);
822 obj_desc = tmp_desc;
823 break;
826 case AML_ARG_OP:
828 acpi_ds_method_data_get_value (MTH_TYPE_ARG,
829 (obj_desc->reference.offset), walk_state, &tmp_desc);
832 * Delete our reference to the input object and
833 * point to the object just retrieved
835 acpi_cm_remove_reference (obj_desc);
836 obj_desc = tmp_desc;
837 break;
839 default:
841 /* Index op - handled below */
842 break;
847 /* Obj_desc may have changed from the code above */
849 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
850 /* Get the actual object from the Node (This is the dereference) */
852 ret_desc = ((ACPI_NAMESPACE_NODE *) obj_desc)->object;
854 /* Returning a pointer to the object, add another reference! */
856 acpi_cm_add_reference (ret_desc);
859 else {
861 * This must be a reference object produced by the Index
862 * ASL operation -- check internal opcode
865 if ((obj_desc->reference.op_code != AML_INDEX_OP) &&
866 (obj_desc->reference.op_code != AML_REF_OF_OP))
868 status = AE_TYPE;
869 goto cleanup;
873 switch (obj_desc->reference.op_code)
875 case AML_INDEX_OP:
878 * Supported target types for the Index operator are
879 * 1) A Buffer
880 * 2) A Package
883 if (obj_desc->reference.target_type == ACPI_TYPE_BUFFER_FIELD) {
885 * The target is a buffer, we must create a new object that
886 * contains one element of the buffer, the element pointed
887 * to by the index.
889 * NOTE: index into a buffer is NOT a pointer to a
890 * sub-buffer of the main buffer, it is only a pointer to a
891 * single element (byte) of the buffer!
893 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
894 if (!ret_desc) {
895 status = AE_NO_MEMORY;
896 goto cleanup;
899 tmp_desc = obj_desc->reference.object;
900 ret_desc->number.value =
901 tmp_desc->buffer.pointer[obj_desc->reference.offset];
903 /* TBD: [Investigate] (see below) Don't add an additional
904 * ref!
908 else if (obj_desc->reference.target_type == ACPI_TYPE_PACKAGE) {
910 * The target is a package, we want to return the referenced
911 * element of the package. We must add another reference to
912 * this object, however.
915 ret_desc = *(obj_desc->reference.where);
916 if (!ret_desc) {
918 * We can't return a NULL dereferenced value. This is
919 * an uninitialized package element and is thus a
920 * severe error.
923 status = AE_AML_UNINITIALIZED_ELEMENT;
924 goto cleanup;
927 acpi_cm_add_reference (ret_desc);
930 else {
931 status = AE_AML_OPERAND_TYPE;
932 goto cleanup;
935 break;
938 case AML_REF_OF_OP:
940 ret_desc = obj_desc->reference.object;
942 /* Add another reference to the object! */
944 acpi_cm_add_reference (ret_desc);
945 break;
949 break;
952 default:
954 REPORT_ERROR (("Acpi_aml_exec_monadic2: Unknown monadic opcode %X\n",
955 opcode));
956 status = AE_AML_BAD_OPCODE;
957 goto cleanup;
961 cleanup:
963 if (obj_desc) {
964 acpi_cm_remove_reference (obj_desc);
967 /* Delete return object on error */
969 if (ACPI_FAILURE (status) &&
970 (ret_desc))
972 acpi_cm_remove_reference (ret_desc);
973 ret_desc = NULL;
976 *return_desc = ret_desc;
977 return (status);