merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / drivers / bus / acpi / namespace / nsobject.c
1 /*******************************************************************************
2 *
3 * Module Name: nsobject - Utilities for objects attached to namespace
4 * table entries
5 * $Revision: 1.1 $
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 OBJECT_TYPE_INTERNAL type)
61 {
62 ACPI_OPERAND_OBJECT *obj_desc;
63 ACPI_OPERAND_OBJECT *previous_obj_desc;
64 OBJECT_TYPE_INTERNAL obj_type = ACPI_TYPE_ANY;
65 u8 flags;
66 u16 opcode;
67
68
69 /*
70 * Parameter validation
71 */
72
73 if (!acpi_gbl_root_node) {
74 /* Name space not initialized */
75
76 REPORT_ERROR (("Ns_attach_object: Namespace not initialized\n"));
77 return (AE_NO_NAMESPACE);
78 }
79
80 if (!node) {
81 /* Invalid handle */
82
83 REPORT_ERROR (("Ns_attach_object: Null Named_obj handle\n"));
84 return (AE_BAD_PARAMETER);
85 }
86
87 if (!object && (ACPI_TYPE_ANY != type)) {
88 /* Null object */
89
90 REPORT_ERROR (("Ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n"));
91 return (AE_BAD_PARAMETER);
92 }
93
94 if (!VALID_DESCRIPTOR_TYPE (node, ACPI_DESC_TYPE_NAMED)) {
95 /* Not a name handle */
96
97 REPORT_ERROR (("Ns_attach_object: Invalid handle\n"));
98 return (AE_BAD_PARAMETER);
99 }
100
101 /* Check if this object is already attached */
102
103 if (node->object == object) {
104 return (AE_OK);
105 }
106
107
108 /* Get the current flags field of the Node */
109
110 flags = node->flags;
111 flags &= ~ANOBJ_AML_ATTACHMENT;
112
113
114 /* If null object, we will just install it */
115
116 if (!object) {
117 obj_desc = NULL;
118 obj_type = ACPI_TYPE_ANY;
119 }
120
121 /*
122 * If the object is an Node with an attached object,
123 * we will use that (attached) object
124 */
125
126 else if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED) &&
127 ((ACPI_NAMESPACE_NODE *) object)->object) {
128 /*
129 * Value passed is a name handle and that name has a
130 * non-null value. Use that name's value and type.
131 */
132
133 obj_desc = ((ACPI_NAMESPACE_NODE *) object)->object;
134 obj_type = ((ACPI_NAMESPACE_NODE *) object)->type;
135
136 /*
137 * Copy appropriate flags
138 */
139
140 if (((ACPI_NAMESPACE_NODE *) object)->flags & ANOBJ_AML_ATTACHMENT) {
141 flags |= ANOBJ_AML_ATTACHMENT;
142 }
143 }
144
145
146 /*
147 * Otherwise, we will use the parameter object, but we must type
148 * it first
149 */
150
151 else {
152 obj_desc = (ACPI_OPERAND_OBJECT *) object;
153
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 /*
163 * Type is TYPE_Any, we must try to determinte the
164 * actual type of the object
165 */
166
167 /*
168 * Check if value points into the AML code
169 */
170 else if (acpi_tb_system_table_pointer (object)) {
171 /*
172 * Object points into the AML stream.
173 * Set a flag bit in the Node to indicate this
174 */
175
176 flags |= ANOBJ_AML_ATTACHMENT;
177
178 /*
179 * The next byte (perhaps the next two bytes)
180 * will be the AML opcode
181 */
182
183 MOVE_UNALIGNED16_TO_16 (&opcode, object);
184
185 /* Check for a recognized Opcode */
186
187 switch ((u8) opcode) {
188
189 case AML_OP_PREFIX:
190
191 if (opcode != AML_REVISION_OP) {
192 /*
193 * Op_prefix is unrecognized unless part
194 * of Revision_op
195 */
196
197 break;
198 }
199
200 /* Else fall through to set type as Number */
201
202
203 case AML_ZERO_OP: case AML_ONES_OP: case AML_ONE_OP:
204 case AML_BYTE_OP: case AML_WORD_OP: case AML_DWORD_OP:
205
206 obj_type = ACPI_TYPE_INTEGER;
207 break;
208
209
210 case AML_STRING_OP:
211
212 obj_type = ACPI_TYPE_STRING;
213 break;
214
215
216 case AML_BUFFER_OP:
217
218 obj_type = ACPI_TYPE_BUFFER;
219 break;
220
221
222 case AML_MUTEX_OP:
223
224 obj_type = ACPI_TYPE_MUTEX;
225 break;
226
227
228 case AML_PACKAGE_OP:
229
230 obj_type = ACPI_TYPE_PACKAGE;
231 break;
232
233
234 default:
235
236 return (AE_TYPE);
237 break;
238 }
239 }
240
241 else {
242 /*
243 * Cannot figure out the type -- set to Def_any which
244 * will print as an error in the name table dump
245 */
246
247
248 obj_type = INTERNAL_TYPE_DEF_ANY;
249 }
250 }
251
252
253 /*
254 * Must increment the new value's reference count
255 * (if it is an internal object)
256 */
257
258 acpi_cm_add_reference (obj_desc);
259
260 /* Save the existing object (if any) for deletion later */
261
262 previous_obj_desc = node->object;
263
264 /* Install the object and set the type, flags */
265
266 node->object = obj_desc;
267 node->type = (u8) obj_type;
268 node->flags |= flags;
269
270
271 /*
272 * Delete an existing attached object.
273 */
274
275 if (previous_obj_desc) {
276 /* One for the attach to the Node */
277
278 acpi_cm_remove_reference (previous_obj_desc);
279
280 /* Now delete */
281
282 acpi_cm_remove_reference (previous_obj_desc);
283 }
284
285 return (AE_OK);
286 }
287
288
289 /*******************************************************************************
290 *
291 * FUNCTION: Acpi_ns_detach_object
292 *
293 * PARAMETERS: Node - An object whose Value will be deleted
294 *
295 * RETURN: None.
296 *
297 * DESCRIPTION: Delete the Value associated with a namespace object. If the
298 * Value is an allocated object, it is freed. Otherwise, the
299 * field is simply cleared.
300 *
301 ******************************************************************************/
302
303 void
304 acpi_ns_detach_object (
305 ACPI_NAMESPACE_NODE *node)
306 {
307 ACPI_OPERAND_OBJECT *obj_desc;
308
309
310 obj_desc = node->object;
311 if (!obj_desc) {
312 return;
313 }
314
315 /* Clear the entry in all cases */
316
317 node->object = NULL;
318
319 /* Found a valid value */
320
321 /*
322 * Not every value is an object allocated via Acpi_cm_callocate,
323 * - must check
324 */
325
326 if (!acpi_tb_system_table_pointer (obj_desc)) {
327 /* Attempt to delete the object (and all subobjects) */
328
329 acpi_cm_remove_reference (obj_desc);
330 }
331
332 return;
333 }
334
335
336 /*******************************************************************************
337 *
338 * FUNCTION: Acpi_ns_get_attached_object
339 *
340 * PARAMETERS: Handle - Parent Node to be examined
341 *
342 * RETURN: Current value of the object field from the Node whose
343 * handle is passed
344 *
345 ******************************************************************************/
346
347 void *
348 acpi_ns_get_attached_object (
349 ACPI_HANDLE handle)
350 {
351
352 if (!handle) {
353 /* handle invalid */
354
355 return (NULL);
356 }
357
358 return (((ACPI_NAMESPACE_NODE *) handle)->object);
359 }
360
361