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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  *
  3.  * Module Name: pr.c
  4.  *   $Revision: 34 $
  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. #include <acpi.h>
  25. #include <bm.h>
  26. #include "pr.h"
  27. #define _COMPONENT ACPI_PROCESSOR
  28. MODULE_NAME ("pr")
  29. /****************************************************************************
  30.  *                                  Globals
  31.  ****************************************************************************/
  32. extern fadt_descriptor_rev2 acpi_fadt;
  33. /****************************************************************************
  34.  *                             Internal Functions
  35.  ****************************************************************************/
  36. /****************************************************************************
  37.  *
  38.  * FUNCTION:    pr_print
  39.  *
  40.  * PARAMETERS:
  41.  *
  42.  * RETURN:
  43.  *
  44.  * DESCRIPTION: Prints out information on a specific thermal zone.
  45.  *
  46.  ****************************************************************************/
  47. void
  48. pr_print (
  49. PR_CONTEXT              *processor)
  50. {
  51. #ifdef ACPI_DEBUG
  52. acpi_buffer             buffer;
  53. FUNCTION_TRACE("pr_print");
  54. buffer.length = 256;
  55. buffer.pointer = acpi_os_callocate(buffer.length);
  56. if (!buffer.pointer) {
  57. return;
  58. }
  59. /*
  60.  * Get the full pathname for this ACPI object.
  61.  */
  62. acpi_get_name(processor->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
  63. /*
  64.  * Print out basic processor information.
  65.  */
  66. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------n"));
  67. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| Processor[%02x]:[%p] uid[%02x] %sn", processor->device_handle, processor->acpi_handle, processor->uid, (char*)buffer.pointer));
  68. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "|   power: %cC0 %cC1 %cC2[%d] %cC3[%d]n", (processor->power.state[0].is_valid?'+':'-'), (processor->power.state[1].is_valid?'+':'-'), (processor->power.state[2].is_valid?'+':'-'), processor->power.state[2].latency, (processor->power.state[3].is_valid?'+':'-'), processor->power.state[3].latency));
  69. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "|   performance: states[%d]n", processor->performance.state_count));
  70. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------n"));
  71. acpi_os_free(buffer.pointer);
  72. #endif /* ACPI_DEBUG */
  73. return;
  74. }
  75. /****************************************************************************
  76.  *
  77.  * FUNCTION:    pr_add_device
  78.  *
  79.  * PARAMETERS:  <none>
  80.  *
  81.  * RETURN:
  82.  *
  83.  * DESCRIPTION:
  84.  *
  85.  ****************************************************************************/
  86. acpi_status
  87. pr_add_device(
  88. BM_HANDLE device_handle,
  89. void **context)
  90. {
  91. acpi_status status = AE_OK;
  92. PR_CONTEXT *processor = NULL;
  93. BM_DEVICE *device = NULL;
  94. acpi_buffer buffer;
  95. acpi_object acpi_object;
  96. static u32 processor_count = 0;
  97. FUNCTION_TRACE("pr_add_device");
  98. if (!context || *context) {
  99. return_ACPI_STATUS(AE_BAD_PARAMETER);
  100. }
  101. status = bm_get_device_info(device_handle, &device);
  102. if (ACPI_FAILURE(status)) {
  103. return_ACPI_STATUS(status);
  104. }
  105. processor = acpi_os_callocate(sizeof(PR_CONTEXT));
  106. if (!processor) {
  107. return AE_NO_MEMORY;
  108. }
  109. processor->device_handle = device->handle;
  110. processor->acpi_handle = device->acpi_handle;
  111. /*
  112.  * Processor Block:
  113.  * ----------------
  114.  */
  115. memset(&acpi_object, 0, sizeof(acpi_object));
  116. buffer.length = sizeof(acpi_object);
  117. buffer.pointer = &acpi_object;
  118. status = acpi_evaluate_object(processor->acpi_handle, NULL, NULL, &buffer);
  119. if (ACPI_FAILURE(status)) {
  120. goto end;
  121. }
  122. /*
  123.  * Processor ID:
  124.  * -------------
  125.  * TBD:  We need to synchronize the processor ID values in ACPI
  126.  *       with those of the APIC.  For example, an IBM T20 has a
  127.  *       proc_id value of '1', where the Linux value for the
  128.  *       first CPU on this system is '0'.  Since x86 CPUs are
  129.  *       mapped 1:1 we can simply use a zero-based counter.  Note
  130.  *       that this assumes that processor objects are enumerated
  131.  *       in the proper order.
  132.  */
  133. /* processor->uid = acpi_object.processor.proc_id; */
  134. processor->uid = processor_count++;
  135. processor->pblk.length = acpi_object.processor.pblk_length;
  136. processor->pblk.address = acpi_object.processor.pblk_address;
  137. status = pr_power_add_device(processor);
  138. if (ACPI_FAILURE(status)) {
  139. goto end;
  140. }
  141. status = pr_perf_add_device(processor);
  142. if (ACPI_FAILURE(status)) {
  143. goto end;
  144. }
  145. status = pr_osl_add_device(processor);
  146. if (ACPI_FAILURE(status)) {
  147. goto end;
  148. }
  149. *context = processor;
  150. pr_print(processor);
  151. end:
  152. if (ACPI_FAILURE(status)) {
  153. acpi_os_free(processor);
  154. }
  155. return_ACPI_STATUS(status);
  156. }
  157. /****************************************************************************
  158.  *
  159.  * FUNCTION:    pr_remove_device
  160.  *
  161.  * PARAMETERS:  <none>
  162.  *
  163.  * RETURN:
  164.  *
  165.  * DESCRIPTION:
  166.  *
  167.  ****************************************************************************/
  168. acpi_status
  169. pr_remove_device (
  170. void **context)
  171. {
  172. acpi_status status = AE_OK;
  173. PR_CONTEXT *processor= NULL;
  174. FUNCTION_TRACE("pr_remove_device");
  175. if (!context || !*context) {
  176. return_ACPI_STATUS(AE_BAD_PARAMETER);
  177. }
  178. processor = (PR_CONTEXT*)(*context);
  179. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing processor device [%02x].n", processor->device_handle));
  180. pr_osl_remove_device(processor);
  181. pr_perf_remove_device(processor);
  182. pr_power_remove_device(processor);
  183. acpi_os_free(processor);
  184. return_ACPI_STATUS(status);
  185. }
  186. /****************************************************************************
  187.  *                            External Functions
  188.  ****************************************************************************/
  189. /****************************************************************************
  190.  *
  191.  * FUNCTION:    pr_initialize
  192.  *
  193.  * PARAMETERS:  <none>
  194.  *
  195.  * RETURN:
  196.  *
  197.  * DESCRIPTION:
  198.  *
  199.  ****************************************************************************/
  200. acpi_status
  201. pr_initialize (void)
  202. {
  203. acpi_status status = AE_OK;
  204. BM_DEVICE_ID criteria;
  205. BM_DRIVER driver;
  206. FUNCTION_TRACE("pr_initialize");
  207. memset(&criteria, 0, sizeof(BM_DEVICE_ID));
  208. memset(&driver, 0, sizeof(BM_DRIVER));
  209. /*
  210.  * Initialize power (Cx state) policy.
  211.  */
  212. status = pr_power_initialize();
  213. if (ACPI_FAILURE(status)) {
  214. return_ACPI_STATUS(status);
  215. }
  216. /*
  217.  * Register driver for processor devices.
  218.  */
  219. criteria.type = BM_TYPE_PROCESSOR;
  220. driver.notify = &pr_notify;
  221. driver.request = &pr_request;
  222. status = bm_register_driver(&criteria, &driver);
  223. return_ACPI_STATUS(status);
  224. }
  225. /****************************************************************************
  226.  *
  227.  * FUNCTION:    pr_terminate
  228.  *
  229.  * PARAMETERS:  <none>
  230.  *
  231.  * RETURN:
  232.  *
  233.  * DESCRIPTION:
  234.  *
  235.  ****************************************************************************/
  236. acpi_status
  237. pr_terminate (void)
  238. {
  239. acpi_status             status = AE_OK;
  240. BM_DEVICE_ID criteria;
  241. BM_DRIVER driver;
  242. FUNCTION_TRACE("pr_terminate");
  243. memset(&criteria, 0, sizeof(BM_DEVICE_ID));
  244. memset(&driver, 0, sizeof(BM_DRIVER));
  245. /*
  246.  * Terminate power (Cx state) policy.
  247.  */
  248. status = pr_power_terminate();
  249. if (ACPI_FAILURE(status)) {
  250. return_ACPI_STATUS(status);
  251. }
  252. /*
  253.  * Unegister driver for processor devices.
  254.  */
  255. criteria.type = BM_TYPE_PROCESSOR;
  256. driver.notify = &pr_notify;
  257. driver.request = &pr_request;
  258. status = bm_unregister_driver(&criteria, &driver);
  259. return_ACPI_STATUS(status);
  260. }
  261. /****************************************************************************
  262.  *
  263.  * FUNCTION:    pr_notify
  264.  *
  265.  * PARAMETERS:
  266.  *
  267.  * RETURN:
  268.  *
  269.  * DESCRIPTION:
  270.  *
  271.  ****************************************************************************/
  272. acpi_status
  273. pr_notify (
  274. BM_NOTIFY notify_type,
  275. BM_HANDLE device_handle,
  276. void **context)
  277. {
  278. acpi_status status = AE_OK;
  279. PR_CONTEXT *processor = NULL;
  280. FUNCTION_TRACE("pr_notify");
  281. processor = (PR_CONTEXT*)*context;
  282. switch (notify_type) {
  283. case BM_NOTIFY_DEVICE_ADDED:
  284. status = pr_add_device(device_handle, context);
  285. break;
  286. case BM_NOTIFY_DEVICE_REMOVED:
  287. status = pr_remove_device(context);
  288. break;
  289. case PR_NOTIFY_PERF_STATES:
  290. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Performance states change event detected on processor [%02x].n", device_handle));
  291. /* TBD: Streamline (this is simple but overkill). */
  292. status = pr_perf_remove_device(processor);
  293. if (ACPI_SUCCESS(status)) {
  294. status = pr_perf_add_device(processor);
  295. }
  296. if (ACPI_SUCCESS(status)) {
  297. status = pr_osl_generate_event(notify_type,
  298. (processor));
  299. }
  300. break;
  301. case PR_NOTIFY_POWER_STATES:
  302. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Power states change event detected on processor [%02x].n", device_handle));
  303. /* TBD: Streamline (this is simple but overkill). */
  304. status = pr_power_remove_device(processor);
  305. if (ACPI_SUCCESS(status)) {
  306. status = pr_power_add_device(processor);
  307. }
  308. if (ACPI_SUCCESS(status)) {
  309. status = pr_osl_generate_event(notify_type,
  310. (processor));
  311. }
  312. break;
  313. default:
  314. status = AE_SUPPORT;
  315. break;
  316. }
  317. return_ACPI_STATUS(status);
  318. }
  319. /****************************************************************************
  320.  *
  321.  * FUNCTION:    pr_request
  322.  *
  323.  * PARAMETERS:
  324.  *
  325.  * RETURN:
  326.  *
  327.  * DESCRIPTION:
  328.  *
  329.  ****************************************************************************/
  330. acpi_status
  331. pr_request (
  332. BM_REQUEST *request,
  333. void *context)
  334. {
  335. acpi_status status = AE_OK;
  336. PR_CONTEXT *processor = NULL;
  337. FUNCTION_TRACE("pr_request");
  338. /*
  339.  * Must have a valid request structure and context.
  340.  */
  341. if (!request || !context) {
  342. return_ACPI_STATUS(AE_BAD_PARAMETER);
  343. }
  344. processor = (PR_CONTEXT*)context;
  345. /*
  346.  * Handle request:
  347.  * ---------------
  348.  */
  349. switch (request->command) {
  350. case PR_COMMAND_GET_POWER_INFO:
  351. status = bm_copy_to_buffer(&(request->buffer),
  352. &(processor->power), sizeof(PR_POWER));
  353. break;
  354. case PR_COMMAND_SET_POWER_INFO:
  355.  {
  356. PR_POWER *power_info = NULL;
  357. u32 i = 0;
  358. status = bm_cast_buffer(&(request->buffer),
  359. (void**)&power_info, sizeof(PR_POWER));
  360. if (ACPI_SUCCESS(status)) {
  361. for (i=0; i<processor->power.state_count; i++) {
  362. MEMCPY(&(processor->power.state[i].promotion),
  363. &(power_info->state[i].promotion),
  364. sizeof(PR_CX_POLICY_VALUES));
  365. MEMCPY(&(processor->power.state[i].demotion),
  366. &(power_info->state[i].demotion),
  367. sizeof(PR_CX_POLICY_VALUES));
  368. }
  369. }
  370. }
  371. break;
  372. case PR_COMMAND_GET_PERF_INFO:
  373. status = bm_copy_to_buffer(&(request->buffer),
  374. &(processor->performance), sizeof(PR_PERFORMANCE));
  375. break;
  376. case PR_COMMAND_GET_PERF_STATE:
  377. status = bm_copy_to_buffer(&(request->buffer),
  378. &(processor->performance.active_state), sizeof(u32));
  379. break;
  380. case PR_COMMAND_SET_PERF_LIMIT:
  381.  {
  382. u32 *limit = NULL;
  383. status = bm_cast_buffer(&(request->buffer),
  384. (void**)&limit, sizeof(u32));
  385. if (ACPI_SUCCESS(status)) {
  386. status = pr_perf_set_limit(processor, *limit);
  387. }
  388. }
  389. break;
  390. default:
  391. status = AE_SUPPORT;
  392. break;
  393. }
  394. request->status = status;
  395. return_ACPI_STATUS(status);
  396. }