📄 bm.c
字号:
(*child) = node;
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_enumerate_namespace
*
* PARAMETERS: <none>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_enumerate_namespace (void)
{
ACPI_STATUS status = AE_OK;
ACPI_HANDLE parent_handle = ACPI_ROOT_OBJECT;
ACPI_HANDLE child_handle = NULL;
BM_NODE *parent = NULL;
BM_NODE *child = NULL;
ACPI_OBJECT_TYPE acpi_type = 0;
u32 level = 1;
FUNCTION_TRACE("bm_enumerate_namespace");
parent = node_list.nodes[0];
/*
* Enumerate ACPI Namespace:
* -------------------------
* Parse through the ACPI namespace, identify all 'devices',
* and create a new entry for each in our collection.
*/
while (level > 0) {
/*
* Get the next object at this level.
*/
status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, child_handle, &child_handle);
if (ACPI_SUCCESS(status)) {
/*
* TODO: This is a hack to get around the problem
* identifying scope objects. Scopes
* somehow need to be uniquely identified.
*/
status = acpi_get_type(child_handle, &acpi_type);
if (ACPI_SUCCESS(status) && (acpi_type == ACPI_TYPE_ANY)) {
status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL);
if (ACPI_SUCCESS(status)) {
acpi_type = INTERNAL_TYPE_SCOPE;
}
}
/*
* Device?
* -------
* If this object is a 'device', insert into the
* ACPI Bus Manager's local hierarchy and search
* the object's scope for any child devices (a
* depth-first search).
*/
switch (acpi_type) {
case INTERNAL_TYPE_SCOPE:
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_THERMAL:
case ACPI_TYPE_POWER:
status = bm_add_namespace_device(child_handle, acpi_type, parent, &child);
if (ACPI_SUCCESS(status)) {
status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL);
if (ACPI_SUCCESS(status)) {
level++;
parent_handle = child_handle;
child_handle = 0;
parent = child;
}
}
break;
}
}
/*
* Scope Exhausted:
* ----------------
* No more children in this object's scope, Go back up
* in the namespace tree to the object's parent.
*/
else {
level--;
child_handle = parent_handle;
acpi_get_parent(parent_handle,
&parent_handle);
if (parent) {
parent = parent->parent;
}
else {
return_ACPI_STATUS(AE_NULL_ENTRY);
}
}
}
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************
*
* FUNCTION: bm_add_fixed_feature_device
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_add_fixed_feature_device (
BM_NODE *parent,
BM_DEVICE_TYPE device_type,
char *device_hid)
{
ACPI_STATUS status = AE_OK;
BM_NODE *node = NULL;
FUNCTION_TRACE("bm_add_fixed_feature_device");
if (!parent) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (node_list.count > BM_HANDLES_MAX) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
* Allocate the new device and add to the device array.
*/
node = acpi_os_callocate(sizeof(BM_NODE));
if (!node) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
* Get device info.
*/
node->device.handle = node_list.count;
node->device.acpi_handle = ACPI_ROOT_OBJECT;
node->device.id.type = BM_TYPE_FIXED_BUTTON;
if (device_hid) {
MEMCPY((void*)node->device.id.hid, device_hid,
sizeof(node->device.id.hid));
}
node->device.flags = BM_FLAGS_FIXED_FEATURE;
node->device.status = BM_STATUS_DEFAULT;
/* TODO: Device PM capabilities */
/*
* Add to the node_list.
*/
node_list.nodes[node_list.count++] = node;
/*
* Formulate Hierarchy:
* --------------------
* Arrange within the namespace by assigning the parent and
* adding to the parent device's list of children (scope).
*/
node->parent = parent;
node->next = NULL;
if (parent) {
if (!parent->scope.head) {
parent->scope.head = node;
}
else {
if (!parent->scope.tail) {
(parent->scope.head)->next = node;
}
else {
(parent->scope.tail)->next = node;
}
}
parent->scope.tail = node;
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_enumerate_fixed_features
*
* PARAMETERS: <none>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_enumerate_fixed_features (void)
{
FUNCTION_TRACE("bm_enumerate_fixed_features");
/*
* Root Object:
* ------------
* Fabricate the root object, which happens to always get a
* device_handle of zero.
*/
node_list.nodes[0] = acpi_os_callocate(sizeof(BM_NODE));
if (NULL == (node_list.nodes[0])) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
node_list.nodes[0]->device.handle = BM_HANDLE_ROOT;
node_list.nodes[0]->device.acpi_handle = ACPI_ROOT_OBJECT;
node_list.nodes[0]->device.flags = BM_FLAGS_UNKNOWN;
node_list.nodes[0]->device.status = BM_STATUS_DEFAULT;
node_list.nodes[0]->device.id.type = BM_TYPE_SYSTEM;
/* TODO: Get system PM capabilities (Sx states?) */
node_list.count++;
/*
* Fixed Features:
* ---------------
* Enumerate fixed-feature devices (e.g. power and sleep buttons).
*/
if (acpi_fadt.pwr_button == 0) {
bm_add_fixed_feature_device(node_list.nodes[0],
BM_TYPE_FIXED_BUTTON, BM_HID_POWER_BUTTON);
}
if (acpi_fadt.sleep_button == 0) {
bm_add_fixed_feature_device(node_list.nodes[0],
BM_TYPE_FIXED_BUTTON, BM_HID_SLEEP_BUTTON);
}
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************
*
* FUNCTION: bm_get_handle
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_get_handle (
ACPI_HANDLE acpi_handle,
BM_HANDLE *device_handle)
{
ACPI_STATUS status = AE_OK;
u32 i = 0;
FUNCTION_TRACE("bm_get_handle");
if (!device_handle) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
*device_handle = BM_HANDLE_UNKNOWN;
/*
* Search all devices for a match on the ACPI handle.
*/
for (i=0; i<node_list.count; i++) {
if (!node_list.nodes[i]) {
DEBUG_PRINT(ACPI_ERROR, ("Invalid (NULL) node entry [0x%02x] detected.\n", device_handle));
status = AE_NULL_ENTRY;
break;
}
if (node_list.nodes[i]->device.acpi_handle == acpi_handle) {
*device_handle = node_list.nodes[i]->device.handle;
break;
}
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_get_node
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_get_node (
BM_HANDLE device_handle,
ACPI_HANDLE acpi_handle,
BM_NODE **node)
{
ACPI_STATUS status = AE_OK;
FUNCTION_TRACE("bm_get_node");
if (!node) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* If no device handle, resolve acpi handle to device handle.
*/
if (!device_handle && acpi_handle) {
status = bm_get_handle(acpi_handle, &device_handle);
if (ACPI_FAILURE(status))
return_ACPI_STATUS(status);
}
/*
* Valid device handle?
*/
if (device_handle > BM_HANDLES_MAX) {
DEBUG_PRINT(ACPI_ERROR, ("Invalid node handle [0x%02x] detected.\n", device_handle));
return_ACPI_STATUS(AE_ERROR);
}
*node = node_list.nodes[device_handle];
/*
* Valid node?
*/
if (!(*node)) {
DEBUG_PRINT(ACPI_ERROR, ("Invalid (NULL) node entry [0x%02x] detected.\n", device_handle));
return_ACPI_STATUS(AE_NULL_ENTRY);
}
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************
* External Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: bm_initialize
*
* PARAMETERS: <none>
*
* RETURN: Exception code.
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_initialize (void)
{
ACPI_STATUS status = AE_OK;
u32 start = 0;
u32 stop = 0;
u32 elapsed = 0;
FUNCTION_TRACE("bm_initialize");
MEMSET(&node_list, 0, sizeof(BM_HANDLE_LIST));
acpi_get_timer(&start);
DEBUG_PRINT(ACPI_INFO, ("Building device hierarchy.\n"));
/*
* Enumerate ACPI fixed-feature devices.
*/
status = bm_enumerate_fixed_features();
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Enumerate the ACPI namespace.
*/
status = bm_enumerate_namespace();
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_get_timer(&stop);
acpi_get_timer_duration(start, stop, &elapsed);
DEBUG_PRINT(ACPI_INFO, ("Device heirarchy build took [%d] microseconds.\n", elapsed));
/*
* Display hierarchy.
*/
#ifdef ACPI_DEBUG
bm_print_hierarchy();
#endif /*ACPI_DEBUG*/
/*
* Register for all standard and device-specific notifications.
*/
DEBUG_PRINT(ACPI_INFO, ("Registering for all device notifications.\n"));
status = acpi_install_notify_handler(ACPI_ROOT_OBJECT,
ACPI_SYSTEM_NOTIFY, &bm_notify, NULL);
if (ACPI_FAILURE(status)) {
DEBUG_PRINT(ACPI_ERROR, ("Unable to register for standard notifications.\n"));
return_ACPI_STATUS(status);
}
status = acpi_install_notify_handler(ACPI_ROOT_OBJECT,
ACPI_DEVICE_NOTIFY, &bm_notify, NULL);
if (ACPI_FAILURE(status)) {
DEBUG_PRINT(ACPI_ERROR, ("Unable to register for device-specific notifications.\n"));
return_ACPI_STATUS(status);
}
/*
* Initialize /proc interface.
*/
//DEBUG_PRINT(ACPI_INFO, ("Initializing /proc interface.\n"));
//status = bm_proc_initialize();
DEBUG_PRINT(ACPI_INFO, ("ACPI Bus Manager enabled.\n"));
/*
* Initialize built-in power resource driver.
*/
bm_pr_initialize();
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_terminate
*
* PARAMETERS: <none>
*
* RETURN: Exception code.
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_terminate (void)
{
ACPI_STATUS status = AE_OK;
u32 i = 0;
FUNCTION_TRACE("bm_terminate");
/*
* Terminate built-in power resource driver.
*/
bm_pr_terminate();
/*
* Remove the /proc interface.
*/
//DEBUG_PRINT(ACPI_INFO, ("Removing /proc interface.\n"));
//status = bm_proc_terminate();
/*
* Unregister for all notifications.
*/
DEBUG_PRINT(ACPI_INFO, ("Unregistering for device notifications.\n"));
status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT,
ACPI_SYSTEM_NOTIFY, &bm_notify);
if (ACPI_FAILURE(status)) {
DEBUG_PRINT(ACPI_ERROR, ("Unable to un-register for standard notifications.\n"));
}
status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT,
ACPI_DEVICE_NOTIFY, &bm_notify);
if (ACPI_FAILURE(status)) {
DEBUG_PRINT(ACPI_ERROR, ("Unable to un-register for device-specific notifications.\n"));
}
/*
* Parse through the device array, freeing all entries.
*/
DEBUG_PRINT(ACPI_INFO, ("Removing device hierarchy.\n"));
for (i = 0; i < node_list.count; i++) {
if (node_list.nodes[i]) {
acpi_os_free(node_list.nodes[i]);
}
}
DEBUG_PRINT(ACPI_INFO, ("ACPI Bus Manager disabled.\n"));
return_ACPI_STATUS(AE_OK);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -