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