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

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: evrgnini- ACPI Address_space (Op_region) init
  4.  *              $Revision: 48 $
  5.  *
  6.  *****************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 R. Byron Moore
  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 "acevents.h"
  26. #include "acnamesp.h"
  27. #include "acinterp.h"
  28. #include "amlcode.h"
  29. #define _COMPONENT          ACPI_EVENTS
  30.  MODULE_NAME         ("evrgnini")
  31. /*******************************************************************************
  32.  *
  33.  * FUNCTION:    Acpi_ev_system_memory_region_setup
  34.  *
  35.  * PARAMETERS:  Region_obj          - region we are interested in
  36.  *              Function            - start or stop
  37.  *              Handler_context     - Address space handler context
  38.  *              Region_context      - Region specific context
  39.  *
  40.  * RETURN:      Status
  41.  *
  42.  * DESCRIPTION: Do any prep work for region handling, a nop for now
  43.  *
  44.  ******************************************************************************/
  45. acpi_status
  46. acpi_ev_system_memory_region_setup (
  47. acpi_handle             handle,
  48. u32                     function,
  49. void                    *handler_context,
  50. void                    **region_context)
  51. {
  52. FUNCTION_TRACE ("Ev_system_memory_region_setup");
  53. if (function == ACPI_REGION_DEACTIVATE) {
  54. if (*region_context) {
  55. ACPI_MEM_FREE (*region_context);
  56. *region_context = NULL;
  57. }
  58. return_ACPI_STATUS (AE_OK);
  59. }
  60. /* Activate.  Create a new context */
  61. *region_context = ACPI_MEM_CALLOCATE (sizeof (acpi_mem_space_context));
  62. if (!(*region_context)) {
  63. return_ACPI_STATUS (AE_NO_MEMORY);
  64. }
  65. return_ACPI_STATUS (AE_OK);
  66. }
  67. /*******************************************************************************
  68.  *
  69.  * FUNCTION:    Acpi_ev_io_space_region_setup
  70.  *
  71.  * PARAMETERS:  Region_obj          - region we are interested in
  72.  *              Function            - start or stop
  73.  *              Handler_context     - Address space handler context
  74.  *              Region_context      - Region specific context
  75.  *
  76.  * RETURN:      Status
  77.  *
  78.  * DESCRIPTION: Do any prep work for region handling
  79.  *
  80.  ******************************************************************************/
  81. acpi_status
  82. acpi_ev_io_space_region_setup (
  83. acpi_handle             handle,
  84. u32                     function,
  85. void                    *handler_context,
  86. void                    **region_context)
  87. {
  88. FUNCTION_TRACE ("Ev_io_space_region_setup");
  89. if (function == ACPI_REGION_DEACTIVATE) {
  90. *region_context = NULL;
  91. }
  92. else {
  93. *region_context = handler_context;
  94. }
  95. return_ACPI_STATUS (AE_OK);
  96. }
  97. /*******************************************************************************
  98.  *
  99.  * FUNCTION:    Acpi_ev_pci_config_region_setup
  100.  *
  101.  * PARAMETERS:  Region_obj          - region we are interested in
  102.  *              Function            - start or stop
  103.  *              Handler_context     - Address space handler context
  104.  *              Region_context      - Region specific context
  105.  *
  106.  * RETURN:      Status
  107.  *
  108.  * DESCRIPTION: Do any prep work for region handling
  109.  *
  110.  * MUTEX:       Assumes namespace is not locked
  111.  *
  112.  ******************************************************************************/
  113. acpi_status
  114. acpi_ev_pci_config_region_setup (
  115. acpi_handle             handle,
  116. u32                     function,
  117. void                    *handler_context,
  118. void                    **region_context)
  119. {
  120. acpi_status             status = AE_OK;
  121. acpi_integer            temp;
  122. acpi_pci_id             *pci_id = *region_context;
  123. acpi_operand_object     *handler_obj;
  124. acpi_namespace_node     *node;
  125. acpi_operand_object     *region_obj = (acpi_operand_object *) handle;
  126. acpi_device_id          object_hID;
  127. FUNCTION_TRACE ("Ev_pci_config_region_setup");
  128. handler_obj = region_obj->region.addr_handler;
  129. if (!handler_obj) {
  130. /*
  131.  *  No installed handler. This shouldn't happen because the dispatch
  132.  *  routine checks before we get here, but we check again just in case.
  133.  */
  134. ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
  135. "Attempting to init a region %p, with no handlern", region_obj));
  136. return_ACPI_STATUS (AE_NOT_EXIST);
  137. }
  138. if (function == ACPI_REGION_DEACTIVATE) {
  139. if (pci_id) {
  140. ACPI_MEM_FREE (pci_id);
  141. *region_context = NULL;
  142. }
  143. return_ACPI_STATUS (status);
  144. }
  145. /* Create a new context */
  146. pci_id = ACPI_MEM_CALLOCATE (sizeof (acpi_pci_id));
  147. if (!pci_id) {
  148. return_ACPI_STATUS (AE_NO_MEMORY);
  149. }
  150. /*
  151.  *  For PCI Config space access, we have to pass the segment, bus,
  152.  *  device and function numbers.  This routine must acquire those.
  153.  */
  154. /*
  155.  *  First get device and function numbers from the _ADR object
  156.  *  in the parent's scope.
  157.  */
  158. node = acpi_ns_get_parent_object (region_obj->region.node);
  159. /* Acpi_evaluate the _ADR object */
  160. status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node, &temp);
  161. /*
  162.  *  The default is zero, since the allocation above zeroed the data, just
  163.  *  do nothing on failures.
  164.  */
  165. if (ACPI_SUCCESS (status)) {
  166. pci_id->device = HIWORD (temp);
  167. pci_id->function = LOWORD (temp);
  168. }
  169. /*
  170.  *  Get the _SEG and _BBN values from the device upon which the handler
  171.  *  is installed.
  172.  *
  173.  *  We need to get the _SEG and _BBN objects relative to the PCI BUS device.
  174.  *  This is the device the handler has been registered to handle.
  175.  */
  176. /*
  177.  *  If the Addr_handler.Node is still pointing to the root, we need
  178.  *  to scan upward for a PCI Root bridge and re-associate the Op_region
  179.  *  handlers with that device.
  180.  */
  181. if (handler_obj->addr_handler.node == acpi_gbl_root_node) {
  182. /*
  183.  * Node is currently the parent object
  184.  */
  185. while (node != acpi_gbl_root_node) {
  186. status = acpi_ut_execute_HID (node, &object_hID);
  187. if (ACPI_SUCCESS (status)) {
  188. if (!(STRNCMP (object_hID.buffer, PCI_ROOT_HID_STRING,
  189.    sizeof (PCI_ROOT_HID_STRING)))) {
  190. acpi_install_address_space_handler (node,
  191.    ACPI_ADR_SPACE_PCI_CONFIG,
  192.    ACPI_DEFAULT_HANDLER, NULL, NULL);
  193. break;
  194. }
  195. }
  196. node = acpi_ns_get_parent_object (node);
  197. }
  198. }
  199. else {
  200. node = handler_obj->addr_handler.node;
  201. }
  202. /*
  203.  * The PCI segment number comes from the _SEG method
  204.  */
  205. status = acpi_ut_evaluate_numeric_object (METHOD_NAME__SEG, node, &temp);
  206. if (ACPI_SUCCESS (status)) {
  207. pci_id->segment = LOWORD (temp);
  208. }
  209. /*
  210.  * The PCI bus number comes from the _BBN method
  211.  */
  212. status = acpi_ut_evaluate_numeric_object (METHOD_NAME__BBN, node, &temp);
  213. if (ACPI_SUCCESS (status)) {
  214. pci_id->bus = LOWORD (temp);
  215. }
  216. *region_context = pci_id;
  217. return_ACPI_STATUS (AE_OK);
  218. }
  219. /*******************************************************************************
  220.  *
  221.  * FUNCTION:    Acpi_ev_pci_bar_region_setup
  222.  *
  223.  * PARAMETERS:  Region_obj          - region we are interested in
  224.  *              Function            - start or stop
  225.  *              Handler_context     - Address space handler context
  226.  *              Region_context      - Region specific context
  227.  *
  228.  * RETURN:      Status
  229.  *
  230.  * DESCRIPTION: Do any prep work for region handling
  231.  *
  232.  * MUTEX:       Assumes namespace is not locked
  233.  *
  234.  ******************************************************************************/
  235. acpi_status
  236. acpi_ev_pci_bar_region_setup (
  237. acpi_handle             handle,
  238. u32                     function,
  239. void                    *handler_context,
  240. void                    **region_context)
  241. {
  242. FUNCTION_TRACE ("Ev_pci_bar_region_setup");
  243. return_ACPI_STATUS (AE_OK);
  244. }
  245. /*******************************************************************************
  246.  *
  247.  * FUNCTION:    Acpi_ev_cmos_region_setup
  248.  *
  249.  * PARAMETERS:  Region_obj          - region we are interested in
  250.  *              Function            - start or stop
  251.  *              Handler_context     - Address space handler context
  252.  *              Region_context      - Region specific context
  253.  *
  254.  * RETURN:      Status
  255.  *
  256.  * DESCRIPTION: Do any prep work for region handling
  257.  *
  258.  * MUTEX:       Assumes namespace is not locked
  259.  *
  260.  ******************************************************************************/
  261. acpi_status
  262. acpi_ev_cmos_region_setup (
  263. acpi_handle             handle,
  264. u32                     function,
  265. void                    *handler_context,
  266. void                    **region_context)
  267. {
  268. FUNCTION_TRACE ("Ev_cmos_region_setup");
  269. return_ACPI_STATUS (AE_OK);
  270. }
  271. /*******************************************************************************
  272.  *
  273.  * FUNCTION:    Acpi_ev_default_region_setup
  274.  *
  275.  * PARAMETERS:  Region_obj          - region we are interested in
  276.  *              Function            - start or stop
  277.  *              Handler_context     - Address space handler context
  278.  *              Region_context      - Region specific context
  279.  *
  280.  * RETURN:      Status
  281.  *
  282.  * DESCRIPTION: Do any prep work for region handling
  283.  *
  284.  ******************************************************************************/
  285. acpi_status
  286. acpi_ev_default_region_setup (
  287. acpi_handle             handle,
  288. u32                     function,
  289. void                    *handler_context,
  290. void                    **region_context)
  291. {
  292. FUNCTION_TRACE ("Ev_default_region_setup");
  293. if (function == ACPI_REGION_DEACTIVATE) {
  294. *region_context = NULL;
  295. }
  296. else {
  297. *region_context = handler_context;
  298. }
  299. return_ACPI_STATUS (AE_OK);
  300. }
  301. /*******************************************************************************
  302.  *
  303.  * FUNCTION:    Acpi_ev_initialize_region
  304.  *
  305.  * PARAMETERS:  Region_obj - Region we are initializing
  306.  *
  307.  * RETURN:      Status
  308.  *
  309.  * DESCRIPTION: Initializes the region, finds any _REG methods and saves them
  310.  *              for execution at a later time
  311.  *
  312.  *              Get the appropriate address space handler for a newly
  313.  *              created region.
  314.  *
  315.  *              This also performs address space specific intialization.  For
  316.  *              example, PCI regions must have an _ADR object that contains
  317.  *              a PCI address in the scope of the definition.  This address is
  318.  *              required to perform an access to PCI config space.
  319.  *
  320.  ******************************************************************************/
  321. acpi_status
  322. acpi_ev_initialize_region (
  323. acpi_operand_object     *region_obj,
  324. u8                      acpi_ns_locked)
  325. {
  326. acpi_operand_object     *handler_obj;
  327. acpi_operand_object     *obj_desc;
  328. ACPI_ADR_SPACE_TYPE     space_id;
  329. acpi_namespace_node     *node;
  330. acpi_status             status;
  331. acpi_namespace_node     *method_node;
  332. acpi_name               *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
  333. FUNCTION_TRACE_U32 ("Ev_initialize_region", acpi_ns_locked);
  334. if (!region_obj) {
  335. return_ACPI_STATUS (AE_BAD_PARAMETER);
  336. }
  337. node = acpi_ns_get_parent_object (region_obj->region.node);
  338. space_id = region_obj->region.space_id;
  339. region_obj->region.addr_handler = NULL;
  340. region_obj->region.extra->extra.method_REG = NULL;
  341. region_obj->region.flags &= ~(AOPOBJ_INITIALIZED);
  342. /*
  343.  *  Find any "_REG" associated with this region definition
  344.  */
  345. status = acpi_ns_search_node (*reg_name_ptr, node,
  346.   ACPI_TYPE_METHOD, &method_node);
  347. if (ACPI_SUCCESS (status)) {
  348. /*
  349.  *  The _REG method is optional and there can be only one per region
  350.  *  definition.  This will be executed when the handler is attached
  351.  *  or removed
  352.  */
  353. region_obj->region.extra->extra.method_REG = method_node;
  354. }
  355. /*
  356.  *  The following loop depends upon the root Node having no parent
  357.  *  ie: Acpi_gbl_Root_node->Parent_entry being set to NULL
  358.  */
  359. while (node) {
  360. /*
  361.  *  Check to see if a handler exists
  362.  */
  363. handler_obj = NULL;
  364. obj_desc = acpi_ns_get_attached_object (node);
  365. if (obj_desc) {
  366. /*
  367.  *  can only be a handler if the object exists
  368.  */
  369. switch (node->type) {
  370. case ACPI_TYPE_DEVICE:
  371. handler_obj = obj_desc->device.addr_handler;
  372. break;
  373. case ACPI_TYPE_PROCESSOR:
  374. handler_obj = obj_desc->processor.addr_handler;
  375. break;
  376. case ACPI_TYPE_THERMAL:
  377. handler_obj = obj_desc->thermal_zone.addr_handler;
  378. break;
  379. }
  380. while (handler_obj) {
  381. /*
  382.  *  This guy has at least one address handler
  383.  *  see if it has the type we want
  384.  */
  385. if (handler_obj->addr_handler.space_id == space_id) {
  386. ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
  387. "Found handler %p for region %p in obj %pn",
  388. handler_obj, region_obj, obj_desc));
  389. /*
  390.  *  Found it! Now update the region and the handler
  391.  */
  392. acpi_ev_associate_region_and_handler (handler_obj, region_obj,
  393. acpi_ns_locked);
  394. return_ACPI_STATUS (AE_OK);
  395. }
  396. handler_obj = handler_obj->addr_handler.next;
  397. } /* while handlerobj */
  398. }
  399. /*
  400.  *  This one does not have the handler we need
  401.  *  Pop up one level
  402.  */
  403. node = acpi_ns_get_parent_object (node);
  404. } /* while Node != ROOT */
  405. /*
  406.  *  If we get here, there is no handler for this region
  407.  */
  408. ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
  409. "No handler for Region_type %s(%X) (Region_obj %p)n",
  410. acpi_ut_get_region_name (space_id), space_id, region_obj));
  411. return_ACPI_STATUS (AE_NOT_EXIST);
  412. }