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

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: bm.c
  4.  *   $Revision: 48 $
  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 <linux/kernel.h>
  25. #include <linux/module.h>
  26. #include <linux/init.h>
  27. #include <acpi.h>
  28. #include "bm.h"
  29. #define _COMPONENT ACPI_BUS
  30. MODULE_NAME ("bm")
  31. /****************************************************************************
  32.  *                                  Globals
  33.  ****************************************************************************/
  34. extern fadt_descriptor_rev2 acpi_fadt;
  35. /* TBD: Make dynamically sizeable. */
  36. BM_NODE_LIST node_list;
  37. /****************************************************************************
  38.  *                            Internal Functions
  39.  ****************************************************************************/
  40. /*****************************************************************************
  41.  *
  42.  * FUNCTION:    bm_print_object
  43.  *
  44.  * PARAMETERS:
  45.  *
  46.  * RETURN:
  47.  *
  48.  * DESCRIPTION:
  49.  *
  50.  ****************************************************************************/
  51. void
  52. bm_print_object (
  53. acpi_handle handle)
  54. {
  55. acpi_buffer buffer;
  56. acpi_handle parent;
  57. acpi_object_type type;
  58. buffer.length = 256;
  59. buffer.pointer = acpi_os_callocate(buffer.length);
  60. if (!buffer.pointer) {
  61. return;
  62. }
  63. acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
  64. acpi_get_parent(handle, &parent);
  65. acpi_get_type(handle, &type);
  66. /*
  67.  * TBD: Hack to get around scope identification problem.
  68.  */
  69. if (type == ACPI_TYPE_ANY) {
  70. if (ACPI_SUCCESS(acpi_get_next_object(ACPI_TYPE_ANY,
  71. handle, 0, NULL))) {
  72. type = INTERNAL_TYPE_SCOPE;
  73. }
  74. }
  75. switch (type)
  76.  {
  77. case INTERNAL_TYPE_SCOPE:
  78. acpi_os_printf("SCOPE: ");
  79. break;
  80. case ACPI_TYPE_INTEGER:
  81. acpi_os_printf("SIMPLE (number): ");
  82. break;
  83. case ACPI_TYPE_STRING:
  84. acpi_os_printf("SIMPLE (string): ");
  85. break;
  86. case ACPI_TYPE_BUFFER:
  87. acpi_os_printf("SIMPLE (buffer): ");
  88. break;
  89. case ACPI_TYPE_PACKAGE:
  90. acpi_os_printf("SIMPLE (package): ");
  91. break;
  92. case ACPI_TYPE_FIELD_UNIT:
  93. acpi_os_printf("FIELD UNIT: ");
  94. break;
  95. case ACPI_TYPE_DEVICE:
  96. acpi_os_printf("DEVICE: ");
  97. break;
  98. case ACPI_TYPE_EVENT:
  99. acpi_os_printf("EVENT: ");
  100. break;
  101. case ACPI_TYPE_METHOD:
  102. acpi_os_printf("CONTROL METHOD: ");
  103. break;
  104. case ACPI_TYPE_MUTEX:
  105. acpi_os_printf("MUTEX: ");
  106. break;
  107. case ACPI_TYPE_REGION:
  108. acpi_os_printf("OPERATION REGION: ");
  109. break;
  110. case ACPI_TYPE_POWER:
  111. acpi_os_printf("POWER RESOURCE: ");
  112. break;
  113. case ACPI_TYPE_PROCESSOR:
  114. acpi_os_printf("PROCESSOR: ");
  115. break;
  116. case ACPI_TYPE_THERMAL:
  117. acpi_os_printf("THERMAL ZONE: ");
  118. break;
  119. case ACPI_TYPE_BUFFER_FIELD:
  120. acpi_os_printf("BUFFER FIELD: ");
  121. break;
  122. case ACPI_TYPE_DDB_HANDLE:
  123. acpi_os_printf("DDB HANDLE: ");
  124. break;
  125. default:
  126. acpi_os_printf("OTHER (%d): ", type);
  127. break;
  128. }
  129. acpi_os_printf("Object[%p][%s] parent[%p].n", handle, (char*)buffer.pointer, parent);
  130. acpi_os_free(buffer.pointer);
  131. }
  132. /****************************************************************************
  133.  *
  134.  * FUNCTION:    bm_print_node
  135.  *
  136.  * PARAMETERS:
  137.  *
  138.  * RETURN:
  139.  *
  140.  * DESCRIPTION:
  141.  *
  142.  ****************************************************************************/
  143. void
  144. bm_print_node (
  145. BM_NODE *node,
  146. u32                     flags)
  147. {
  148. #ifdef ACPI_DEBUG
  149. acpi_buffer             buffer;
  150. BM_DEVICE *device = NULL;
  151. char                    *type_string = NULL;
  152. PROC_NAME("bm_print_node");
  153. if (!node) {
  154. return;
  155. }
  156. device = &(node->device);
  157. if (flags & BM_PRINT_PRESENT) {
  158. if (!BM_DEVICE_PRESENT(device)) {
  159. return;
  160. }
  161. }
  162. buffer.length = 256;
  163. buffer.pointer = acpi_os_callocate(buffer.length);
  164. if (!buffer.pointer) {
  165. return;
  166. }
  167. acpi_get_name(device->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
  168. switch(device->id.type) {
  169. case BM_TYPE_SYSTEM:
  170. type_string = " System";
  171. break;
  172. case BM_TYPE_SCOPE:
  173. type_string = "  Scope";
  174. break;
  175. case BM_TYPE_PROCESSOR:
  176. type_string = "   Proc";
  177. break;
  178. case BM_TYPE_THERMAL_ZONE:
  179. type_string = "Thermal";
  180. break;
  181. case BM_TYPE_POWER_RESOURCE:
  182. type_string = "  Power";
  183. break;
  184. case BM_TYPE_FIXED_BUTTON:
  185. type_string = " Button";
  186. break;
  187. case BM_TYPE_DEVICE:
  188. type_string = " Device";
  189. break;
  190. default:
  191. type_string = "Unknown";
  192. break;
  193. }
  194. if (!(flags & BM_PRINT_GROUP)) {
  195. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+-------------------------------------------------------------------------------n"));
  196. }
  197. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| %s[%02x]:[%p] flags[%02x] hid[%s] %sn", type_string, device->handle, device->acpi_handle, device->flags, (device->id.hid[0] ? device->id.hid : "       "), (char*)buffer.pointer));
  198. if (flags & BM_PRINT_IDENTIFICATION) {
  199. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "|   identification: uid[%s] adr[%08x]n", device->id.uid, device->id.adr));
  200. }
  201. if (flags & BM_PRINT_LINKAGE) {
  202. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "|   linkage: this[%p] parent[%p] next[%p]n", node, node->parent, node->next));
  203. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "|     scope.head[%p] scope.tail[%p]n", node->scope.head, node->scope.tail));
  204. }
  205. if (flags & BM_PRINT_POWER) {
  206. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "|   power: state[D%d] flags[%08x]n", device->power.state, device->power.flags));
  207. 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]));
  208. }
  209. if (!(flags & BM_PRINT_GROUP)) {
  210. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+-------------------------------------------------------------------------------n"));
  211. }
  212. acpi_os_free(buffer.pointer);
  213. #endif /*ACPI_DEBUG*/
  214. return;
  215. }
  216. /****************************************************************************
  217.  *
  218.  * FUNCTION:    bm_print_hierarchy
  219.  *
  220.  * PARAMETERS:
  221.  *
  222.  * RETURN:
  223.  *
  224.  * DESCRIPTION:
  225.  *
  226.  ****************************************************************************/
  227. void
  228. bm_print_hierarchy (void)
  229. {
  230. #ifdef ACPI_DEBUG
  231. u32 i = 0;
  232. FUNCTION_TRACE("bm_print_hierarchy");
  233. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------n"));
  234. for (i = 0; i < node_list.count; i++) {
  235. bm_print_node(node_list.nodes[i], BM_PRINT_GROUP | BM_PRINT_PRESENT);
  236. }
  237. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------n"));
  238. #endif /*ACPI_DEBUG*/
  239. return_VOID;
  240. }
  241. /****************************************************************************
  242.  *
  243.  * FUNCTION:    bm_get_status
  244.  *
  245.  * PARAMETERS:
  246.  *
  247.  * RETURN:
  248.  *
  249.  * DESCRIPTION:
  250.  *
  251.  ****************************************************************************/
  252. acpi_status
  253. bm_get_status (
  254. BM_DEVICE *device)
  255. {
  256. acpi_status           status = AE_OK;
  257. if (!device) {
  258. return AE_BAD_PARAMETER;
  259. }
  260. device->status = BM_STATUS_UNKNOWN;
  261. /*
  262.  * Dynamic Status?
  263.  * ---------------
  264.  * If _STA isn't present we just return the default status.
  265.  */
  266. if (!(device->flags & BM_FLAGS_DYNAMIC_STATUS)) {
  267. device->status = BM_STATUS_DEFAULT;
  268. return AE_OK;
  269. }
  270. /*
  271.  * Evaluate _STA:
  272.  * --------------
  273.  */
  274. status = bm_evaluate_simple_integer(device->acpi_handle, "_STA",
  275. &(device->status));
  276. return status;
  277. }
  278. /****************************************************************************
  279.  *
  280.  * FUNCTION:    bm_get_identification
  281.  *
  282.  * PARAMETERS:
  283.  *
  284.  * RETURN:
  285.  *
  286.  * DESCRIPTION:
  287.  *
  288.  ****************************************************************************/
  289. acpi_status
  290. bm_get_identification (
  291. BM_DEVICE *device)
  292. {
  293. acpi_status             status = AE_OK;
  294. acpi_device_info        info;
  295. if (!device) {
  296. return AE_BAD_PARAMETER;
  297. }
  298. if (!(device->flags & BM_FLAGS_IDENTIFIABLE)) {
  299. return AE_OK;
  300. }
  301. device->id.uid[0] = BM_UID_UNKNOWN;
  302. device->id.hid[0] = BM_HID_UNKNOWN;
  303. device->id.adr = BM_ADDRESS_UNKNOWN;
  304. /*
  305.  * Get Object Info:
  306.  * ----------------
  307.  * Evalute _UID, _HID, and _ADR...
  308.  */
  309. status = acpi_get_object_info(device->acpi_handle, &info);
  310. if (ACPI_FAILURE(status)) {
  311. return status;
  312. }
  313. if (info.valid & ACPI_VALID_UID) {
  314. MEMCPY((void*)device->id.uid, (void*)info.unique_id,
  315. sizeof(BM_DEVICE_UID));
  316. }
  317. if (info.valid & ACPI_VALID_HID) {
  318. MEMCPY((void*)device->id.hid, (void*)info.hardware_id,
  319. sizeof(BM_DEVICE_HID));
  320. }
  321. if (info.valid & ACPI_VALID_ADR) {
  322. device->id.adr = info.address;
  323. }
  324. return status;
  325. }
  326. /****************************************************************************
  327.  *
  328.  * FUNCTION:    bm_get_flags
  329.  *
  330.  * PARAMETERS:
  331.  *
  332.  * RETURN:
  333.  *
  334.  * DESCRIPTION:
  335.  *
  336.  ****************************************************************************/
  337. acpi_status
  338. bm_get_flags (
  339. BM_DEVICE *device)
  340. {
  341. acpi_handle acpi_handle = NULL;
  342. if (!device) {
  343. return AE_BAD_PARAMETER;
  344. }
  345. device->flags = BM_FLAGS_UNKNOWN;
  346. switch (device->id.type) {
  347. case BM_TYPE_DEVICE:
  348. /*
  349.  * Presence of _DCK indicates a docking station.
  350.  */
  351. if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
  352. "_DCK", &acpi_handle))) {
  353. device->flags |= BM_FLAGS_DOCKING_STATION;
  354. }
  355. /*
  356.  * Presence of _EJD and/or _EJx indicates 'ejectable'.
  357.  * TBD: _EJx...
  358.  */
  359. if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
  360. "_EJD", &acpi_handle))) {
  361. device->flags |= BM_FLAGS_EJECTABLE;
  362. }
  363. /*
  364.  * Presence of _PR0 or _PS0 indicates 'power manageable'.
  365.  */
  366. if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
  367. "_PR0", &acpi_handle)) ||
  368. ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
  369. "_PS0", &acpi_handle))) {
  370. device->flags |= BM_FLAGS_POWER_CONTROL;
  371. }
  372. /*
  373.  * Presence of _CRS indicates 'configurable'.
  374.  */
  375. if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
  376. "_CRS", &acpi_handle))) {
  377. device->flags |= BM_FLAGS_CONFIGURABLE;
  378. }
  379. /* Fall through to next case statement. */
  380. case BM_TYPE_PROCESSOR:
  381. case BM_TYPE_THERMAL_ZONE:
  382. case BM_TYPE_POWER_RESOURCE:
  383. /*
  384.  * Presence of _HID or _ADR indicates 'identifiable'.
  385.  */
  386. if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
  387. "_HID", &acpi_handle)) ||
  388.    ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
  389.    "_ADR", &acpi_handle))) {
  390. device->flags |= BM_FLAGS_IDENTIFIABLE;
  391. }
  392. /*
  393.  * Presence of _STA indicates 'dynamic status'.
  394.  */
  395. if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle,
  396. "_STA", &acpi_handle))) {
  397. device->flags |= BM_FLAGS_DYNAMIC_STATUS;
  398. }
  399. break;
  400. }
  401. return AE_OK;
  402. }
  403. /****************************************************************************
  404.  *
  405.  * FUNCTION:    bm_add_namespace_device
  406.  *
  407.  * PARAMETERS:
  408.  *
  409.  * RETURN:
  410.  *
  411.  * DESCRIPTION:
  412.  *
  413.  ****************************************************************************/
  414. acpi_status
  415. bm_add_namespace_device (
  416. acpi_handle             acpi_handle,
  417. acpi_object_type        acpi_type,
  418. BM_NODE *parent,
  419. BM_NODE **child)
  420. {
  421. acpi_status             status = AE_OK;
  422. BM_NODE *node = NULL;
  423. BM_DEVICE *device = NULL;
  424. FUNCTION_TRACE("bm_add_namespace_device");
  425. if (!parent || !child) {
  426. return_ACPI_STATUS(AE_BAD_PARAMETER);
  427. }
  428. if (node_list.count > BM_HANDLES_MAX) {
  429. return_ACPI_STATUS(AE_NO_MEMORY);
  430. }
  431. (*child) = NULL;
  432. /*
  433.  * Create Node:
  434.  * ------------
  435.  */
  436. node = acpi_os_callocate(sizeof(BM_NODE));
  437. if (!node) {
  438. return_ACPI_STATUS(AE_NO_MEMORY);
  439. }
  440. node->parent = parent;
  441. node->next = NULL;
  442. device = &(node->device);
  443. device->handle = node_list.count;
  444. device->acpi_handle = acpi_handle;
  445. /*
  446.  * Device Type:
  447.  * ------------
  448.  */
  449. switch (acpi_type) {
  450. case INTERNAL_TYPE_SCOPE:
  451. device->id.type = BM_TYPE_SCOPE;
  452. break;
  453. case ACPI_TYPE_PROCESSOR:
  454. device->id.type = BM_TYPE_PROCESSOR;
  455. break;
  456. case ACPI_TYPE_THERMAL:
  457. device->id.type = BM_TYPE_THERMAL_ZONE;
  458. break;
  459. case ACPI_TYPE_POWER:
  460. device->id.type = BM_TYPE_POWER_RESOURCE;
  461. break;
  462. case ACPI_TYPE_DEVICE:
  463. device->id.type = BM_TYPE_DEVICE;
  464. break;
  465. }
  466. /*
  467.  * Get Other Device Info:
  468.  * ----------------------
  469.  * But only if this device's parent is present (which implies
  470.  * this device MAY be present).
  471.  */
  472. if (BM_NODE_PRESENT(node->parent)) {
  473. /*
  474.  * Device Flags
  475.  */
  476. status = bm_get_flags(device);
  477. if (ACPI_FAILURE(status)) {
  478. goto end;
  479. }
  480. /*
  481.  * Device Identification
  482.  */
  483. status = bm_get_identification(device);
  484. if (ACPI_FAILURE(status)) {
  485. goto end;
  486. }
  487. /*
  488.  * Device Status
  489.  */
  490. status = bm_get_status(device);
  491. if (ACPI_FAILURE(status)) {
  492. goto end;
  493. }
  494. /*
  495.  * Power Management:
  496.  * -----------------
  497.  * If this node doesn't provide direct power control
  498.  * then we inherit PM capabilities from its parent.
  499.  *
  500.  * TBD: Inherit!
  501.  */
  502. if (BM_IS_POWER_CONTROL(device)) {
  503. status = bm_get_pm_capabilities(node);
  504. if (ACPI_FAILURE(status)) {
  505. goto end;
  506. }
  507. }
  508. }
  509. end:
  510. if (ACPI_FAILURE(status)) {
  511. acpi_os_free(node);
  512. }
  513. else {
  514. /*
  515.  * Add to the node_list.
  516.  */
  517. node_list.nodes[node_list.count++] = node;
  518. /*
  519.  * Formulate Hierarchy:
  520.  * --------------------
  521.  * Arrange within the namespace by assigning the parent and
  522.  * adding to the parent device's list of children (scope).
  523.  */
  524. if (!parent->scope.head) {
  525. parent->scope.head = node;
  526. }
  527. else {
  528. if (!parent->scope.tail) {
  529. (parent->scope.head)->next = node;
  530. }
  531. else {
  532. (parent->scope.tail)->next = node;
  533. }
  534. }
  535. parent->scope.tail = node;
  536. (*child) = node;
  537. }
  538. return_ACPI_STATUS(status);
  539. }
  540. /****************************************************************************
  541.  *
  542.  * FUNCTION:    bm_enumerate_namespace
  543.  *
  544.  * PARAMETERS:  <none>
  545.  *
  546.  * RETURN:
  547.  *
  548.  * DESCRIPTION:
  549.  *
  550.  ****************************************************************************/
  551. acpi_status
  552. bm_enumerate_namespace (void)
  553. {
  554. acpi_status status = AE_OK;
  555. acpi_handle             parent_handle = ACPI_ROOT_OBJECT;
  556. acpi_handle             child_handle = NULL;
  557. BM_NODE *parent = NULL;
  558. BM_NODE *child = NULL;
  559. acpi_object_type        acpi_type = 0;
  560. u32                     level = 1;
  561. FUNCTION_TRACE("bm_enumerate_namespace");
  562. parent = node_list.nodes[0];
  563. /*
  564.  * Enumerate ACPI Namespace:
  565.  * -------------------------
  566.  * Parse through the ACPI namespace, identify all 'devices',
  567.  * and create a new entry for each in our collection.
  568.  */
  569. while (level > 0) {
  570. /*
  571.  * Get the next object at this level.
  572.  */
  573. status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, child_handle, &child_handle);
  574. if (ACPI_SUCCESS(status)) {
  575. /*
  576.  * TBD: This is a hack to get around the problem
  577.  *       identifying scope objects.  Scopes
  578.  *       somehow need to be uniquely identified.
  579.  */
  580. status = acpi_get_type(child_handle, &acpi_type);
  581. if (ACPI_SUCCESS(status) && (acpi_type == ACPI_TYPE_ANY)) {
  582. status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL);
  583. if (ACPI_SUCCESS(status)) {
  584. acpi_type = INTERNAL_TYPE_SCOPE;
  585. }
  586. }
  587. /*
  588.  * Device?
  589.  * -------
  590.  * If this object is a 'device', insert into the
  591.  * ACPI Bus Manager's local hierarchy and search
  592.  * the object's scope for any child devices (a
  593.  * depth-first search).
  594.  */
  595. switch (acpi_type) {
  596. case INTERNAL_TYPE_SCOPE:
  597. case ACPI_TYPE_DEVICE:
  598. case ACPI_TYPE_PROCESSOR:
  599. case ACPI_TYPE_THERMAL:
  600. case ACPI_TYPE_POWER:
  601. status = bm_add_namespace_device(child_handle, acpi_type, parent, &child);
  602. if (ACPI_SUCCESS(status)) {
  603. status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL);
  604. if (ACPI_SUCCESS(status)) {
  605. level++;
  606. parent_handle = child_handle;
  607. child_handle = 0;
  608. parent = child;
  609. }
  610. }
  611. break;
  612. }
  613. }
  614. /*
  615.  * Scope Exhausted:
  616.  * ----------------
  617.  * No more children in this object's scope, Go back up
  618.  * in the namespace tree to the object's parent.
  619.  */
  620. else {
  621. level--;
  622. child_handle = parent_handle;
  623. acpi_get_parent(parent_handle,
  624. &parent_handle);
  625. if (parent) {
  626. parent = parent->parent;
  627. }
  628. else {
  629. return_ACPI_STATUS(AE_NULL_ENTRY);
  630. }
  631. }
  632. }
  633. return_ACPI_STATUS(AE_OK);
  634. }
  635. /****************************************************************************
  636.  *
  637.  * FUNCTION:    bm_add_fixed_feature_device
  638.  *
  639.  * PARAMETERS:
  640.  *
  641.  * RETURN:
  642.  *
  643.  * DESCRIPTION:
  644.  *
  645.  ****************************************************************************/
  646. acpi_status
  647. bm_add_fixed_feature_device (
  648. BM_NODE *parent,
  649. BM_DEVICE_TYPE device_type,
  650. char *device_hid)
  651. {
  652. acpi_status             status = AE_OK;
  653. BM_NODE *node = NULL;
  654. FUNCTION_TRACE("bm_add_fixed_feature_device");
  655. if (!parent) {
  656. return_ACPI_STATUS(AE_BAD_PARAMETER);
  657. }
  658. if (node_list.count > BM_HANDLES_MAX) {
  659. return_ACPI_STATUS(AE_NO_MEMORY);
  660. }
  661. /*
  662.  * Allocate the new device and add to the device array.
  663.  */
  664. node = acpi_os_callocate(sizeof(BM_NODE));
  665. if (!node) {
  666. return_ACPI_STATUS(AE_NO_MEMORY);
  667. }
  668. /*
  669.  * Get device info.
  670.  */
  671. node->device.handle = node_list.count;
  672. node->device.acpi_handle = ACPI_ROOT_OBJECT;
  673. node->device.id.type = BM_TYPE_FIXED_BUTTON;
  674. if (device_hid) {
  675. MEMCPY((void*)node->device.id.hid, device_hid,
  676. sizeof(node->device.id.hid));
  677. }
  678. node->device.flags = BM_FLAGS_FIXED_FEATURE;
  679. node->device.status = BM_STATUS_DEFAULT;
  680. /* TBD: Device PM capabilities */
  681. /*
  682.  * Add to the node_list.
  683.  */
  684. node_list.nodes[node_list.count++] = node;
  685. /*
  686.  * Formulate Hierarchy:
  687.  * --------------------
  688.  * Arrange within the namespace by assigning the parent and
  689.  * adding to the parent device's list of children (scope).
  690.  */
  691. node->parent = parent;
  692. node->next = NULL;
  693. if (parent) {
  694. if (!parent->scope.head) {
  695. parent->scope.head = node;
  696. }
  697. else {
  698. if (!parent->scope.tail) {
  699. (parent->scope.head)->next = node;
  700. }
  701. else {
  702. (parent->scope.tail)->next = node;
  703. }
  704. }
  705. parent->scope.tail = node;
  706. }
  707. return_ACPI_STATUS(status);
  708. }
  709. /****************************************************************************
  710.  *
  711.  * FUNCTION:    bm_enumerate_fixed_features
  712.  *
  713.  * PARAMETERS:  <none>
  714.  *
  715.  * RETURN:
  716.  *
  717.  * DESCRIPTION:
  718.  *
  719.  ****************************************************************************/
  720. acpi_status
  721. bm_enumerate_fixed_features (void)
  722. {
  723. FUNCTION_TRACE("bm_enumerate_fixed_features");
  724. /*
  725.  * Root Object:
  726.  * ------------
  727.  * Fabricate the root object, which happens to always get a
  728.  * device_handle of zero.
  729.  */
  730. node_list.nodes[0] = acpi_os_callocate(sizeof(BM_NODE));
  731. if (NULL == (node_list.nodes[0])) {
  732. return_ACPI_STATUS(AE_NO_MEMORY);
  733. }
  734. node_list.nodes[0]->device.handle = BM_HANDLE_ROOT;
  735. node_list.nodes[0]->device.acpi_handle = ACPI_ROOT_OBJECT;
  736. node_list.nodes[0]->device.flags = BM_FLAGS_UNKNOWN;
  737. node_list.nodes[0]->device.status = BM_STATUS_DEFAULT;
  738. node_list.nodes[0]->device.id.type = BM_TYPE_SYSTEM;
  739. /* TBD: Get system PM capabilities (Sx states?) */
  740. node_list.count++;
  741. /*
  742.  * Fixed Features:
  743.  * ---------------
  744.  * Enumerate fixed-feature devices (e.g. power and sleep buttons).
  745.  */
  746. if (acpi_fadt.pwr_button == 0) {
  747. bm_add_fixed_feature_device(node_list.nodes[0],
  748. BM_TYPE_FIXED_BUTTON, BM_HID_POWER_BUTTON);
  749. }
  750. if (acpi_fadt.sleep_button == 0) {
  751. bm_add_fixed_feature_device(node_list.nodes[0],
  752. BM_TYPE_FIXED_BUTTON, BM_HID_SLEEP_BUTTON);
  753. }
  754. return_ACPI_STATUS(AE_OK);
  755. }
  756. /****************************************************************************
  757.  *
  758.  * FUNCTION:    bm_get_handle
  759.  *
  760.  * PARAMETERS:
  761.  *
  762.  * RETURN:
  763.  *
  764.  * DESCRIPTION:
  765.  *
  766.  ****************************************************************************/
  767. acpi_status
  768. bm_get_handle (
  769. acpi_handle             acpi_handle,
  770. BM_HANDLE               *device_handle)
  771. {
  772. acpi_status             status = AE_NOT_FOUND;
  773. u32 i = 0;
  774. FUNCTION_TRACE("bm_get_handle");
  775. if (!device_handle) {
  776. return_ACPI_STATUS(AE_BAD_PARAMETER);
  777. }
  778. *device_handle = BM_HANDLE_UNKNOWN;
  779. /*
  780.  * Search all devices for a match on the ACPI handle.
  781.  */
  782. for (i=0; i<node_list.count; i++) {
  783. if (!node_list.nodes[i]) {
  784. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) node entry [%p] detected.n", device_handle));
  785. status = AE_NULL_ENTRY;
  786. break;
  787. }
  788. if (node_list.nodes[i]->device.acpi_handle == acpi_handle) {
  789. *device_handle = node_list.nodes[i]->device.handle;
  790. status = AE_OK;
  791. break;
  792. }
  793. }
  794. return_ACPI_STATUS(status);
  795. }
  796. /****************************************************************************
  797.  *
  798.  * FUNCTION:    bm_get_node
  799.  *
  800.  * PARAMETERS:
  801.  *
  802.  * RETURN:
  803.  *
  804.  * DESCRIPTION:
  805.  *
  806.  ****************************************************************************/
  807. acpi_status
  808. bm_get_node (
  809. BM_HANDLE               device_handle,
  810. acpi_handle             acpi_handle,
  811. BM_NODE **node)
  812. {
  813. acpi_status             status = AE_OK;
  814. FUNCTION_TRACE("bm_get_node");
  815. if (!node) {
  816. return_ACPI_STATUS(AE_BAD_PARAMETER);
  817. }
  818. /* busmgr failed to init, but we're being called by subordinate drivers */
  819. if (node_list.count < 1) {
  820. return_ACPI_STATUS(AE_NOT_FOUND);
  821. }
  822. /*
  823.  * If no device handle, resolve acpi handle to device handle.
  824.  */
  825. if (!device_handle && acpi_handle) {
  826. status = bm_get_handle(acpi_handle, &device_handle);
  827. if (ACPI_FAILURE(status))
  828. return_ACPI_STATUS(status);
  829. }
  830. /*
  831.  * Valid device handle?
  832.  */
  833. if (device_handle > BM_HANDLES_MAX) {
  834. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid node handle [%02x] detected.n", device_handle));
  835. return_ACPI_STATUS(AE_ERROR);
  836. }
  837. *node = node_list.nodes[device_handle];
  838. /*
  839.  * Valid node?
  840.  */
  841. if (!(*node)) {
  842. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) node entry [%02x] detected.n", device_handle));
  843. return_ACPI_STATUS(AE_NULL_ENTRY);
  844. }
  845. return_ACPI_STATUS(AE_OK);
  846. }
  847. /****************************************************************************
  848.  *                            External Functions
  849.  ****************************************************************************/
  850. /****************************************************************************
  851.  *
  852.  * FUNCTION:    bm_initialize
  853.  *
  854.  * PARAMETERS:  <none>
  855.  *
  856.  * RETURN:      Exception code.
  857.  *
  858.  * DESCRIPTION:
  859.  *
  860.  ****************************************************************************/
  861. acpi_status
  862. bm_initialize (void)
  863. {
  864. acpi_status             status = AE_OK;
  865. u32                     start = 0;
  866. u32                     stop = 0;
  867. u32                     elapsed = 0;
  868. FUNCTION_TRACE("bm_initialize");
  869. MEMSET(&node_list, 0, sizeof(BM_NODE_LIST));
  870. status = acpi_get_timer(&start);
  871. if (ACPI_FAILURE(status)) {
  872. return_ACPI_STATUS(status);
  873. }
  874. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Building device hierarchy.n"));
  875. /*
  876.  * Enumerate ACPI fixed-feature devices.
  877.  */
  878. status = bm_enumerate_fixed_features();
  879. if (ACPI_FAILURE(status)) {
  880. return_ACPI_STATUS(status);
  881. }
  882. /*
  883.  * Enumerate the ACPI namespace.
  884.  */
  885. status = bm_enumerate_namespace();
  886. if (ACPI_FAILURE(status)) {
  887. return_ACPI_STATUS(status);
  888. }
  889. acpi_get_timer(&stop);
  890. acpi_get_timer_duration(start, stop, &elapsed);
  891. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Building device hierarchy took [%d] microseconds.n", elapsed));
  892. /*
  893.  * Display hierarchy.
  894.  */
  895. bm_print_hierarchy();
  896. /*
  897.  * Register for all standard and device-specific notifications.
  898.  */
  899. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registering for all device notifications.n"));
  900. status = acpi_install_notify_handler(ACPI_ROOT_OBJECT,
  901. ACPI_SYSTEM_NOTIFY, &bm_notify, NULL);
  902. if (ACPI_FAILURE(status)) {
  903. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unable to register for standard notifications.n"));
  904. return_ACPI_STATUS(status);
  905. }
  906. status = acpi_install_notify_handler(ACPI_ROOT_OBJECT,
  907. ACPI_DEVICE_NOTIFY, &bm_notify, NULL);
  908. if (ACPI_FAILURE(status)) {
  909. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unable to register for device-specific notifications.n"));
  910. return_ACPI_STATUS(status);
  911. }
  912. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Bus Manager enabled.n"));
  913. /*
  914.  * Initialize built-in power resource driver.
  915.  */
  916. bm_pr_initialize();
  917. return_ACPI_STATUS(status);
  918. }
  919. /****************************************************************************
  920.  *
  921.  * FUNCTION:    bm_terminate
  922.  *
  923.  * PARAMETERS:  <none>
  924.  *
  925.  * RETURN:      Exception code.
  926.  *
  927.  * DESCRIPTION:
  928.  *
  929.  ****************************************************************************/
  930. acpi_status
  931. bm_terminate (void)
  932. {
  933. acpi_status             status = AE_OK;
  934. u32                     i = 0;
  935. FUNCTION_TRACE("bm_terminate");
  936. /*
  937.  * Terminate built-in power resource driver.
  938.  */
  939. bm_pr_terminate();
  940. /*
  941.  * Unregister for all notifications.
  942.  */
  943. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Unregistering for device notifications.n"));
  944. status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT,
  945. ACPI_SYSTEM_NOTIFY, &bm_notify);
  946. if (ACPI_FAILURE(status)) {
  947. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unable to un-register for standard notifications.n"));
  948. }
  949. status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT,
  950. ACPI_DEVICE_NOTIFY, &bm_notify);
  951. if (ACPI_FAILURE(status)) {
  952. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unable to un-register for device-specific notifications.n"));
  953. }
  954. /*
  955.  * Parse through the device array, freeing all entries.
  956.  */
  957. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing device hierarchy.n"));
  958. for (i = 0; i < node_list.count; i++) {
  959. if (node_list.nodes[i]) {
  960. acpi_os_free(node_list.nodes[i]);
  961. }
  962. }
  963. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Bus Manager disabled.n"));
  964. return_ACPI_STATUS(AE_OK);
  965. }