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