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