:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / utils / cmdelete.c
1 /*******************************************************************************
2  *
3  * Module Name: cmdelete - object deletion and reference count utilities
4  *              $Revision$
5  *
6  ******************************************************************************/
7
8 /*
9  *  Copyright (C) 2000, 2001 R. Byron Moore
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26
27 #include "acpi.h"
28 #include "acinterp.h"
29 #include "acnamesp.h"
30 #include "actables.h"
31 #include "acparser.h"
32
33 #define _COMPONENT          ACPI_UTILITIES
34          MODULE_NAME         ("cmdelete")
35
36
37 /*******************************************************************************
38  *
39  * FUNCTION:    Acpi_cm_delete_internal_obj
40  *
41  * PARAMETERS:  *Object        - Pointer to the list to be deleted
42  *
43  * RETURN:      None
44  *
45  * DESCRIPTION: Low level object deletion, after reference counts have been
46  *              updated (All reference counts, including sub-objects!)
47  *
48  ******************************************************************************/
49
50 void
51 acpi_cm_delete_internal_obj (
52         ACPI_OPERAND_OBJECT     *object)
53 {
54         void                    *obj_pointer = NULL;
55         ACPI_OPERAND_OBJECT     *handler_desc;
56
57
58         if (!object) {
59                 return;
60         }
61
62         /*
63          * Must delete or free any pointers within the object that are not
64          * actual ACPI objects (for example, a raw buffer pointer).
65          */
66
67         switch (object->common.type) {
68
69         case ACPI_TYPE_STRING:
70
71                 /* Free the actual string buffer */
72
73                 obj_pointer = object->string.pointer;
74                 break;
75
76
77         case ACPI_TYPE_BUFFER:
78
79                 /* Free the actual buffer */
80
81                 obj_pointer = object->buffer.pointer;
82                 break;
83
84
85         case ACPI_TYPE_PACKAGE:
86
87                 /*
88                  * Elements of the package are not handled here, they are deleted
89                  * separately
90                  */
91
92                 /* Free the (variable length) element pointer array */
93
94                 obj_pointer = object->package.elements;
95                 break;
96
97
98         case ACPI_TYPE_MUTEX:
99
100                 acpi_aml_unlink_mutex (object);
101                 acpi_os_delete_semaphore (object->mutex.semaphore);
102                 break;
103
104
105         case ACPI_TYPE_EVENT:
106
107                 acpi_os_delete_semaphore (object->event.semaphore);
108                 object->event.semaphore = NULL;
109                 break;
110
111
112         case ACPI_TYPE_METHOD:
113
114                 /* Delete the method semaphore if it exists */
115
116                 if (object->method.semaphore) {
117                         acpi_os_delete_semaphore (object->method.semaphore);
118                         object->method.semaphore = NULL;
119                 }
120
121                 break;
122
123
124         case ACPI_TYPE_REGION:
125
126
127                 if (object->region.extra) {
128                         /*
129                          * Free the Region_context if and only if the handler is one of the
130                          * default handlers -- and therefore, we created the context object
131                          * locally, it was not created by an external caller.
132                          */
133                         handler_desc = object->region.addr_handler;
134                         if ((handler_desc) &&
135                                 (handler_desc->addr_handler.hflags == ADDR_HANDLER_DEFAULT_INSTALLED)) {
136                                 obj_pointer = object->region.extra->extra.region_context;
137                         }
138
139                         /* Now we can free the Extra object */
140
141                         acpi_cm_delete_object_desc (object->region.extra);
142                 }
143                 break;
144
145
146         case ACPI_TYPE_FIELD_UNIT:
147
148                 if (object->field_unit.extra) {
149                         acpi_cm_delete_object_desc (object->field_unit.extra);
150                 }
151                 break;
152
153         default:
154                 break;
155         }
156
157
158         /*
159          * Delete any allocated memory found above
160          */
161
162         if (obj_pointer) {
163                 if (!acpi_tb_system_table_pointer (obj_pointer)) {
164                         acpi_cm_free (obj_pointer);
165                 }
166         }
167
168
169         /* Only delete the object if it was dynamically allocated */
170
171
172         if (!(object->common.flags & AOPOBJ_STATIC_ALLOCATION)) {
173                 acpi_cm_delete_object_desc (object);
174
175         }
176
177         return;
178 }
179
180
181 /*******************************************************************************
182  *
183  * FUNCTION:    Acpi_cm_delete_internal_object_list
184  *
185  * PARAMETERS:  *Obj_list       - Pointer to the list to be deleted
186  *
187  * RETURN:      Status          - the status of the call
188  *
189  * DESCRIPTION: This function deletes an internal object list, including both
190  *              simple objects and package objects
191  *
192  ******************************************************************************/
193
194 ACPI_STATUS
195 acpi_cm_delete_internal_object_list (
196         ACPI_OPERAND_OBJECT     **obj_list)
197 {
198         ACPI_OPERAND_OBJECT     **internal_obj;
199
200
201         /* Walk the null-terminated internal list */
202
203         for (internal_obj = obj_list; *internal_obj; internal_obj++) {
204                 /*
205                  * Check for a package
206                  * Simple objects are simply stored in the array and do not
207                  * need to be deleted separately.
208                  */
209
210                 if (IS_THIS_OBJECT_TYPE ((*internal_obj), ACPI_TYPE_PACKAGE)) {
211                         /* Delete the package */
212
213                         /*
214                          * TBD: [Investigate] This might not be the right thing to do,
215                          * depending on how the internal package object was allocated!!!
216                          */
217                         acpi_cm_delete_internal_obj (*internal_obj);
218                 }
219
220         }
221
222         /* Free the combined parameter pointer list and object array */
223
224         acpi_cm_free (obj_list);
225
226         return (AE_OK);
227 }
228
229
230 /*******************************************************************************
231  *
232  * FUNCTION:    Acpi_cm_update_ref_count
233  *
234  * PARAMETERS:  *Object         - Object whose ref count is to be updated
235  *              Action          - What to do
236  *
237  * RETURN:      New ref count
238  *
239  * DESCRIPTION: Modify the ref count and return it.
240  *
241  ******************************************************************************/
242
243 static void
244 acpi_cm_update_ref_count (
245         ACPI_OPERAND_OBJECT     *object,
246         u32                     action)
247 {
248         u16                     count;
249         u16                     new_count;
250
251
252         if (!object) {
253                 return;
254         }
255
256
257         count = object->common.reference_count;
258         new_count = count;
259
260         /*
261          * Reference count action (increment, decrement, or force delete)
262          */
263
264         switch (action) {
265
266         case REF_INCREMENT:
267
268                 new_count++;
269                 object->common.reference_count = new_count;
270
271                 break;
272
273
274         case REF_DECREMENT:
275
276                 if (count < 1) {
277                         new_count = 0;
278                 }
279
280                 else {
281                         new_count--;
282
283                 }
284
285
286                 object->common.reference_count = new_count;
287                 if (new_count == 0) {
288                         acpi_cm_delete_internal_obj (object);
289                 }
290
291                 break;
292
293
294         case REF_FORCE_DELETE:
295
296                 new_count = 0;
297                 object->common.reference_count = new_count;
298                 acpi_cm_delete_internal_obj (object);
299                 break;
300
301
302         default:
303
304                 break;
305         }
306
307
308         /*
309          * Sanity check the reference count, for debug purposes only.
310          * (A deleted object will have a huge reference count)
311          */
312
313
314         return;
315 }
316
317
318 /*******************************************************************************
319  *
320  * FUNCTION:    Acpi_cm_update_object_reference
321  *
322  * PARAMETERS:  *Object             - Increment ref count for this object
323  *                                    and all sub-objects
324  *              Action              - Either REF_INCREMENT or REF_DECREMENT or
325  *                                    REF_FORCE_DELETE
326  *
327  * RETURN:      Status
328  *
329  * DESCRIPTION: Increment the object reference count
330  *
331  * Object references are incremented when:
332  * 1) An object is attached to a Node (namespace object)
333  * 2) An object is copied (all subobjects must be incremented)
334  *
335  * Object references are decremented when:
336  * 1) An object is detached from an Node
337  *
338  ******************************************************************************/
339
340 ACPI_STATUS
341 acpi_cm_update_object_reference (
342         ACPI_OPERAND_OBJECT     *object,
343         u16                     action)
344 {
345         ACPI_STATUS             status;
346         u32                     i;
347         ACPI_OPERAND_OBJECT     *next;
348         ACPI_OPERAND_OBJECT     *new;
349         ACPI_GENERIC_STATE       *state_list = NULL;
350         ACPI_GENERIC_STATE       *state;
351
352
353         /* Ignore a null object ptr */
354
355         if (!object) {
356                 return (AE_OK);
357         }
358
359
360         /*
361          * Make sure that this isn't a namespace handle or an AML pointer
362          */
363
364         if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED)) {
365                 return (AE_OK);
366         }
367
368         if (acpi_tb_system_table_pointer (object)) {
369                 return (AE_OK);
370         }
371
372
373         state = acpi_cm_create_update_state (object, action);
374
375         while (state) {
376
377                 object = state->update.object;
378                 action = state->update.value;
379                 acpi_cm_delete_generic_state (state);
380
381                 /*
382                  * All sub-objects must have their reference count incremented also.
383                  * Different object types have different subobjects.
384                  */
385                 switch (object->common.type) {
386
387                 case ACPI_TYPE_DEVICE:
388
389                         status = acpi_cm_create_update_state_and_push (object->device.addr_handler,
390                                            action, &state_list);
391                         if (ACPI_FAILURE (status)) {
392                                 return (status);
393                         }
394
395                         acpi_cm_update_ref_count (object->device.sys_handler, action);
396                         acpi_cm_update_ref_count (object->device.drv_handler, action);
397                         break;
398
399
400                 case INTERNAL_TYPE_ADDRESS_HANDLER:
401
402                         /* Must walk list of address handlers */
403
404                         next = object->addr_handler.next;
405                         while (next) {
406                                 new = next->addr_handler.next;
407                                 acpi_cm_update_ref_count (next, action);
408
409                                 next = new;
410                         }
411                         break;
412
413
414                 case ACPI_TYPE_PACKAGE:
415
416                         /*
417                          * We must update all the sub-objects of the package
418                          * (Each of whom may have their own sub-objects, etc.
419                          */
420                         for (i = 0; i < object->package.count; i++) {
421                                 /*
422                                  * Push each element onto the stack for later processing.
423                                  * Note: There can be null elements within the package,
424                                  * these are simply ignored
425                                  */
426
427                                 status = acpi_cm_create_update_state_and_push (
428                                                  object->package.elements[i], action, &state_list);
429                                 if (ACPI_FAILURE (status)) {
430                                         return (status);
431                                 }
432                         }
433                         break;
434
435
436                 case ACPI_TYPE_FIELD_UNIT:
437
438                         status = acpi_cm_create_update_state_and_push (
439                                          object->field_unit.container, action, &state_list);
440
441                         if (ACPI_FAILURE (status)) {
442                                 return (status);
443                         }
444                         break;
445
446
447                 case INTERNAL_TYPE_DEF_FIELD:
448
449                         status = acpi_cm_create_update_state_and_push (
450                                          object->field.container, action, &state_list);
451                         if (ACPI_FAILURE (status)) {
452                                 return (status);
453                         }
454                    break;
455
456
457                 case INTERNAL_TYPE_BANK_FIELD:
458
459                         status = acpi_cm_create_update_state_and_push (
460                                          object->bank_field.bank_select, action, &state_list);
461                         if (ACPI_FAILURE (status)) {
462                                 return (status);
463                         }
464
465                         status = acpi_cm_create_update_state_and_push (
466                                          object->bank_field.container, action, &state_list);
467                         if (ACPI_FAILURE (status)) {
468                                 return (status);
469                         }
470                         break;
471
472
473                 case ACPI_TYPE_REGION:
474
475         /* TBD: [Investigate]
476                         Acpi_cm_update_ref_count (Object->Region.Addr_handler, Action);
477         */
478 /*
479                         Status =
480                                 Acpi_cm_create_update_state_and_push (Object->Region.Addr_handler,
481                                                    Action, &State_list);
482                         if (ACPI_FAILURE (Status))
483                         {
484                                 return (Status);
485                         }
486 */
487                         break;
488
489
490                 case INTERNAL_TYPE_REFERENCE:
491
492                         break;
493                 }
494
495
496                 /*
497                  * Now we can update the count in the main object.  This can only
498                  * happen after we update the sub-objects in case this causes the
499                  * main object to be deleted.
500                  */
501
502                 acpi_cm_update_ref_count (object, action);
503
504
505                 /* Move on to the next object to be updated */
506
507                 state = acpi_cm_pop_generic_state (&state_list);
508         }
509
510
511         return (AE_OK);
512 }
513
514
515 /*******************************************************************************
516  *
517  * FUNCTION:    Acpi_cm_add_reference
518  *
519  * PARAMETERS:  *Object        - Object whose reference count is to be
520  *                                  incremented
521  *
522  * RETURN:      None
523  *
524  * DESCRIPTION: Add one reference to an ACPI object
525  *
526  ******************************************************************************/
527
528 void
529 acpi_cm_add_reference (
530         ACPI_OPERAND_OBJECT     *object)
531 {
532
533
534         /*
535          * Ensure that we have a valid object
536          */
537
538         if (!acpi_cm_valid_internal_object (object)) {
539                 return;
540         }
541
542         /*
543          * We have a valid ACPI internal object, now increment the reference count
544          */
545
546         acpi_cm_update_object_reference (object, REF_INCREMENT);
547
548         return;
549 }
550
551
552 /*******************************************************************************
553  *
554  * FUNCTION:    Acpi_cm_remove_reference
555  *
556  * PARAMETERS:  *Object        - Object whose ref count will be decremented
557  *
558  * RETURN:      None
559  *
560  * DESCRIPTION: Decrement the reference count of an ACPI internal object
561  *
562  ******************************************************************************/
563
564 void
565 acpi_cm_remove_reference (
566         ACPI_OPERAND_OBJECT     *object)
567 {
568
569
570         /*
571          * Ensure that we have a valid object
572          */
573
574         if (!acpi_cm_valid_internal_object (object)) {
575                 return;
576         }
577
578         /*
579          * Decrement the reference count, and only actually delete the object
580          * if the reference count becomes 0.  (Must also decrement the ref count
581          * of all subobjects!)
582          */
583
584         acpi_cm_update_object_reference (object, REF_DECREMENT);
585
586         return;
587 }
588
589