File: /usr/src/linux/drivers/acpi/namespace/nsobject.c

1     /*******************************************************************************
2      *
3      * Module Name: nsobject - Utilities for objects attached to namespace
4      *                         table entries
5      *              $Revision: 65 $
6      *
7      ******************************************************************************/
8     
9     /*
10      *  Copyright (C) 2000, 2001 R. Byron Moore
11      *
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.
16      *
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.
21      *
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
25      */
26     
27     
28     #include "acpi.h"
29     #include "amlcode.h"
30     #include "acnamesp.h"
31     #include "acinterp.h"
32     #include "actables.h"
33     
34     
35     #define _COMPONENT          ACPI_NAMESPACE
36     	 MODULE_NAME         ("nsobject")
37     
38     
39     /*******************************************************************************
40      *
41      * FUNCTION:    Acpi_ns_attach_object
42      *
43      * PARAMETERS:  Node                - Parent Node
44      *              Object              - Object to be attached
45      *              Type                - Type of object, or ACPI_TYPE_ANY if not
46      *                                    known
47      *
48      * DESCRIPTION: Record the given object as the value associated with the
49      *              name whose acpi_handle is passed.  If Object is NULL
50      *              and Type is ACPI_TYPE_ANY, set the name as having no value.
51      *
52      * MUTEX:       Assumes namespace is locked
53      *
54      ******************************************************************************/
55     
56     acpi_status
57     acpi_ns_attach_object (
58     	acpi_namespace_node     *node,
59     	acpi_operand_object     *object,
60     	acpi_object_type8       type)
61     {
62     	acpi_operand_object     *obj_desc;
63     	acpi_operand_object     *previous_obj_desc;
64     	acpi_object_type8       obj_type = ACPI_TYPE_ANY;
65     	u8                      flags;
66     	u16                     opcode;
67     
68     
69     	FUNCTION_TRACE ("Ns_attach_object");
70     
71     
72     	/*
73     	 * Parameter validation
74     	 */
75     	if (!acpi_gbl_root_node) {
76     		/* Name space not initialized  */
77     
78     		REPORT_ERROR (("Ns_attach_object: Namespace not initialized\n"));
79     		return_ACPI_STATUS (AE_NO_NAMESPACE);
80     	}
81     
82     	if (!node) {
83     		/* Invalid handle */
84     
85     		REPORT_ERROR (("Ns_attach_object: Null Named_obj handle\n"));
86     		return_ACPI_STATUS (AE_BAD_PARAMETER);
87     	}
88     
89     	if (!object && (ACPI_TYPE_ANY != type)) {
90     		/* Null object */
91     
92     		REPORT_ERROR (("Ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n"));
93     		return_ACPI_STATUS (AE_BAD_PARAMETER);
94     	}
95     
96     	if (!VALID_DESCRIPTOR_TYPE (node, ACPI_DESC_TYPE_NAMED)) {
97     		/* Not a name handle */
98     
99     		REPORT_ERROR (("Ns_attach_object: Invalid handle\n"));
100     		return_ACPI_STATUS (AE_BAD_PARAMETER);
101     	}
102     
103     	/* Check if this object is already attached */
104     
105     	if (node->object == object) {
106     		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj %p already installed in Name_obj %p\n",
107     			object, node));
108     
109     		return_ACPI_STATUS (AE_OK);
110     	}
111     
112     
113     	/* Get the current flags field of the Node */
114     
115     	flags = node->flags;
116     	flags &= ~ANOBJ_AML_ATTACHMENT;
117     
118     
119     	/* If null object, we will just install it */
120     
121     	if (!object) {
122     		obj_desc = NULL;
123     		obj_type = ACPI_TYPE_ANY;
124     	}
125     
126     	/*
127     	 * If the source object is a namespace Node with an attached object,
128     	 * we will use that (attached) object
129     	 */
130     	else if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED) &&
131     			((acpi_namespace_node *) object)->object) {
132     		/*
133     		 * Value passed is a name handle and that name has a
134     		 * non-null value.  Use that name's value and type.
135     		 */
136     		obj_desc = ((acpi_namespace_node *) object)->object;
137     		obj_type = ((acpi_namespace_node *) object)->type;
138     
139     		/*
140     		 * Copy appropriate flags
141     		 */
142     		if (((acpi_namespace_node *) object)->flags & ANOBJ_AML_ATTACHMENT) {
143     			flags |= ANOBJ_AML_ATTACHMENT;
144     		}
145     	}
146     
147     
148     	/*
149     	 * Otherwise, we will use the parameter object, but we must type
150     	 * it first
151     	 */
152     	else {
153     		obj_desc = (acpi_operand_object *) object;
154     
155     		/* If a valid type (non-ANY) was given, just use it */
156     
157     		if (ACPI_TYPE_ANY != type) {
158     			obj_type = type;
159     		}
160     
161     		/*
162     		 * Type is TYPE_Any, we must try to determinte the
163     		 * actual type of the object.
164     		 * Check if value points into the AML code
165     		 */
166     		else if (acpi_tb_system_table_pointer (object)) {
167     			/*
168     			 * Object points into the AML stream.
169     			 * Set a flag bit in the Node to indicate this
170     			 */
171     			flags |= ANOBJ_AML_ATTACHMENT;
172     
173     			/*
174     			 * The next byte (perhaps the next two bytes)
175     			 * will be the AML opcode
176     			 */
177     			MOVE_UNALIGNED16_TO_16 (&opcode, object);
178     
179     			/* Check for a recognized Opcode */
180     
181     			switch ((u8) opcode) {
182     
183     			case AML_OP_PREFIX:
184     
185     				if (opcode != AML_REVISION_OP) {
186     					/*
187     					 * Op_prefix is unrecognized unless part
188     					 * of Revision_op
189     					 */
190     					break;
191     				}
192     
193     				/* case AML_REVISION_OP: fall through and set the type to Integer */
194     
195     			case AML_ZERO_OP:
196     			case AML_ONES_OP:
197     			case AML_ONE_OP:
198     			case AML_BYTE_OP:
199     			case AML_WORD_OP:
200     			case AML_DWORD_OP:
201     			case AML_QWORD_OP:
202     
203     				obj_type = ACPI_TYPE_INTEGER;
204     				break;
205     
206     
207     			case AML_STRING_OP:
208     
209     				obj_type = ACPI_TYPE_STRING;
210     				break;
211     
212     
213     			case AML_BUFFER_OP:
214     
215     				obj_type = ACPI_TYPE_BUFFER;
216     				break;
217     
218     
219     			case AML_MUTEX_OP:
220     
221     				obj_type = ACPI_TYPE_MUTEX;
222     				break;
223     
224     
225     			case AML_PACKAGE_OP:
226     
227     				obj_type = ACPI_TYPE_PACKAGE;
228     				break;
229     
230     
231     			default:
232     
233     				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
234     					"AML Opcode/Type [%x] not supported in attach\n",
235     					(u8) opcode));
236     
237     				return_ACPI_STATUS (AE_TYPE);
238     				break;
239     			}
240     		}
241     
242     		else {
243     			/*
244     			 * Cannot figure out the type -- set to Def_any which
245     			 * will print as an error in the name table dump
246     			 */
247     			if (acpi_dbg_level > 0) {
248     				DUMP_PATHNAME (node,
249     					"Ns_attach_object confused: setting bogus type for ",
250     					ACPI_LV_INFO, _COMPONENT);
251     
252     				if (acpi_tb_system_table_pointer (object)) {
253     					ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
254     						"AML-stream code %02x\n", *(u8 *) object));
255     				}
256     
257     				else if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED)) {
258     					DUMP_PATHNAME (object, "name ", ACPI_LV_INFO, _COMPONENT);
259     				}
260     
261     				else {
262     					DUMP_PATHNAME (object, "object ", ACPI_LV_INFO, _COMPONENT);
263     					DUMP_STACK_ENTRY (object);
264     				}
265     			}
266     
267     			obj_type = INTERNAL_TYPE_DEF_ANY;
268     		}
269     	}
270     
271     
272     	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
273     		obj_desc, node, &node->name));
274     
275     
276     	/*
277     	 * Must increment the new value's reference count
278     	 * (if it is an internal object)
279     	 */
280     	acpi_ut_add_reference (obj_desc);
281     
282     	/* Save the existing object (if any) for deletion later */
283     
284     	previous_obj_desc = node->object;
285     
286     	/* Install the object and set the type, flags */
287     
288     	node->object   = obj_desc;
289     	node->type     = (u8) obj_type;
290     	node->flags    |= flags;
291     
292     
293     	/*
294     	 * Delete an existing attached object.
295     	 */
296     	if (previous_obj_desc) {
297     		/* One for the attach to the Node */
298     
299     		acpi_ut_remove_reference (previous_obj_desc);
300     
301     		/* Now delete */
302     
303     		acpi_ut_remove_reference (previous_obj_desc);
304     	}
305     
306     	return_ACPI_STATUS (AE_OK);
307     }
308     
309     
310     /*******************************************************************************
311      *
312      * FUNCTION:    Acpi_ns_detach_object
313      *
314      * PARAMETERS:  Node           - An object whose Value will be deleted
315      *
316      * RETURN:      None.
317      *
318      * DESCRIPTION: Delete the Value associated with a namespace object.  If the
319      *              Value is an allocated object, it is freed.  Otherwise, the
320      *              field is simply cleared.
321      *
322      ******************************************************************************/
323     
324     void
325     acpi_ns_detach_object (
326     	acpi_namespace_node     *node)
327     {
328     	acpi_operand_object     *obj_desc;
329     
330     
331     	FUNCTION_TRACE ("Ns_detach_object");
332     
333     
334     	obj_desc = node->object;
335     	if (!obj_desc) {
336     		return_VOID;
337     	}
338     
339     	/* Clear the entry in all cases */
340     
341     	node->object = NULL;
342     
343     	/* Found a valid value */
344     
345     	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Object=%p Value=%p Name %4.4s\n",
346     		node, obj_desc, &node->name));
347     
348     	/*
349     	 * Not every value is an object allocated via ACPI_MEM_CALLOCATE,
350     	 * - must check
351     	 */
352     	if (!acpi_tb_system_table_pointer (obj_desc)) {
353     		/* Attempt to delete the object (and all subobjects) */
354     
355     		acpi_ut_remove_reference (obj_desc);
356     	}
357     
358     	return_VOID;
359     }
360     
361     
362     /*******************************************************************************
363      *
364      * FUNCTION:    Acpi_ns_get_attached_object
365      *
366      * PARAMETERS:  Node             - Parent Node to be examined
367      *
368      * RETURN:      Current value of the object field from the Node whose
369      *              handle is passed
370      *
371      ******************************************************************************/
372     
373     void *
374     acpi_ns_get_attached_object (
375     	acpi_namespace_node     *node)
376     {
377     	FUNCTION_TRACE_PTR ("Ns_get_attached_object", node);
378     
379     
380     	if (!node) {
381     		/* handle invalid */
382     
383     		ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Null Node ptr\n"));
384     		return_PTR (NULL);
385     	}
386     
387     	return_PTR (node->object);
388     }
389     
390     
391