remove whitespace from end of lines
[reactos.git] / reactos / drivers / bus / acpi / ospm / busmgr / bm.c
1 /******************************************************************************
2 *
3 * Module Name: bm.c
4 * $Revision: 1.1 $
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000, 2001 Andrew Grover
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 "bm.h"
29
30
31 #define _COMPONENT ACPI_BUS_MANAGER
32 MODULE_NAME ("bm")
33
34
35 /****************************************************************************
36 * Globals
37 ****************************************************************************/
38
39 extern FADT_DESCRIPTOR_REV2 acpi_fadt;
40 /* TODO: Make dynamically sizeable. */
41 static BM_NODE_LIST node_list;
42
43
44 /****************************************************************************
45 * Internal Functions
46 ****************************************************************************/
47
48 /****************************************************************************
49 *
50 * FUNCTION: bm_print
51 *
52 * PARAMETERS: <TBD>
53 *
54 * RETURN: <TBD>
55 *
56 * DESCRIPTION: <TBD>
57 *
58 ****************************************************************************/
59
60 void
61 bm_print (
62 BM_NODE *node,
63 u32 flags)
64 {
65 ACPI_BUFFER buffer;
66 BM_DEVICE *device = NULL;
67 char *type_string = NULL;
68
69 if (!node) {
70 return;
71 }
72
73 device = &(node->device);
74
75 if (flags & BM_PRINT_PRESENT) {
76 if (!BM_DEVICE_PRESENT(device)) {
77 return;
78 }
79 }
80
81 buffer.length = 256;
82 buffer.pointer = acpi_os_callocate(buffer.length);
83 if (!buffer.pointer) {
84 return;
85 }
86
87 acpi_get_name(device->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
88
89 switch(device->id.type) {
90 case BM_TYPE_SYSTEM:
91 type_string = "System";
92 break;
93 case BM_TYPE_SCOPE:
94 type_string = "Scope";
95 break;
96 case BM_TYPE_PROCESSOR:
97 type_string = "Processor";
98 break;
99 case BM_TYPE_THERMAL_ZONE:
100 type_string = "ThermalZone";
101 break;
102 case BM_TYPE_POWER_RESOURCE:
103 type_string = "PowerResource";
104 break;
105 case BM_TYPE_FIXED_BUTTON:
106 type_string = "Button";
107 break;
108 case BM_TYPE_DEVICE:
109 type_string = "Device";
110 break;
111 default:
112 type_string = "Unknown";
113 break;
114 }
115
116 if (!(flags & BM_PRINT_GROUP)) {
117 DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n"));
118 }
119
120 DEBUG_PRINT(ACPI_INFO, ("%s[0x%02x] hid[%s] %s\n", type_string, device->handle, device->id.hid, buffer.pointer));
121 DEBUG_PRINT(ACPI_INFO, (" acpi_handle[0x%08x] flags[0x%02x] status[0x%02x]\n", device->acpi_handle, device->flags, device->status));
122
123 if (flags & BM_PRINT_IDENTIFICATION) {
124 DEBUG_PRINT(ACPI_INFO, (" identification: uid[%s] adr[0x%08x]\n", device->id.uid, device->id.adr));
125 }
126
127 if (flags & BM_PRINT_LINKAGE) {
128 DEBUG_PRINT(ACPI_INFO, (" linkage: this[%p] parent[%p] next[%p]\n", node, node->parent, node->next));
129 DEBUG_PRINT(ACPI_INFO, (" scope.head[%p] scope.tail[%p]\n", node->scope.head, node->scope.tail));
130 }
131
132 if (flags & BM_PRINT_POWER) {
133 DEBUG_PRINT(ACPI_INFO, (" power: state[D%d] flags[0x%08X]\n", device->power.state, device->power.flags));
134 DEBUG_PRINT(ACPI_INFO, (" S0[0x%02x] S1[0x%02x] S2[0x%02x]\n", device->power.dx_supported[0], device->power.dx_supported[1], device->power.dx_supported[2]));
135 DEBUG_PRINT(ACPI_INFO, (" S3[0x%02x] S4[0x%02x] S5[0x%02x]\n", device->power.dx_supported[3], device->power.dx_supported[4], device->power.dx_supported[5]));
136 }
137
138 if (!(flags & BM_PRINT_GROUP)) {
139 DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n"));
140 }
141
142 acpi_os_free(buffer.pointer);
143
144 return;
145 }
146
147
148 /****************************************************************************
149 *
150 * FUNCTION: bm_print_hierarchy
151 *
152 * PARAMETERS: <TBD>
153 *
154 * RETURN: <TBD>
155 *
156 * DESCRIPTION: <TBD>
157 *
158 ****************************************************************************/
159
160 void
161 bm_print_hierarchy (void)
162 {
163 u32 i = 0;
164
165 FUNCTION_TRACE("bm_print_hierarchy");
166
167 DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n"));
168
169 for (i = 0; i < node_list.count; i++) {
170 bm_print(node_list.nodes[i], BM_PRINT_GROUP | BM_PRINT_PRESENT);
171 }
172
173 DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n"));
174
175 return_VOID;
176 }
177
178
179 /****************************************************************************
180 *
181 * FUNCTION: bm_get_status
182 *
183 * PARAMETERS: <TBD>
184 *
185 * RETURN: <TBD>
186 *
187 * DESCRIPTION: <TBD>
188 *
189 ****************************************************************************/
190
191 ACPI_STATUS
192 bm_get_status (
193 BM_DEVICE *device)
194 {
195 ACPI_STATUS status = AE_OK;
196
197 if (!device) {
198 return AE_BAD_PARAMETER;
199 }
200
201 device->status = BM_STATUS_UNKNOWN;
202
203 /*
204 * Dynamic Status?
205 * ---------------
206 * If _STA isn't present we just return the default status.
207 */
208 if (!(device->flags & BM_FLAGS_DYNAMIC_STATUS)) {
209 device->status = BM_STATUS_DEFAULT;
210 return AE_OK;
211 }
212
213 /*
214 * Evaluate _STA:
215 * --------------
216 */
217 status = bm_evaluate_simple_integer(device->acpi_handle, "_STA",
218 &(device->status));
219
220 return status;
221 }
222
223
224 /****************************************************************************
225 *
226 * FUNCTION: bm_get_identification
227 *
228 * PARAMETERS: <TBD>
229 *
230 * RETURN: <TBD>
231 *
232 * DESCRIPTION: <TBD>
233 *
234 ****************************************************************************/
235
236 ACPI_STATUS
237 bm_get_identification (
238 BM_DEVICE *device)
239 {
240 ACPI_STATUS status = AE_OK;
241 ACPI_DEVICE_INFO info;
242
243 if (!device) {
244 return AE_BAD_PARAMETER;
245 }
246
247 if (!(device->flags & BM_FLAGS_IDENTIFIABLE)) {
248 return AE_OK;
249 }
250
251 MEMSET(&(device->id.uid), 0, sizeof(device->id.uid));
252 MEMSET(&(device->id.hid), 0, sizeof(device->id.hid));
253 device->id.adr = BM_ADDRESS_UNKNOWN;
254
255 /*
256 * Get Object Info:
257 * ----------------
258 * Evalute _UID, _HID, _ADR, and _STA...
259 */
260 status = acpi_get_object_info(device->acpi_handle, &info);
261 if (ACPI_FAILURE(status)) {
262 return status;
263 }
264
265 if (info.valid & ACPI_VALID_UID) {
266 MEMCPY((void*)device->id.uid, (void*)info.unique_id,
267 sizeof(BM_DEVICE_UID));
268 }
269
270 if (info.valid & ACPI_VALID_HID) {
271 MEMCPY((void*)device->id.hid, (void*)info.hardware_id,
272 sizeof(BM_DEVICE_HID));
273 }
274
275 if (info.valid & ACPI_VALID_ADR) {
276 device->id.adr = info.address;
277 }
278
279 return status;
280 }
281
282
283 /****************************************************************************
284 *
285 * FUNCTION: bm_get_flags
286 *
287 * PARAMETERS: <TBD>
288 *
289 * RETURN: <TBD>
290 *
291 * DESCRIPTION: <TBD>
292 *
293 ****************************************************************************/
294
295 ACPI_STATUS
296 bm_get_flags (
297 BM_DEVICE *device)
298 {
299 ACPI_HANDLE acpi_handle = NULL;
300
301 if (!device) {
302 return AE_BAD_PARAMETER;
303 }
304
305 device->flags = BM_FLAGS_UNKNOWN;
306
307 switch (device->id.type) {
308
309 case BM_TYPE_DEVICE:
310
311 /*
312 * Presence of _DCK indicates a docking station.
313 */
314 if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
315 "_DCK", &acpi_handle))) {
316 device->flags |= BM_FLAGS_DOCKING_STATION;
317 }
318
319 /*
320 * Presence of _EJD and/or _EJx indicates 'ejectable'.
321 * TODO: _EJx...
322 */
323 if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
324 "_EJD", &acpi_handle))) {
325 device->flags |= BM_FLAGS_EJECTABLE;
326 }
327
328 /*
329 * Presence of _PR0 or _PS0 indicates 'power manageable'.
330 */
331 if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
332 "_PR0", &acpi_handle)) ||
333 ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
334 "_PS0", &acpi_handle))) {
335 device->flags |= BM_FLAGS_POWER_CONTROL;
336 }
337
338 /*
339 * Presence of _CRS indicates 'configurable'.
340 */
341 if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
342 "_CRS", &acpi_handle))) {
343 device->flags |= BM_FLAGS_CONFIGURABLE;
344 }
345
346 /* Fall through to next case statement. */
347
348 case BM_TYPE_PROCESSOR:
349 case BM_TYPE_THERMAL_ZONE:
350 case BM_TYPE_POWER_RESOURCE:
351 /*
352 * Presence of _HID or _ADR indicates 'identifiable'.
353 */
354 if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
355 "_HID", &acpi_handle)) ||
356 ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
357 "_ADR", &acpi_handle))) {
358 device->flags |= BM_FLAGS_IDENTIFIABLE;
359 }
360
361 /*
362 * Presence of _STA indicates 'dynamic status'.
363 */
364 if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
365 "_STA", &acpi_handle))) {
366 device->flags |= BM_FLAGS_DYNAMIC_STATUS;
367 }
368
369 break;
370 }
371
372 return AE_OK;
373 }
374
375
376 /****************************************************************************
377 *
378 * FUNCTION: bm_add_namespace_device
379 *
380 * PARAMETERS: <TBD>
381 *
382 * RETURN: <TBD>
383 *
384 * DESCRIPTION: <TBD>
385 *
386 ****************************************************************************/
387
388 ACPI_STATUS
389 bm_add_namespace_device (
390 ACPI_HANDLE acpi_handle,
391 ACPI_OBJECT_TYPE acpi_type,
392 BM_NODE *parent,
393 BM_NODE **child)
394 {
395 ACPI_STATUS status = AE_OK;
396 BM_NODE *node = NULL;
397 BM_DEVICE *device = NULL;
398
399 FUNCTION_TRACE("bm_add_namespace_device");
400
401 if (!parent || !child) {
402 return_ACPI_STATUS(AE_BAD_PARAMETER);
403 }
404
405 if (node_list.count > BM_HANDLES_MAX) {
406 return_ACPI_STATUS(AE_NO_MEMORY);
407 }
408
409 (*child) = NULL;
410
411 /*
412 * Create Node:
413 * ------------
414 */
415 node = acpi_os_callocate(sizeof(BM_NODE));
416 if (!node) {
417 return_ACPI_STATUS(AE_NO_MEMORY);
418 }
419
420 node->parent = parent;
421 node->next = NULL;
422
423 device = &(node->device);
424
425 device->handle = node_list.count;
426 device->acpi_handle = acpi_handle;
427
428 /*
429 * Device Type:
430 * ------------
431 */
432 switch (acpi_type) {
433 case INTERNAL_TYPE_SCOPE:
434 device->id.type = BM_TYPE_SCOPE;
435 break;
436 case ACPI_TYPE_PROCESSOR:
437 device->id.type = BM_TYPE_PROCESSOR;
438 break;
439 case ACPI_TYPE_THERMAL:
440 device->id.type = BM_TYPE_THERMAL_ZONE;
441 break;
442 case ACPI_TYPE_POWER:
443 device->id.type = BM_TYPE_POWER_RESOURCE;
444 break;
445 case ACPI_TYPE_DEVICE:
446 device->id.type = BM_TYPE_DEVICE;
447 break;
448 }
449
450 /*
451 * Get Other Device Info:
452 * ----------------------
453 * But only if this device's parent is present (which implies
454 * this device MAY be present).
455 */
456 if (BM_NODE_PRESENT(node->parent)) {
457 /*
458 * Device Flags
459 */
460 status = bm_get_flags(device);
461 if (ACPI_FAILURE(status)) {
462 goto end;
463 }
464
465 /*
466 * Device Identification
467 */
468 status = bm_get_identification(device);
469 if (ACPI_FAILURE(status)) {
470 goto end;
471 }
472
473 /*
474 * Device Status
475 */
476 status = bm_get_status(device);
477 if (ACPI_FAILURE(status)) {
478 goto end;
479 }
480
481 /*
482 * Power Management:
483 * -----------------
484 * If this node doesn't provide direct power control
485 * then we inherit PM capabilities from its parent.
486 *
487 * TODO: Inherit!
488 */
489 if (device->flags & BM_FLAGS_POWER_CONTROL) {
490 status = bm_get_pm_capabilities(node);
491 if (ACPI_FAILURE(status)) {
492 goto end;
493 }
494 }
495 }
496
497 end:
498 if (ACPI_FAILURE(status)) {
499 acpi_os_free(node);
500 }
501 else {
502 /*
503 * Add to the node_list.
504 */
505 node_list.nodes[node_list.count++] = node;
506
507 /*
508 * Formulate Hierarchy:
509 * --------------------
510 * Arrange within the namespace by assigning the parent and
511 * adding to the parent device's list of children (scope).
512 */
513 if (!parent->scope.head) {
514 parent->scope.head = node;
515 }
516 else {
517 if (!parent->scope.tail) {
518 (parent->scope.head)->next = node;
519 }
520 else {
521 (parent->scope.tail)->next = node;
522 }
523 }
524 parent->scope.tail = node;
525
526 (*child) = node;
527 }
528
529 return_ACPI_STATUS(status);
530 }
531
532
533 /****************************************************************************
534 *
535 * FUNCTION: bm_enumerate_namespace
536 *
537 * PARAMETERS: <none>
538 *
539 * RETURN: <TBD>
540 *
541 * DESCRIPTION: <TBD>
542 *
543 ****************************************************************************/
544
545 ACPI_STATUS
546 bm_enumerate_namespace (void)
547 {
548 ACPI_STATUS status = AE_OK;
549 ACPI_HANDLE parent_handle = ACPI_ROOT_OBJECT;
550 ACPI_HANDLE child_handle = NULL;
551 BM_NODE *parent = NULL;
552 BM_NODE *child = NULL;
553 ACPI_OBJECT_TYPE acpi_type = 0;
554 u32 level = 1;
555
556 FUNCTION_TRACE("bm_enumerate_namespace");
557
558 parent = node_list.nodes[0];
559
560 /*
561 * Enumerate ACPI Namespace:
562 * -------------------------
563 * Parse through the ACPI namespace, identify all 'devices',
564 * and create a new entry for each in our collection.
565 */
566 while (level > 0) {
567
568 /*
569 * Get the next object at this level.
570 */
571 status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, child_handle, &child_handle);
572 if (ACPI_SUCCESS(status)) {
573
574 /*
575 * TODO: This is a hack to get around the problem
576 * identifying scope objects. Scopes
577 * somehow need to be uniquely identified.
578 */
579 status = acpi_get_type(child_handle, &acpi_type);
580 if (ACPI_SUCCESS(status) && (acpi_type == ACPI_TYPE_ANY)) {
581 status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL);
582 if (ACPI_SUCCESS(status)) {
583 acpi_type = INTERNAL_TYPE_SCOPE;
584 }
585 }
586
587 /*
588 * Device?
589 * -------
590 * If this object is a 'device', insert into the
591 * ACPI Bus Manager's local hierarchy and search
592 * the object's scope for any child devices (a
593 * depth-first search).
594 */
595 switch (acpi_type) {
596 case INTERNAL_TYPE_SCOPE:
597 case ACPI_TYPE_DEVICE:
598 case ACPI_TYPE_PROCESSOR:
599 case ACPI_TYPE_THERMAL:
600 case ACPI_TYPE_POWER:
601 status = bm_add_namespace_device(child_handle, acpi_type, parent, &child);
602 if (ACPI_SUCCESS(status)) {
603 status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL);
604 if (ACPI_SUCCESS(status)) {
605 level++;
606 parent_handle = child_handle;
607 child_handle = 0;
608 parent = child;
609 }
610 }
611 break;
612 }
613 }
614
615 /*
616 * Scope Exhausted:
617 * ----------------
618 * No more children in this object's scope, Go back up
619 * in the namespace tree to the object's parent.
620 */
621 else {
622 level--;
623 child_handle = parent_handle;
624 acpi_get_parent(parent_handle,
625 &parent_handle);
626
627 if (parent) {
628 parent = parent->parent;
629 }
630 else {
631 return_ACPI_STATUS(AE_NULL_ENTRY);
632 }
633 }
634 }
635
636 return_ACPI_STATUS(AE_OK);
637 }
638
639
640 /****************************************************************************
641 *
642 * FUNCTION: bm_add_fixed_feature_device
643 *
644 * PARAMETERS: <TBD>
645 *
646 * RETURN: <TBD>
647 *
648 * DESCRIPTION: <TBD>
649 *
650 ****************************************************************************/
651
652 ACPI_STATUS
653 bm_add_fixed_feature_device (
654 BM_NODE *parent,
655 BM_DEVICE_TYPE device_type,
656 char *device_hid)
657 {
658 ACPI_STATUS status = AE_OK;
659 BM_NODE *node = NULL;
660
661 FUNCTION_TRACE("bm_add_fixed_feature_device");
662
663 if (!parent) {
664 return_ACPI_STATUS(AE_BAD_PARAMETER);
665 }
666
667 if (node_list.count > BM_HANDLES_MAX) {
668 return_ACPI_STATUS(AE_NO_MEMORY);
669 }
670
671 /*
672 * Allocate the new device and add to the device array.
673 */
674 node = acpi_os_callocate(sizeof(BM_NODE));
675 if (!node) {
676 return_ACPI_STATUS(AE_NO_MEMORY);
677 }
678
679 /*
680 * Get device info.
681 */
682 node->device.handle = node_list.count;
683 node->device.acpi_handle = ACPI_ROOT_OBJECT;
684 node->device.id.type = BM_TYPE_FIXED_BUTTON;
685 if (device_hid) {
686 MEMCPY((void*)node->device.id.hid, device_hid,
687 sizeof(node->device.id.hid));
688 }
689 node->device.flags = BM_FLAGS_FIXED_FEATURE;
690 node->device.status = BM_STATUS_DEFAULT;
691 /* TODO: Device PM capabilities */
692
693 /*
694 * Add to the node_list.
695 */
696 node_list.nodes[node_list.count++] = node;
697
698 /*
699 * Formulate Hierarchy:
700 * --------------------
701 * Arrange within the namespace by assigning the parent and
702 * adding to the parent device's list of children (scope).
703 */
704 node->parent = parent;
705 node->next = NULL;
706
707 if (parent) {
708 if (!parent->scope.head) {
709 parent->scope.head = node;
710 }
711 else {
712 if (!parent->scope.tail) {
713 (parent->scope.head)->next = node;
714 }
715 else {
716 (parent->scope.tail)->next = node;
717 }
718 }
719 parent->scope.tail = node;
720 }
721
722 return_ACPI_STATUS(status);
723 }
724
725
726 /****************************************************************************
727 *
728 * FUNCTION: bm_enumerate_fixed_features
729 *
730 * PARAMETERS: <none>
731 *
732 * RETURN: <TBD>
733 *
734 * DESCRIPTION: <TBD>
735 *
736 ****************************************************************************/
737
738 ACPI_STATUS
739 bm_enumerate_fixed_features (void)
740 {
741 FUNCTION_TRACE("bm_enumerate_fixed_features");
742
743 /*
744 * Root Object:
745 * ------------
746 * Fabricate the root object, which happens to always get a
747 * device_handle of zero.
748 */
749 node_list.nodes[0] = acpi_os_callocate(sizeof(BM_NODE));
750 if (NULL == (node_list.nodes[0])) {
751 return_ACPI_STATUS(AE_NO_MEMORY);
752 }
753
754 node_list.nodes[0]->device.handle = BM_HANDLE_ROOT;
755 node_list.nodes[0]->device.acpi_handle = ACPI_ROOT_OBJECT;
756 node_list.nodes[0]->device.flags = BM_FLAGS_UNKNOWN;
757 node_list.nodes[0]->device.status = BM_STATUS_DEFAULT;
758 node_list.nodes[0]->device.id.type = BM_TYPE_SYSTEM;
759 /* TODO: Get system PM capabilities (Sx states?) */
760
761 node_list.count++;
762
763 /*
764 * Fixed Features:
765 * ---------------
766 * Enumerate fixed-feature devices (e.g. power and sleep buttons).
767 */
768 if (acpi_fadt.pwr_button == 0) {
769 bm_add_fixed_feature_device(node_list.nodes[0],
770 BM_TYPE_FIXED_BUTTON, BM_HID_POWER_BUTTON);
771 }
772
773 if (acpi_fadt.sleep_button == 0) {
774 bm_add_fixed_feature_device(node_list.nodes[0],
775 BM_TYPE_FIXED_BUTTON, BM_HID_SLEEP_BUTTON);
776 }
777
778 return_ACPI_STATUS(AE_OK);
779 }
780
781
782 /****************************************************************************
783 *
784 * FUNCTION: bm_get_handle
785 *
786 * PARAMETERS: <TBD>
787 *
788 * RETURN: <TBD>
789 *
790 * DESCRIPTION: <TBD>
791 *
792 ****************************************************************************/
793
794 ACPI_STATUS
795 bm_get_handle (
796 ACPI_HANDLE acpi_handle,
797 BM_HANDLE *device_handle)
798 {
799 ACPI_STATUS status = AE_OK;
800 u32 i = 0;
801
802 FUNCTION_TRACE("bm_get_handle");
803
804 if (!device_handle) {
805 return_ACPI_STATUS(AE_BAD_PARAMETER);
806 }
807
808 *device_handle = BM_HANDLE_UNKNOWN;
809
810 /*
811 * Search all devices for a match on the ACPI handle.
812 */
813 for (i=0; i<node_list.count; i++) {
814
815 if (!node_list.nodes[i]) {
816 DEBUG_PRINT(ACPI_ERROR, ("Invalid (NULL) node entry [0x%02x] detected.\n", device_handle));
817 status = AE_NULL_ENTRY;
818 break;
819 }
820
821 if (node_list.nodes[i]->device.acpi_handle == acpi_handle) {
822 *device_handle = node_list.nodes[i]->device.handle;
823 break;
824 }
825 }
826
827 return_ACPI_STATUS(status);
828 }
829
830
831 /****************************************************************************
832 *
833 * FUNCTION: bm_get_node
834 *
835 * PARAMETERS: <TBD>
836 *
837 * RETURN: <TBD>
838 *
839 * DESCRIPTION: <TBD>
840 *
841 ****************************************************************************/
842
843 ACPI_STATUS
844 bm_get_node (
845 BM_HANDLE device_handle,
846 ACPI_HANDLE acpi_handle,
847 BM_NODE **node)
848 {
849 ACPI_STATUS status = AE_OK;
850
851 FUNCTION_TRACE("bm_get_node");
852
853 if (!node) {
854 return_ACPI_STATUS(AE_BAD_PARAMETER);
855 }
856
857 /*
858 * If no device handle, resolve acpi handle to device handle.
859 */
860 if (!device_handle && acpi_handle) {
861 status = bm_get_handle(acpi_handle, &device_handle);
862 if (ACPI_FAILURE(status))
863 return_ACPI_STATUS(status);
864 }
865
866 /*
867 * Valid device handle?
868 */
869 if (device_handle > BM_HANDLES_MAX) {
870 DEBUG_PRINT(ACPI_ERROR, ("Invalid node handle [0x%02x] detected.\n", device_handle));
871 return_ACPI_STATUS(AE_ERROR);
872 }
873
874 *node = node_list.nodes[device_handle];
875
876 /*
877 * Valid node?
878 */
879 if (!(*node)) {
880 DEBUG_PRINT(ACPI_ERROR, ("Invalid (NULL) node entry [0x%02x] detected.\n", device_handle));
881 return_ACPI_STATUS(AE_NULL_ENTRY);
882 }
883
884 return_ACPI_STATUS(AE_OK);
885 }
886
887
888 /****************************************************************************
889 * External Functions
890 ****************************************************************************/
891
892 /****************************************************************************
893 *
894 * FUNCTION: bm_initialize
895 *
896 * PARAMETERS: <none>
897 *
898 * RETURN: Exception code.
899 *
900 * DESCRIPTION: <TBD>
901 *
902 ****************************************************************************/
903
904 ACPI_STATUS
905 bm_initialize (void)
906 {
907 ACPI_STATUS status = AE_OK;
908 u32 start = 0;
909 u32 stop = 0;
910 u32 elapsed = 0;
911
912 FUNCTION_TRACE("bm_initialize");
913
914 MEMSET(&node_list, 0, sizeof(BM_HANDLE_LIST));
915
916 acpi_get_timer(&start);
917
918 DEBUG_PRINT(ACPI_INFO, ("Building device hierarchy.\n"));
919
920 /*
921 * Enumerate ACPI fixed-feature devices.
922 */
923 status = bm_enumerate_fixed_features();
924 if (ACPI_FAILURE(status)) {
925 return_ACPI_STATUS(status);
926 }
927
928 /*
929 * Enumerate the ACPI namespace.
930 */
931 status = bm_enumerate_namespace();
932 if (ACPI_FAILURE(status)) {
933 return_ACPI_STATUS(status);
934 }
935
936 acpi_get_timer(&stop);
937 acpi_get_timer_duration(start, stop, &elapsed);
938
939 DEBUG_PRINT(ACPI_INFO, ("Device heirarchy build took [%d] microseconds.\n", elapsed));
940
941 /*
942 * Display hierarchy.
943 */
944 #ifdef ACPI_DEBUG
945 bm_print_hierarchy();
946 #endif /*ACPI_DEBUG*/
947
948 /*
949 * Register for all standard and device-specific notifications.
950 */
951 DEBUG_PRINT(ACPI_INFO, ("Registering for all device notifications.\n"));
952
953 status = acpi_install_notify_handler(ACPI_ROOT_OBJECT,
954 ACPI_SYSTEM_NOTIFY, &bm_notify, NULL);
955 if (ACPI_FAILURE(status)) {
956 DEBUG_PRINT(ACPI_ERROR, ("Unable to register for standard notifications.\n"));
957 return_ACPI_STATUS(status);
958 }
959
960 status = acpi_install_notify_handler(ACPI_ROOT_OBJECT,
961 ACPI_DEVICE_NOTIFY, &bm_notify, NULL);
962 if (ACPI_FAILURE(status)) {
963 DEBUG_PRINT(ACPI_ERROR, ("Unable to register for device-specific notifications.\n"));
964 return_ACPI_STATUS(status);
965 }
966
967 /*
968 * Initialize /proc interface.
969 */
970 //DEBUG_PRINT(ACPI_INFO, ("Initializing /proc interface.\n"));
971 //status = bm_proc_initialize();
972
973 DEBUG_PRINT(ACPI_INFO, ("ACPI Bus Manager enabled.\n"));
974
975 /*
976 * Initialize built-in power resource driver.
977 */
978 bm_pr_initialize();
979
980 return_ACPI_STATUS(status);
981 }
982
983
984 /****************************************************************************
985 *
986 * FUNCTION: bm_terminate
987 *
988 * PARAMETERS: <none>
989 *
990 * RETURN: Exception code.
991 *
992 * DESCRIPTION: <TBD>
993 *
994 ****************************************************************************/
995
996 ACPI_STATUS
997 bm_terminate (void)
998 {
999 ACPI_STATUS status = AE_OK;
1000 u32 i = 0;
1001
1002 FUNCTION_TRACE("bm_terminate");
1003
1004 /*
1005 * Terminate built-in power resource driver.
1006 */
1007 bm_pr_terminate();
1008
1009 /*
1010 * Remove the /proc interface.
1011 */
1012 //DEBUG_PRINT(ACPI_INFO, ("Removing /proc interface.\n"));
1013 //status = bm_proc_terminate();
1014
1015
1016 /*
1017 * Unregister for all notifications.
1018 */
1019
1020 DEBUG_PRINT(ACPI_INFO, ("Unregistering for device notifications.\n"));
1021
1022 status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT,
1023 ACPI_SYSTEM_NOTIFY, &bm_notify);
1024 if (ACPI_FAILURE(status)) {
1025 DEBUG_PRINT(ACPI_ERROR, ("Unable to un-register for standard notifications.\n"));
1026 }
1027
1028 status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT,
1029 ACPI_DEVICE_NOTIFY, &bm_notify);
1030 if (ACPI_FAILURE(status)) {
1031 DEBUG_PRINT(ACPI_ERROR, ("Unable to un-register for device-specific notifications.\n"));
1032 }
1033
1034 /*
1035 * Parse through the device array, freeing all entries.
1036 */
1037 DEBUG_PRINT(ACPI_INFO, ("Removing device hierarchy.\n"));
1038 for (i = 0; i < node_list.count; i++) {
1039 if (node_list.nodes[i]) {
1040 acpi_os_free(node_list.nodes[i]);
1041 }
1042 }
1043
1044 DEBUG_PRINT(ACPI_INFO, ("ACPI Bus Manager disabled.\n"));
1045
1046 return_ACPI_STATUS(AE_OK);
1047 }