bmpower.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:15k
- /****************************************************************************
- *
- * Module Name: bmpower.c - Driver for ACPI Power Resource 'devices'
- * $Revision: 20 $
- *
- ****************************************************************************/
- /*
- * Copyright (C) 2000, 2001 Andrew Grover
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- /*
- * TBD: 1. Sequencing of power resource list transitions.
- * 2. Global serialization of power resource transtions (see ACPI
- * spec section 7.1.2/7.1.3).
- * 3. Better error handling.
- */
- #include <acpi.h>
- #include "bm.h"
- #include "bmpower.h"
- #define _COMPONENT ACPI_BUS
- MODULE_NAME ("bmpower")
- /****************************************************************************
- * Function Prototypes
- ****************************************************************************/
- acpi_status
- bm_pr_notify (
- BM_NOTIFY notify_type,
- BM_HANDLE device_handle,
- void **context);
-
- acpi_status
- bm_pr_request (
- BM_REQUEST *request,
- void *context);
-
- /****************************************************************************
- * Internal Functions
- ****************************************************************************/
- /****************************************************************************
- *
- * FUNCTION: bm_pr_print
- *
- * PARAMETERS:
- *
- * RETURN:
- *
- * DESCRIPTION:
- *
- ****************************************************************************/
- acpi_status
- bm_pr_print (
- BM_POWER_RESOURCE *pr)
- {
- acpi_buffer buffer;
- PROC_NAME("bm_pr_print");
- if (!pr) {
- return(AE_BAD_PARAMETER);
- }
- buffer.length = 256;
- buffer.pointer = acpi_os_callocate(buffer.length);
- if (!buffer.pointer) {
- return(AE_NO_MEMORY);
- }
- acpi_get_name(pr->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
- acpi_os_printf("Power Resource: foundn");
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------n"));
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| Power_resource[%02x]:[%p] %sn", pr->device_handle, pr->acpi_handle, (char*)buffer.pointer));
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| system_level[S%d] resource_order[%d]n", pr->system_level, pr->resource_order));
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| state[D%d] reference_count[%d]n", pr->state, pr->reference_count));
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------n"));
- acpi_os_free(buffer.pointer);
- return(AE_OK);
- }
- /****************************************************************************
- *
- * FUNCTION: bm_pr_get_state
- *
- * PARAMETERS:
- *
- * RETURN:
- *
- * DESCRIPTION:
- *
- ****************************************************************************/
- acpi_status
- bm_pr_get_state (
- BM_POWER_RESOURCE *pr)
- {
- acpi_status status = AE_OK;
- BM_DEVICE_STATUS device_status = BM_STATUS_UNKNOWN;
- FUNCTION_TRACE("bm_pr_get_state");
- if (!pr) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
- pr->state = ACPI_STATE_UNKNOWN;
- /*
- * Evaluate _STA:
- * --------------
- * Evalute _STA to determine whether the power resource is ON or OFF.
- * Note that if the power resource isn't present we'll get AE_OK but
- * an unknown status.
- */
- status = bm_get_device_status(pr->device_handle, &device_status);
- if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Error reading status for power resource [%02x].n", pr->device_handle));
- return_ACPI_STATUS(status);
- }
- /*
- * Mask off all bits but the first as some systems return non-standard
- * values (e.g. 0x51).
- */
- switch (device_status & 0x01) {
- case 0:
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Power resource [%02x] is OFF.n", pr->device_handle));
- pr->state = ACPI_STATE_D3;
- break;
- case 1:
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Power resource [%02x] is ON.n", pr->device_handle));
- pr->state = ACPI_STATE_D0;
- break;
- }
- return_ACPI_STATUS(status);
- }
- /****************************************************************************
- *
- * FUNCTION: bm_pr_set_state
- *
- * PARAMETERS:
- *
- * RETURN:
- *
- * DESCRIPTION:
- *
- ****************************************************************************/
- acpi_status
- bm_pr_set_state (
- BM_POWER_RESOURCE *pr,
- BM_POWER_STATE target_state)
- {
- acpi_status status = AE_OK;
- FUNCTION_TRACE("bm_pr_set_state");
- if (!pr) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
- status = bm_pr_get_state(pr);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- if (target_state == pr->state) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Power resource [%02x] already at target power state [D%d].n", pr->device_handle, pr->state));
- return_ACPI_STATUS(AE_OK);
- }
- switch (target_state) {
- case ACPI_STATE_D0:
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Turning power resource [%02x] ON.n", pr->device_handle));
- status = bm_evaluate_object(pr->acpi_handle, "_ON", NULL, NULL);
- break;
- case ACPI_STATE_D3:
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Turning power resource [%02x] OFF.n", pr->device_handle));
- status = bm_evaluate_object(pr->acpi_handle, "_OFF", NULL, NULL);
- break;
- default:
- status = AE_BAD_PARAMETER;
- break;
- }
- status = bm_pr_get_state(pr);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- return_ACPI_STATUS(status);
- }
- /****************************************************************************
- *
- * FUNCTION: bm_pr_list_get_state
- *
- * PARAMETERS:
- *
- * RETURN:
- *
- * DESCRIPTION:
- *
- ****************************************************************************/
- acpi_status
- bm_pr_list_get_state (
- BM_HANDLE_LIST *pr_list,
- BM_POWER_STATE *power_state)
- {
- acpi_status status = AE_OK;
- BM_POWER_RESOURCE *pr = NULL;
- u32 i = 0;
- FUNCTION_TRACE("bm_pr_list_get_state");
- if (!pr_list || !power_state) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
- if (pr_list->count < 1) {
- pr->state = ACPI_STATE_UNKNOWN;
- return_ACPI_STATUS(AE_ERROR);
- }
- (*power_state) = ACPI_STATE_D0;
- /*
- * Calculate Current power_state:
- * -----------------------------
- * The current state of a list of power resources is ON if all
- * power resources are currently in the ON state. In other words,
- * if any power resource in the list is OFF then the collection
- * isn't fully ON.
- */
- for (i = 0; i < pr_list->count; i++) {
- status = bm_get_device_context(pr_list->handles[i],
- (BM_DRIVER_CONTEXT*)(&pr));
- if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Invalid reference to power resource [%02x].n", pr_list->handles[i]));
- (*power_state) = ACPI_STATE_UNKNOWN;
- break;
- }
- status = bm_pr_get_state(pr);
- if (ACPI_FAILURE(status)) {
- (*power_state) = ACPI_STATE_UNKNOWN;
- break;
- }
- if (pr->state != ACPI_STATE_D0) {
- (*power_state) = pr->state;
- break;
- }
- }
- return_ACPI_STATUS(status);
- }
- /****************************************************************************
- *
- * FUNCTION: bm_pr_list_transition
- *
- * PARAMETERS:
- *
- * RETURN:
- *
- * DESCRIPTION:
- *
- ****************************************************************************/
- acpi_status
- bm_pr_list_transition (
- BM_HANDLE_LIST *current_list,
- BM_HANDLE_LIST *target_list)
- {
- acpi_status status = AE_OK;
- BM_POWER_RESOURCE *pr = NULL;
- u32 i = 0;
- FUNCTION_TRACE("bm_pr_list_transition");
- if (!current_list || !target_list) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
- /*
- * Reference Target:
- * -----------------
- * Reference all resources for the target power state first (so
- * the device doesn't get turned off while transitioning). Power
- * resources that aren't on (new reference count of 1) are turned on.
- */
- for (i = 0; i < target_list->count; i++) {
- status = bm_get_device_context(target_list->handles[i],
- (BM_DRIVER_CONTEXT*)(&pr));
- if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Invalid reference to power resource [%02x].n", target_list->handles[i]));
- continue;
- }
- if (++pr->reference_count == 1) {
- /* TBD: Need ordering based upon resource_order */
- status = bm_pr_set_state(pr, ACPI_STATE_D0);
- if (ACPI_FAILURE(status)) {
- /* TBD: How do we handle this? */
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to change power state for power resource [%02x].n", target_list->handles[i]));
- }
- }
- }
- /*
- * Dereference Current:
- * --------------------
- * Dereference all resources for the current power state. Power
- * resources no longer referenced (new reference count of 0) are
- * turned off.
- */
- for (i = 0; i < current_list->count; i++) {
- status = bm_get_device_context(current_list->handles[i],
- (BM_DRIVER_CONTEXT*)(&pr));
- if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Invalid reference to power resource [%02x].n", target_list->handles[i]));
- continue;
- }
- if (--pr->reference_count == 0) {
- /* TBD: Need ordering based upon resource_order */
- status = bm_pr_set_state(pr, ACPI_STATE_D3);
- if (ACPI_FAILURE(status)) {
- /* TBD: How do we handle this? */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unable to change power state for power resource [%02x].n", current_list->handles[i]));
- }
- }
- }
- return_ACPI_STATUS(status);
- }
- /****************************************************************************
- *
- * FUNCTION: bm_pr_add_device
- *
- * PARAMETERS:
- *
- * RETURN:
- *
- * DESCRIPTION:
- *
- ****************************************************************************/
- acpi_status
- bm_pr_add_device (
- BM_HANDLE device_handle,
- void **context)
- {
- acpi_status status = AE_OK;
- BM_POWER_RESOURCE *pr = NULL;
- BM_DEVICE *device = NULL;
- acpi_buffer buffer;
- acpi_object acpi_object;
- FUNCTION_TRACE("bm_pr_add_device");
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Adding power resource [%02x].n", device_handle));
- if (!context || *context) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
- buffer.length = sizeof(acpi_object);
- buffer.pointer = &acpi_object;
- /*
- * Get information on this device.
- */
- status = bm_get_device_info(device_handle, &device);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- /*
- * Allocate a new BM_POWER_RESOURCE structure.
- */
- pr = acpi_os_callocate(sizeof(BM_POWER_RESOURCE));
- if (!pr) {
- return_ACPI_STATUS(AE_NO_MEMORY);
- }
- pr->device_handle = device->handle;
- pr->acpi_handle = device->acpi_handle;
- /*
- * Get information on this power resource.
- */
- status = acpi_evaluate_object(pr->acpi_handle, NULL, NULL, &buffer);
- if (ACPI_FAILURE(status)) {
- goto end;
- }
- pr->system_level = acpi_object.power_resource.system_level;
- pr->resource_order = acpi_object.power_resource.resource_order;
- pr->state = ACPI_STATE_UNKNOWN;
- pr->reference_count = 0;
- /*
- * Get the power resource's current state (ON|OFF).
- */
- status = bm_pr_get_state(pr);
- end:
- if (ACPI_FAILURE(status)) {
- acpi_os_free(pr);
- }
- else {
- *context = pr;
- bm_pr_print(pr);
- }
- return_ACPI_STATUS(status);
- }
- /****************************************************************************
- *
- * FUNCTION: bm_pr_remove_device
- *
- * PARAMETERS:
- *
- * RETURN:
- *
- * DESCRIPTION:
- *
- ****************************************************************************/
- acpi_status
- bm_pr_remove_device (
- void **context)
- {
- acpi_status status = AE_OK;
- BM_POWER_RESOURCE *pr = NULL;
- FUNCTION_TRACE("bm_pr_remove_device");
- if (!context || !*context) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
- pr = (BM_POWER_RESOURCE*)*context;
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing power resource [%02x].n", pr->device_handle));
- acpi_os_free(pr);
- return_ACPI_STATUS(status);
- }
- /****************************************************************************
- * External Functions
- ****************************************************************************/
- /****************************************************************************
- *
- * FUNCTION: bm_pr_initialize
- *
- * PARAMETERS: <none>
- *
- * RETURN:
- *
- * DESCRIPTION:
- *
- ****************************************************************************/
- acpi_status
- bm_pr_initialize (void)
- {
- acpi_status status = AE_OK;
- BM_DEVICE_ID criteria;
- BM_DRIVER driver;
- FUNCTION_TRACE("bm_pr_initialize");
- MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
- MEMSET(&driver, 0, sizeof(BM_DRIVER));
- criteria.type = BM_TYPE_POWER_RESOURCE;
- driver.notify = &bm_pr_notify;
- driver.request = &bm_pr_request;
- status = bm_register_driver(&criteria, &driver);
- return_ACPI_STATUS(status);
- }
- /****************************************************************************
- *
- * FUNCTION: bm_pr_terminate
- *
- * PARAMETERS:
- *
- * RETURN:
- *
- * DESCRIPTION:
- *
- ****************************************************************************/
- acpi_status
- bm_pr_terminate (void)
- {
- acpi_status status = AE_OK;
- BM_DEVICE_ID criteria;
- BM_DRIVER driver;
- FUNCTION_TRACE("bm_pr_terminate");
- MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
- MEMSET(&driver, 0, sizeof(BM_DRIVER));
- criteria.type = BM_TYPE_POWER_RESOURCE;
- driver.notify = &bm_pr_notify;
- driver.request = &bm_pr_request;
- status = bm_unregister_driver(&criteria, &driver);
- return_ACPI_STATUS(status);
- }
- /****************************************************************************
- *
- * FUNCTION: bm_pr_notify
- *
- * PARAMETERS:
- *
- * RETURN:
- *
- * DESCRIPTION:
- *
- ****************************************************************************/
- acpi_status
- bm_pr_notify (
- BM_NOTIFY notify_type,
- BM_HANDLE device_handle,
- void **context)
- {
- acpi_status status = AE_OK;
- FUNCTION_TRACE("bm_pr_notify");
- switch (notify_type) {
- case BM_NOTIFY_DEVICE_ADDED:
- status = bm_pr_add_device(device_handle, context);
- break;
- case BM_NOTIFY_DEVICE_REMOVED:
- status = bm_pr_remove_device(context);
- break;
- default:
- status = AE_SUPPORT;
- break;
- }
- return_ACPI_STATUS(status);
- }
- /****************************************************************************
- *
- * FUNCTION: bm_pr_request
- *
- * PARAMETERS:
- *
- * RETURN:
- *
- * DESCRIPTION:
- *
- ****************************************************************************/
- acpi_status
- bm_pr_request (
- BM_REQUEST *request,
- void *context)
- {
- acpi_status status = AE_OK;
- BM_POWER_RESOURCE *pr = NULL;
- FUNCTION_TRACE("bm_pr_request");
- /*
- * Must have a valid request structure and context.
- */
- if (!request || !context) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
- /*
- * context contains information specific to this power resource.
- */
- pr = (BM_POWER_RESOURCE*)context;
- /*
- * Handle request:
- * ---------------
- */
- switch (request->command) {
- default:
- status = AE_SUPPORT;
- break;
- }
- request->status = status;
- return_ACPI_STATUS(status);
- }