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