Merge branch 'origin'
[pandora-kernel.git] / drivers / acpi / namespace / nsobject.c
1 /*******************************************************************************
2  *
3  * Module Name: nsobject - Utilities for objects attached to namespace
4  *                         table entries
5  *
6  ******************************************************************************/
7
8 /*
9  * Copyright (C) 2000 - 2006, R. Byron Moore
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44
45 #include <acpi/acpi.h>
46 #include <acpi/acnamesp.h>
47
48 #define _COMPONENT          ACPI_NAMESPACE
49 ACPI_MODULE_NAME("nsobject")
50
51 /*******************************************************************************
52  *
53  * FUNCTION:    acpi_ns_attach_object
54  *
55  * PARAMETERS:  Node                - Parent Node
56  *              Object              - Object to be attached
57  *              Type                - Type of object, or ACPI_TYPE_ANY if not
58  *                                    known
59  *
60  * RETURN:      Status
61  *
62  * DESCRIPTION: Record the given object as the value associated with the
63  *              name whose acpi_handle is passed.  If Object is NULL
64  *              and Type is ACPI_TYPE_ANY, set the name as having no value.
65  *              Note: Future may require that the Node->Flags field be passed
66  *              as a parameter.
67  *
68  * MUTEX:       Assumes namespace is locked
69  *
70  ******************************************************************************/
71 acpi_status
72 acpi_ns_attach_object(struct acpi_namespace_node *node,
73                       union acpi_operand_object *object, acpi_object_type type)
74 {
75         union acpi_operand_object *obj_desc;
76         union acpi_operand_object *last_obj_desc;
77         acpi_object_type object_type = ACPI_TYPE_ANY;
78
79         ACPI_FUNCTION_TRACE("ns_attach_object");
80
81         /*
82          * Parameter validation
83          */
84         if (!node) {
85                 /* Invalid handle */
86
87                 ACPI_ERROR((AE_INFO, "Null named_obj handle"));
88                 return_ACPI_STATUS(AE_BAD_PARAMETER);
89         }
90
91         if (!object && (ACPI_TYPE_ANY != type)) {
92                 /* Null object */
93
94                 ACPI_ERROR((AE_INFO,
95                             "Null object, but type not ACPI_TYPE_ANY"));
96                 return_ACPI_STATUS(AE_BAD_PARAMETER);
97         }
98
99         if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
100                 /* Not a name handle */
101
102                 ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
103                             node, acpi_ut_get_descriptor_name(node)));
104                 return_ACPI_STATUS(AE_BAD_PARAMETER);
105         }
106
107         /* Check if this object is already attached */
108
109         if (node->object == object) {
110                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
111                                   "Obj %p already installed in name_obj %p\n",
112                                   object, node));
113
114                 return_ACPI_STATUS(AE_OK);
115         }
116
117         /* If null object, we will just install it */
118
119         if (!object) {
120                 obj_desc = NULL;
121                 object_type = ACPI_TYPE_ANY;
122         }
123
124         /*
125          * If the source object is a namespace Node with an attached object,
126          * we will use that (attached) object
127          */
128         else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) &&
129                  ((struct acpi_namespace_node *)object)->object) {
130                 /*
131                  * Value passed is a name handle and that name has a
132                  * non-null value.  Use that name's value and type.
133                  */
134                 obj_desc = ((struct acpi_namespace_node *)object)->object;
135                 object_type = ((struct acpi_namespace_node *)object)->type;
136         }
137
138         /*
139          * Otherwise, we will use the parameter object, but we must type
140          * it first
141          */
142         else {
143                 obj_desc = (union acpi_operand_object *)object;
144
145                 /* Use the given type */
146
147                 object_type = type;
148         }
149
150         ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
151                           obj_desc, node, acpi_ut_get_node_name(node)));
152
153         /* Detach an existing attached object if present */
154
155         if (node->object) {
156                 acpi_ns_detach_object(node);
157         }
158
159         if (obj_desc) {
160                 /*
161                  * Must increment the new value's reference count
162                  * (if it is an internal object)
163                  */
164                 acpi_ut_add_reference(obj_desc);
165
166                 /*
167                  * Handle objects with multiple descriptors - walk
168                  * to the end of the descriptor list
169                  */
170                 last_obj_desc = obj_desc;
171                 while (last_obj_desc->common.next_object) {
172                         last_obj_desc = last_obj_desc->common.next_object;
173                 }
174
175                 /* Install the object at the front of the object list */
176
177                 last_obj_desc->common.next_object = node->object;
178         }
179
180         node->type = (u8) object_type;
181         node->object = obj_desc;
182
183         return_ACPI_STATUS(AE_OK);
184 }
185
186 /*******************************************************************************
187  *
188  * FUNCTION:    acpi_ns_detach_object
189  *
190  * PARAMETERS:  Node           - A Namespace node whose object will be detached
191  *
192  * RETURN:      None.
193  *
194  * DESCRIPTION: Detach/delete an object associated with a namespace node.
195  *              if the object is an allocated object, it is freed.
196  *              Otherwise, the field is simply cleared.
197  *
198  ******************************************************************************/
199
200 void acpi_ns_detach_object(struct acpi_namespace_node *node)
201 {
202         union acpi_operand_object *obj_desc;
203
204         ACPI_FUNCTION_TRACE("ns_detach_object");
205
206         obj_desc = node->object;
207
208         if (!obj_desc ||
209             (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA)) {
210                 return_VOID;
211         }
212
213         /* Clear the entry in all cases */
214
215         node->object = NULL;
216         if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) {
217                 node->object = obj_desc->common.next_object;
218                 if (node->object &&
219                     (ACPI_GET_OBJECT_TYPE(node->object) !=
220                      ACPI_TYPE_LOCAL_DATA)) {
221                         node->object = node->object->common.next_object;
222                 }
223         }
224
225         /* Reset the node type to untyped */
226
227         node->type = ACPI_TYPE_ANY;
228
229         ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
230                           node, acpi_ut_get_node_name(node), obj_desc));
231
232         /* Remove one reference on the object (and all subobjects) */
233
234         acpi_ut_remove_reference(obj_desc);
235         return_VOID;
236 }
237
238 /*******************************************************************************
239  *
240  * FUNCTION:    acpi_ns_get_attached_object
241  *
242  * PARAMETERS:  Node             - Namespace node
243  *
244  * RETURN:      Current value of the object field from the Node whose
245  *              handle is passed
246  *
247  * DESCRIPTION: Obtain the object attached to a namespace node.
248  *
249  ******************************************************************************/
250
251 union acpi_operand_object *acpi_ns_get_attached_object(struct
252                                                        acpi_namespace_node
253                                                        *node)
254 {
255         ACPI_FUNCTION_TRACE_PTR("ns_get_attached_object", node);
256
257         if (!node) {
258                 ACPI_WARNING((AE_INFO, "Null Node ptr"));
259                 return_PTR(NULL);
260         }
261
262         if (!node->object ||
263             ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND)
264              && (ACPI_GET_DESCRIPTOR_TYPE(node->object) !=
265                  ACPI_DESC_TYPE_NAMED))
266             || (ACPI_GET_OBJECT_TYPE(node->object) == ACPI_TYPE_LOCAL_DATA)) {
267                 return_PTR(NULL);
268         }
269
270         return_PTR(node->object);
271 }
272
273 /*******************************************************************************
274  *
275  * FUNCTION:    acpi_ns_get_secondary_object
276  *
277  * PARAMETERS:  Node             - Namespace node
278  *
279  * RETURN:      Current value of the object field from the Node whose
280  *              handle is passed.
281  *
282  * DESCRIPTION: Obtain a secondary object associated with a namespace node.
283  *
284  ******************************************************************************/
285
286 union acpi_operand_object *acpi_ns_get_secondary_object(union
287                                                         acpi_operand_object
288                                                         *obj_desc)
289 {
290         ACPI_FUNCTION_TRACE_PTR("ns_get_secondary_object", obj_desc);
291
292         if ((!obj_desc) ||
293             (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) ||
294             (!obj_desc->common.next_object) ||
295             (ACPI_GET_OBJECT_TYPE(obj_desc->common.next_object) ==
296              ACPI_TYPE_LOCAL_DATA)) {
297                 return_PTR(NULL);
298         }
299
300         return_PTR(obj_desc->common.next_object);
301 }
302
303 /*******************************************************************************
304  *
305  * FUNCTION:    acpi_ns_attach_data
306  *
307  * PARAMETERS:  Node            - Namespace node
308  *              Handler         - Handler to be associated with the data
309  *              Data            - Data to be attached
310  *
311  * RETURN:      Status
312  *
313  * DESCRIPTION: Low-level attach data.  Create and attach a Data object.
314  *
315  ******************************************************************************/
316
317 acpi_status
318 acpi_ns_attach_data(struct acpi_namespace_node *node,
319                     acpi_object_handler handler, void *data)
320 {
321         union acpi_operand_object *prev_obj_desc;
322         union acpi_operand_object *obj_desc;
323         union acpi_operand_object *data_desc;
324
325         /* We only allow one attachment per handler */
326
327         prev_obj_desc = NULL;
328         obj_desc = node->object;
329         while (obj_desc) {
330                 if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
331                     (obj_desc->data.handler == handler)) {
332                         return (AE_ALREADY_EXISTS);
333                 }
334
335                 prev_obj_desc = obj_desc;
336                 obj_desc = obj_desc->common.next_object;
337         }
338
339         /* Create an internal object for the data */
340
341         data_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_DATA);
342         if (!data_desc) {
343                 return (AE_NO_MEMORY);
344         }
345
346         data_desc->data.handler = handler;
347         data_desc->data.pointer = data;
348
349         /* Install the data object */
350
351         if (prev_obj_desc) {
352                 prev_obj_desc->common.next_object = data_desc;
353         } else {
354                 node->object = data_desc;
355         }
356
357         return (AE_OK);
358 }
359
360 /*******************************************************************************
361  *
362  * FUNCTION:    acpi_ns_detach_data
363  *
364  * PARAMETERS:  Node            - Namespace node
365  *              Handler         - Handler associated with the data
366  *
367  * RETURN:      Status
368  *
369  * DESCRIPTION: Low-level detach data.  Delete the data node, but the caller
370  *              is responsible for the actual data.
371  *
372  ******************************************************************************/
373
374 acpi_status
375 acpi_ns_detach_data(struct acpi_namespace_node * node,
376                     acpi_object_handler handler)
377 {
378         union acpi_operand_object *obj_desc;
379         union acpi_operand_object *prev_obj_desc;
380
381         prev_obj_desc = NULL;
382         obj_desc = node->object;
383         while (obj_desc) {
384                 if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
385                     (obj_desc->data.handler == handler)) {
386                         if (prev_obj_desc) {
387                                 prev_obj_desc->common.next_object =
388                                     obj_desc->common.next_object;
389                         } else {
390                                 node->object = obj_desc->common.next_object;
391                         }
392
393                         acpi_ut_remove_reference(obj_desc);
394                         return (AE_OK);
395                 }
396
397                 prev_obj_desc = obj_desc;
398                 obj_desc = obj_desc->common.next_object;
399         }
400
401         return (AE_NOT_FOUND);
402 }
403
404 /*******************************************************************************
405  *
406  * FUNCTION:    acpi_ns_get_attached_data
407  *
408  * PARAMETERS:  Node            - Namespace node
409  *              Handler         - Handler associated with the data
410  *              Data            - Where the data is returned
411  *
412  * RETURN:      Status
413  *
414  * DESCRIPTION: Low level interface to obtain data previously associated with
415  *              a namespace node.
416  *
417  ******************************************************************************/
418
419 acpi_status
420 acpi_ns_get_attached_data(struct acpi_namespace_node * node,
421                           acpi_object_handler handler, void **data)
422 {
423         union acpi_operand_object *obj_desc;
424
425         obj_desc = node->object;
426         while (obj_desc) {
427                 if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
428                     (obj_desc->data.handler == handler)) {
429                         *data = obj_desc->data.pointer;
430                         return (AE_OK);
431                 }
432
433                 obj_desc = obj_desc->common.next_object;
434         }
435
436         return (AE_NOT_FOUND);
437 }