bmpower.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:15k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /****************************************************************************
  2.  *
  3.  * Module Name: bmpower.c - Driver for ACPI Power Resource 'devices'
  4.  *   $Revision: 20 $
  5.  *
  6.  ****************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 Andrew Grover
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. /*
  25.  * TBD: 1. Sequencing of power resource list transitions.
  26.  * 2. Global serialization of power resource transtions (see ACPI
  27.  *         spec section 7.1.2/7.1.3).
  28.  *      3. Better error handling.
  29.  */
  30. #include <acpi.h>
  31. #include "bm.h"
  32. #include "bmpower.h"
  33. #define _COMPONENT ACPI_BUS
  34. MODULE_NAME ("bmpower")
  35. /****************************************************************************
  36.  *                             Function Prototypes
  37.  ****************************************************************************/
  38. acpi_status
  39. bm_pr_notify (
  40. BM_NOTIFY               notify_type,
  41. BM_HANDLE               device_handle,
  42. void                    **context);
  43. acpi_status
  44. bm_pr_request (
  45. BM_REQUEST *request,
  46. void                    *context);
  47. /****************************************************************************
  48.  *                             Internal Functions
  49.  ****************************************************************************/
  50. /****************************************************************************
  51.  *
  52.  * FUNCTION:    bm_pr_print
  53.  *
  54.  * PARAMETERS:
  55.  *
  56.  * RETURN:
  57.  *
  58.  * DESCRIPTION:
  59.  *
  60.  ****************************************************************************/
  61. acpi_status
  62. bm_pr_print (
  63. BM_POWER_RESOURCE *pr)
  64. {
  65. acpi_buffer             buffer;
  66. PROC_NAME("bm_pr_print");
  67. if (!pr) {
  68. return(AE_BAD_PARAMETER);
  69. }
  70. buffer.length = 256;
  71. buffer.pointer = acpi_os_callocate(buffer.length);
  72. if (!buffer.pointer) {
  73. return(AE_NO_MEMORY);
  74. }
  75. acpi_get_name(pr->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
  76. acpi_os_printf("Power Resource: foundn");
  77. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------n"));
  78. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| Power_resource[%02x]:[%p] %sn", pr->device_handle, pr->acpi_handle, (char*)buffer.pointer));
  79. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "|   system_level[S%d] resource_order[%d]n", pr->system_level, pr->resource_order));
  80. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "|   state[D%d] reference_count[%d]n", pr->state, pr->reference_count));
  81. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------n"));
  82. acpi_os_free(buffer.pointer);
  83. return(AE_OK);
  84. }
  85. /****************************************************************************
  86.  *
  87.  * FUNCTION:    bm_pr_get_state
  88.  *
  89.  * PARAMETERS:
  90.  *
  91.  * RETURN:
  92.  *
  93.  * DESCRIPTION:
  94.  *
  95.  ****************************************************************************/
  96. acpi_status
  97. bm_pr_get_state (
  98. BM_POWER_RESOURCE *pr)
  99. {
  100. acpi_status             status = AE_OK;
  101. BM_DEVICE_STATUS        device_status = BM_STATUS_UNKNOWN;
  102. FUNCTION_TRACE("bm_pr_get_state");
  103. if (!pr) {
  104. return_ACPI_STATUS(AE_BAD_PARAMETER);
  105. }
  106. pr->state = ACPI_STATE_UNKNOWN;
  107. /*
  108.  * Evaluate _STA:
  109.  * --------------
  110.  * Evalute _STA to determine whether the power resource is ON or OFF.
  111.  * Note that if the power resource isn't present we'll get AE_OK but
  112.  * an unknown status.
  113.  */
  114. status = bm_get_device_status(pr->device_handle, &device_status);
  115. if (ACPI_FAILURE(status)) {
  116. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Error reading status for power resource [%02x].n", pr->device_handle));
  117. return_ACPI_STATUS(status);
  118. }
  119. /*
  120.  * Mask off all bits but the first as some systems return non-standard
  121.  * values (e.g. 0x51).
  122.  */
  123. switch (device_status & 0x01) {
  124. case 0:
  125. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Power resource [%02x] is OFF.n", pr->device_handle));
  126. pr->state = ACPI_STATE_D3;
  127. break;
  128. case 1:
  129. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Power resource [%02x] is ON.n", pr->device_handle));
  130. pr->state = ACPI_STATE_D0;
  131. break;
  132. }
  133. return_ACPI_STATUS(status);
  134. }
  135. /****************************************************************************
  136.  *
  137.  * FUNCTION:    bm_pr_set_state
  138.  *
  139.  * PARAMETERS:
  140.  *
  141.  * RETURN:
  142.  *
  143.  * DESCRIPTION:
  144.  *
  145.  ****************************************************************************/
  146. acpi_status
  147. bm_pr_set_state (
  148. BM_POWER_RESOURCE *pr,
  149. BM_POWER_STATE          target_state)
  150. {
  151. acpi_status             status = AE_OK;
  152. FUNCTION_TRACE("bm_pr_set_state");
  153. if (!pr) {
  154. return_ACPI_STATUS(AE_BAD_PARAMETER);
  155. }
  156. status = bm_pr_get_state(pr);
  157. if (ACPI_FAILURE(status)) {
  158. return_ACPI_STATUS(status);
  159. }
  160. if (target_state == pr->state) {
  161. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Power resource [%02x] already at target power state [D%d].n", pr->device_handle, pr->state));
  162. return_ACPI_STATUS(AE_OK);
  163. }
  164. switch (target_state) {
  165. case ACPI_STATE_D0:
  166. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Turning power resource [%02x] ON.n", pr->device_handle));
  167. status = bm_evaluate_object(pr->acpi_handle, "_ON", NULL, NULL);
  168. break;
  169. case ACPI_STATE_D3:
  170. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Turning power resource [%02x] OFF.n", pr->device_handle));
  171. status = bm_evaluate_object(pr->acpi_handle, "_OFF", NULL, NULL);
  172. break;
  173. default:
  174. status = AE_BAD_PARAMETER;
  175. break;
  176. }
  177. status = bm_pr_get_state(pr);
  178. if (ACPI_FAILURE(status)) {
  179. return_ACPI_STATUS(status);
  180. }
  181. return_ACPI_STATUS(status);
  182. }
  183. /****************************************************************************
  184.  *
  185.  * FUNCTION:    bm_pr_list_get_state
  186.  *
  187.  * PARAMETERS:
  188.  *
  189.  * RETURN:
  190.  *
  191.  * DESCRIPTION:
  192.  *
  193.  ****************************************************************************/
  194. acpi_status
  195. bm_pr_list_get_state (
  196. BM_HANDLE_LIST          *pr_list,
  197. BM_POWER_STATE          *power_state)
  198. {
  199. acpi_status             status = AE_OK;
  200. BM_POWER_RESOURCE *pr = NULL;
  201. u32                     i = 0;
  202. FUNCTION_TRACE("bm_pr_list_get_state");
  203. if (!pr_list || !power_state) {
  204. return_ACPI_STATUS(AE_BAD_PARAMETER);
  205. }
  206. if (pr_list->count < 1) {
  207. pr->state = ACPI_STATE_UNKNOWN;
  208. return_ACPI_STATUS(AE_ERROR);
  209. }
  210. (*power_state) = ACPI_STATE_D0;
  211. /*
  212.  * Calculate Current power_state:
  213.  * -----------------------------
  214.  * The current state of a list of power resources is ON if all
  215.  * power resources are currently in the ON state.  In other words,
  216.  * if any power resource in the list is OFF then the collection
  217.  * isn't fully ON.
  218.  */
  219. for (i = 0; i < pr_list->count; i++) {
  220. status = bm_get_device_context(pr_list->handles[i],
  221. (BM_DRIVER_CONTEXT*)(&pr));
  222. if (ACPI_FAILURE(status)) {
  223. ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Invalid reference to power resource [%02x].n", pr_list->handles[i]));
  224. (*power_state) = ACPI_STATE_UNKNOWN;
  225. break;
  226. }
  227. status = bm_pr_get_state(pr);
  228. if (ACPI_FAILURE(status)) {
  229. (*power_state) = ACPI_STATE_UNKNOWN;
  230. break;
  231. }
  232. if (pr->state != ACPI_STATE_D0) {
  233. (*power_state) = pr->state;
  234. break;
  235. }
  236. }
  237. return_ACPI_STATUS(status);
  238. }
  239. /****************************************************************************
  240.  *
  241.  * FUNCTION:    bm_pr_list_transition
  242.  *
  243.  * PARAMETERS:
  244.  *
  245.  * RETURN:
  246.  *
  247.  * DESCRIPTION:
  248.  *
  249.  ****************************************************************************/
  250. acpi_status
  251. bm_pr_list_transition (
  252. BM_HANDLE_LIST          *current_list,
  253. BM_HANDLE_LIST          *target_list)
  254. {
  255. acpi_status             status = AE_OK;
  256. BM_POWER_RESOURCE *pr = NULL;
  257. u32                     i = 0;
  258. FUNCTION_TRACE("bm_pr_list_transition");
  259. if (!current_list || !target_list) {
  260. return_ACPI_STATUS(AE_BAD_PARAMETER);
  261. }
  262. /*
  263.  * Reference Target:
  264.  * -----------------
  265.  * Reference all resources for the target power state first (so
  266.  * the device doesn't get turned off while transitioning).  Power
  267.  * resources that aren't on (new reference count of 1) are turned on.
  268.  */
  269. for (i = 0; i < target_list->count; i++) {
  270. status = bm_get_device_context(target_list->handles[i],
  271. (BM_DRIVER_CONTEXT*)(&pr));
  272. if (ACPI_FAILURE(status)) {
  273. ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Invalid reference to power resource [%02x].n", target_list->handles[i]));
  274. continue;
  275. }
  276. if (++pr->reference_count == 1) {
  277. /* TBD: Need ordering based upon resource_order */
  278. status = bm_pr_set_state(pr, ACPI_STATE_D0);
  279. if (ACPI_FAILURE(status)) {
  280. /* TBD: How do we handle this? */
  281. ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to change power state for power resource [%02x].n", target_list->handles[i]));
  282. }
  283. }
  284. }
  285. /*
  286.  * Dereference Current:
  287.  * --------------------
  288.  * Dereference all resources for the current power state.  Power
  289.  * resources no longer referenced (new reference count of 0) are
  290.  * turned off.
  291.  */
  292. for (i = 0; i < current_list->count; i++) {
  293. status = bm_get_device_context(current_list->handles[i],
  294. (BM_DRIVER_CONTEXT*)(&pr));
  295. if (ACPI_FAILURE(status)) {
  296. ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Invalid reference to power resource [%02x].n", target_list->handles[i]));
  297. continue;
  298. }
  299. if (--pr->reference_count == 0) {
  300. /* TBD: Need ordering based upon resource_order */
  301. status = bm_pr_set_state(pr, ACPI_STATE_D3);
  302. if (ACPI_FAILURE(status)) {
  303. /* TBD: How do we handle this? */
  304. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unable to change power state for power resource [%02x].n", current_list->handles[i]));
  305. }
  306. }
  307. }
  308. return_ACPI_STATUS(status);
  309. }
  310. /****************************************************************************
  311.  *
  312.  * FUNCTION:    bm_pr_add_device
  313.  *
  314.  * PARAMETERS:
  315.  *
  316.  * RETURN:
  317.  *
  318.  * DESCRIPTION:
  319.  *
  320.  ****************************************************************************/
  321. acpi_status
  322. bm_pr_add_device (
  323. BM_HANDLE               device_handle,
  324. void                    **context)
  325. {
  326. acpi_status             status = AE_OK;
  327. BM_POWER_RESOURCE *pr = NULL;
  328. BM_DEVICE *device = NULL;
  329. acpi_buffer buffer;
  330. acpi_object acpi_object;
  331. FUNCTION_TRACE("bm_pr_add_device");
  332. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Adding power resource [%02x].n", device_handle));
  333. if (!context || *context) {
  334. return_ACPI_STATUS(AE_BAD_PARAMETER);
  335. }
  336. buffer.length = sizeof(acpi_object);
  337. buffer.pointer = &acpi_object;
  338. /*
  339.  * Get information on this device.
  340.  */
  341. status = bm_get_device_info(device_handle, &device);
  342. if (ACPI_FAILURE(status)) {
  343. return_ACPI_STATUS(status);
  344. }
  345. /*
  346.  * Allocate a new BM_POWER_RESOURCE structure.
  347.  */
  348. pr = acpi_os_callocate(sizeof(BM_POWER_RESOURCE));
  349. if (!pr) {
  350. return_ACPI_STATUS(AE_NO_MEMORY);
  351. }
  352. pr->device_handle = device->handle;
  353. pr->acpi_handle = device->acpi_handle;
  354. /*
  355.  * Get information on this power resource.
  356.  */
  357. status = acpi_evaluate_object(pr->acpi_handle, NULL, NULL, &buffer);
  358. if (ACPI_FAILURE(status)) {
  359. goto end;
  360. }
  361. pr->system_level = acpi_object.power_resource.system_level;
  362. pr->resource_order = acpi_object.power_resource.resource_order;
  363. pr->state = ACPI_STATE_UNKNOWN;
  364. pr->reference_count = 0;
  365. /*
  366.  * Get the power resource's current state (ON|OFF).
  367.  */
  368. status = bm_pr_get_state(pr);
  369. end:
  370. if (ACPI_FAILURE(status)) {
  371. acpi_os_free(pr);
  372. }
  373. else {
  374. *context = pr;
  375. bm_pr_print(pr);
  376. }
  377. return_ACPI_STATUS(status);
  378. }
  379. /****************************************************************************
  380.  *
  381.  * FUNCTION:    bm_pr_remove_device
  382.  *
  383.  * PARAMETERS:
  384.  *
  385.  * RETURN:
  386.  *
  387.  * DESCRIPTION:
  388.  *
  389.  ****************************************************************************/
  390. acpi_status
  391. bm_pr_remove_device (
  392. void                    **context)
  393. {
  394. acpi_status             status = AE_OK;
  395. BM_POWER_RESOURCE *pr = NULL;
  396. FUNCTION_TRACE("bm_pr_remove_device");
  397. if (!context || !*context) {
  398. return_ACPI_STATUS(AE_BAD_PARAMETER);
  399. }
  400. pr = (BM_POWER_RESOURCE*)*context;
  401. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing power resource [%02x].n", pr->device_handle));
  402. acpi_os_free(pr);
  403. return_ACPI_STATUS(status);
  404. }
  405. /****************************************************************************
  406.  *                             External Functions
  407.  ****************************************************************************/
  408. /****************************************************************************
  409.  *
  410.  * FUNCTION:    bm_pr_initialize
  411.  *
  412.  * PARAMETERS:  <none>
  413.  *
  414.  * RETURN:
  415.  *
  416.  * DESCRIPTION:
  417.  *
  418.  ****************************************************************************/
  419. acpi_status
  420. bm_pr_initialize (void)
  421. {
  422. acpi_status             status = AE_OK;
  423. BM_DEVICE_ID criteria;
  424. BM_DRIVER driver;
  425. FUNCTION_TRACE("bm_pr_initialize");
  426. MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
  427. MEMSET(&driver, 0, sizeof(BM_DRIVER));
  428. criteria.type = BM_TYPE_POWER_RESOURCE;
  429. driver.notify = &bm_pr_notify;
  430. driver.request = &bm_pr_request;
  431. status = bm_register_driver(&criteria, &driver);
  432. return_ACPI_STATUS(status);
  433. }
  434. /****************************************************************************
  435.  *
  436.  * FUNCTION:    bm_pr_terminate
  437.  *
  438.  * PARAMETERS:
  439.  *
  440.  * RETURN:
  441.  *
  442.  * DESCRIPTION:
  443.  *
  444.  ****************************************************************************/
  445. acpi_status
  446. bm_pr_terminate (void)
  447. {
  448. acpi_status             status = AE_OK;
  449. BM_DEVICE_ID criteria;
  450. BM_DRIVER driver;
  451. FUNCTION_TRACE("bm_pr_terminate");
  452. MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
  453. MEMSET(&driver, 0, sizeof(BM_DRIVER));
  454. criteria.type = BM_TYPE_POWER_RESOURCE;
  455. driver.notify = &bm_pr_notify;
  456. driver.request = &bm_pr_request;
  457. status = bm_unregister_driver(&criteria, &driver);
  458. return_ACPI_STATUS(status);
  459. }
  460. /****************************************************************************
  461.  *
  462.  * FUNCTION:    bm_pr_notify
  463.  *
  464.  * PARAMETERS:
  465.  *
  466.  * RETURN:
  467.  *
  468.  * DESCRIPTION:
  469.  *
  470.  ****************************************************************************/
  471. acpi_status
  472. bm_pr_notify (
  473. BM_NOTIFY               notify_type,
  474. BM_HANDLE               device_handle,
  475. void                    **context)
  476. {
  477. acpi_status             status = AE_OK;
  478. FUNCTION_TRACE("bm_pr_notify");
  479. switch (notify_type) {
  480. case BM_NOTIFY_DEVICE_ADDED:
  481. status = bm_pr_add_device(device_handle, context);
  482. break;
  483. case BM_NOTIFY_DEVICE_REMOVED:
  484. status = bm_pr_remove_device(context);
  485. break;
  486. default:
  487. status = AE_SUPPORT;
  488. break;
  489. }
  490. return_ACPI_STATUS(status);
  491. }
  492. /****************************************************************************
  493.  *
  494.  * FUNCTION:    bm_pr_request
  495.  *
  496.  * PARAMETERS:
  497.  *
  498.  * RETURN:
  499.  *
  500.  * DESCRIPTION:
  501.  *
  502.  ****************************************************************************/
  503. acpi_status
  504. bm_pr_request (
  505. BM_REQUEST *request,
  506. void                    *context)
  507. {
  508. acpi_status             status = AE_OK;
  509. BM_POWER_RESOURCE *pr = NULL;
  510. FUNCTION_TRACE("bm_pr_request");
  511. /*
  512.  * Must have a valid request structure and context.
  513.  */
  514. if (!request || !context) {
  515. return_ACPI_STATUS(AE_BAD_PARAMETER);
  516. }
  517. /*
  518.  * context contains information specific to this power resource.
  519.  */
  520. pr = (BM_POWER_RESOURCE*)context;
  521. /*
  522.  * Handle request:
  523.  * ---------------
  524.  */
  525. switch (request->command) {
  526. default:
  527. status = AE_SUPPORT;
  528. break;
  529. }
  530. request->status = status;
  531. return_ACPI_STATUS(status);
  532. }