1*95b482a8SLen Brown /****************************************************************************** 2*95b482a8SLen Brown * 3*95b482a8SLen Brown * Module Name: evrgnini- ACPI address_space (op_region) init 4*95b482a8SLen Brown * 5*95b482a8SLen Brown *****************************************************************************/ 6*95b482a8SLen Brown 7*95b482a8SLen Brown /* 8*95b482a8SLen Brown * Copyright (C) 2000 - 2008, Intel Corp. 9*95b482a8SLen Brown * All rights reserved. 10*95b482a8SLen Brown * 11*95b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 12*95b482a8SLen Brown * modification, are permitted provided that the following conditions 13*95b482a8SLen Brown * are met: 14*95b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 15*95b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 16*95b482a8SLen Brown * without modification. 17*95b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18*95b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 19*95b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 20*95b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 21*95b482a8SLen Brown * binary redistribution. 22*95b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 23*95b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 24*95b482a8SLen Brown * from this software without specific prior written permission. 25*95b482a8SLen Brown * 26*95b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 27*95b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 28*95b482a8SLen Brown * Software Foundation. 29*95b482a8SLen Brown * 30*95b482a8SLen Brown * NO WARRANTY 31*95b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32*95b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33*95b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34*95b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35*95b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36*95b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37*95b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38*95b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39*95b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40*95b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41*95b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 42*95b482a8SLen Brown */ 43*95b482a8SLen Brown 44*95b482a8SLen Brown #include <acpi/acpi.h> 45*95b482a8SLen Brown #include <acpi/accommon.h> 46*95b482a8SLen Brown #include <acpi/acevents.h> 47*95b482a8SLen Brown #include <acpi/acnamesp.h> 48*95b482a8SLen Brown 49*95b482a8SLen Brown #define _COMPONENT ACPI_EVENTS 50*95b482a8SLen Brown ACPI_MODULE_NAME("evrgnini") 51*95b482a8SLen Brown 52*95b482a8SLen Brown /* Local prototypes */ 53*95b482a8SLen Brown static u8 acpi_ev_match_pci_root_bridge(char *id); 54*95b482a8SLen Brown 55*95b482a8SLen Brown static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); 56*95b482a8SLen Brown 57*95b482a8SLen Brown /******************************************************************************* 58*95b482a8SLen Brown * 59*95b482a8SLen Brown * FUNCTION: acpi_ev_system_memory_region_setup 60*95b482a8SLen Brown * 61*95b482a8SLen Brown * PARAMETERS: Handle - Region we are interested in 62*95b482a8SLen Brown * Function - Start or stop 63*95b482a8SLen Brown * handler_context - Address space handler context 64*95b482a8SLen Brown * region_context - Region specific context 65*95b482a8SLen Brown * 66*95b482a8SLen Brown * RETURN: Status 67*95b482a8SLen Brown * 68*95b482a8SLen Brown * DESCRIPTION: Setup a system_memory operation region 69*95b482a8SLen Brown * 70*95b482a8SLen Brown ******************************************************************************/ 71*95b482a8SLen Brown 72*95b482a8SLen Brown acpi_status 73*95b482a8SLen Brown acpi_ev_system_memory_region_setup(acpi_handle handle, 74*95b482a8SLen Brown u32 function, 75*95b482a8SLen Brown void *handler_context, void **region_context) 76*95b482a8SLen Brown { 77*95b482a8SLen Brown union acpi_operand_object *region_desc = 78*95b482a8SLen Brown (union acpi_operand_object *)handle; 79*95b482a8SLen Brown struct acpi_mem_space_context *local_region_context; 80*95b482a8SLen Brown 81*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_system_memory_region_setup); 82*95b482a8SLen Brown 83*95b482a8SLen Brown if (function == ACPI_REGION_DEACTIVATE) { 84*95b482a8SLen Brown if (*region_context) { 85*95b482a8SLen Brown local_region_context = 86*95b482a8SLen Brown (struct acpi_mem_space_context *)*region_context; 87*95b482a8SLen Brown 88*95b482a8SLen Brown /* Delete a cached mapping if present */ 89*95b482a8SLen Brown 90*95b482a8SLen Brown if (local_region_context->mapped_length) { 91*95b482a8SLen Brown acpi_os_unmap_memory(local_region_context-> 92*95b482a8SLen Brown mapped_logical_address, 93*95b482a8SLen Brown local_region_context-> 94*95b482a8SLen Brown mapped_length); 95*95b482a8SLen Brown } 96*95b482a8SLen Brown ACPI_FREE(local_region_context); 97*95b482a8SLen Brown *region_context = NULL; 98*95b482a8SLen Brown } 99*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 100*95b482a8SLen Brown } 101*95b482a8SLen Brown 102*95b482a8SLen Brown /* Create a new context */ 103*95b482a8SLen Brown 104*95b482a8SLen Brown local_region_context = 105*95b482a8SLen Brown ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context)); 106*95b482a8SLen Brown if (!(local_region_context)) { 107*95b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 108*95b482a8SLen Brown } 109*95b482a8SLen Brown 110*95b482a8SLen Brown /* Save the region length and address for use in the handler */ 111*95b482a8SLen Brown 112*95b482a8SLen Brown local_region_context->length = region_desc->region.length; 113*95b482a8SLen Brown local_region_context->address = region_desc->region.address; 114*95b482a8SLen Brown 115*95b482a8SLen Brown *region_context = local_region_context; 116*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 117*95b482a8SLen Brown } 118*95b482a8SLen Brown 119*95b482a8SLen Brown /******************************************************************************* 120*95b482a8SLen Brown * 121*95b482a8SLen Brown * FUNCTION: acpi_ev_io_space_region_setup 122*95b482a8SLen Brown * 123*95b482a8SLen Brown * PARAMETERS: Handle - Region we are interested in 124*95b482a8SLen Brown * Function - Start or stop 125*95b482a8SLen Brown * handler_context - Address space handler context 126*95b482a8SLen Brown * region_context - Region specific context 127*95b482a8SLen Brown * 128*95b482a8SLen Brown * RETURN: Status 129*95b482a8SLen Brown * 130*95b482a8SLen Brown * DESCRIPTION: Setup a IO operation region 131*95b482a8SLen Brown * 132*95b482a8SLen Brown ******************************************************************************/ 133*95b482a8SLen Brown 134*95b482a8SLen Brown acpi_status 135*95b482a8SLen Brown acpi_ev_io_space_region_setup(acpi_handle handle, 136*95b482a8SLen Brown u32 function, 137*95b482a8SLen Brown void *handler_context, void **region_context) 138*95b482a8SLen Brown { 139*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_io_space_region_setup); 140*95b482a8SLen Brown 141*95b482a8SLen Brown if (function == ACPI_REGION_DEACTIVATE) { 142*95b482a8SLen Brown *region_context = NULL; 143*95b482a8SLen Brown } else { 144*95b482a8SLen Brown *region_context = handler_context; 145*95b482a8SLen Brown } 146*95b482a8SLen Brown 147*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 148*95b482a8SLen Brown } 149*95b482a8SLen Brown 150*95b482a8SLen Brown /******************************************************************************* 151*95b482a8SLen Brown * 152*95b482a8SLen Brown * FUNCTION: acpi_ev_pci_config_region_setup 153*95b482a8SLen Brown * 154*95b482a8SLen Brown * PARAMETERS: Handle - Region we are interested in 155*95b482a8SLen Brown * Function - Start or stop 156*95b482a8SLen Brown * handler_context - Address space handler context 157*95b482a8SLen Brown * region_context - Region specific context 158*95b482a8SLen Brown * 159*95b482a8SLen Brown * RETURN: Status 160*95b482a8SLen Brown * 161*95b482a8SLen Brown * DESCRIPTION: Setup a PCI_Config operation region 162*95b482a8SLen Brown * 163*95b482a8SLen Brown * MUTEX: Assumes namespace is not locked 164*95b482a8SLen Brown * 165*95b482a8SLen Brown ******************************************************************************/ 166*95b482a8SLen Brown 167*95b482a8SLen Brown acpi_status 168*95b482a8SLen Brown acpi_ev_pci_config_region_setup(acpi_handle handle, 169*95b482a8SLen Brown u32 function, 170*95b482a8SLen Brown void *handler_context, void **region_context) 171*95b482a8SLen Brown { 172*95b482a8SLen Brown acpi_status status = AE_OK; 173*95b482a8SLen Brown acpi_integer pci_value; 174*95b482a8SLen Brown struct acpi_pci_id *pci_id = *region_context; 175*95b482a8SLen Brown union acpi_operand_object *handler_obj; 176*95b482a8SLen Brown struct acpi_namespace_node *parent_node; 177*95b482a8SLen Brown struct acpi_namespace_node *pci_root_node; 178*95b482a8SLen Brown struct acpi_namespace_node *pci_device_node; 179*95b482a8SLen Brown union acpi_operand_object *region_obj = 180*95b482a8SLen Brown (union acpi_operand_object *)handle; 181*95b482a8SLen Brown 182*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); 183*95b482a8SLen Brown 184*95b482a8SLen Brown handler_obj = region_obj->region.handler; 185*95b482a8SLen Brown if (!handler_obj) { 186*95b482a8SLen Brown /* 187*95b482a8SLen Brown * No installed handler. This shouldn't happen because the dispatch 188*95b482a8SLen Brown * routine checks before we get here, but we check again just in case. 189*95b482a8SLen Brown */ 190*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 191*95b482a8SLen Brown "Attempting to init a region %p, with no handler\n", 192*95b482a8SLen Brown region_obj)); 193*95b482a8SLen Brown return_ACPI_STATUS(AE_NOT_EXIST); 194*95b482a8SLen Brown } 195*95b482a8SLen Brown 196*95b482a8SLen Brown *region_context = NULL; 197*95b482a8SLen Brown if (function == ACPI_REGION_DEACTIVATE) { 198*95b482a8SLen Brown if (pci_id) { 199*95b482a8SLen Brown ACPI_FREE(pci_id); 200*95b482a8SLen Brown } 201*95b482a8SLen Brown return_ACPI_STATUS(status); 202*95b482a8SLen Brown } 203*95b482a8SLen Brown 204*95b482a8SLen Brown parent_node = acpi_ns_get_parent_node(region_obj->region.node); 205*95b482a8SLen Brown 206*95b482a8SLen Brown /* 207*95b482a8SLen Brown * Get the _SEG and _BBN values from the device upon which the handler 208*95b482a8SLen Brown * is installed. 209*95b482a8SLen Brown * 210*95b482a8SLen Brown * We need to get the _SEG and _BBN objects relative to the PCI BUS device. 211*95b482a8SLen Brown * This is the device the handler has been registered to handle. 212*95b482a8SLen Brown */ 213*95b482a8SLen Brown 214*95b482a8SLen Brown /* 215*95b482a8SLen Brown * If the address_space.Node is still pointing to the root, we need 216*95b482a8SLen Brown * to scan upward for a PCI Root bridge and re-associate the op_region 217*95b482a8SLen Brown * handlers with that device. 218*95b482a8SLen Brown */ 219*95b482a8SLen Brown if (handler_obj->address_space.node == acpi_gbl_root_node) { 220*95b482a8SLen Brown 221*95b482a8SLen Brown /* Start search from the parent object */ 222*95b482a8SLen Brown 223*95b482a8SLen Brown pci_root_node = parent_node; 224*95b482a8SLen Brown while (pci_root_node != acpi_gbl_root_node) { 225*95b482a8SLen Brown 226*95b482a8SLen Brown /* Get the _HID/_CID in order to detect a root_bridge */ 227*95b482a8SLen Brown 228*95b482a8SLen Brown if (acpi_ev_is_pci_root_bridge(pci_root_node)) { 229*95b482a8SLen Brown 230*95b482a8SLen Brown /* Install a handler for this PCI root bridge */ 231*95b482a8SLen Brown 232*95b482a8SLen Brown status = 233*95b482a8SLen Brown acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); 234*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 235*95b482a8SLen Brown if (status == AE_SAME_HANDLER) { 236*95b482a8SLen Brown /* 237*95b482a8SLen Brown * It is OK if the handler is already installed on the 238*95b482a8SLen Brown * root bridge. Still need to return a context object 239*95b482a8SLen Brown * for the new PCI_Config operation region, however. 240*95b482a8SLen Brown */ 241*95b482a8SLen Brown status = AE_OK; 242*95b482a8SLen Brown } else { 243*95b482a8SLen Brown ACPI_EXCEPTION((AE_INFO, status, 244*95b482a8SLen Brown "Could not install PciConfig handler for Root Bridge %4.4s", 245*95b482a8SLen Brown acpi_ut_get_node_name 246*95b482a8SLen Brown (pci_root_node))); 247*95b482a8SLen Brown } 248*95b482a8SLen Brown } 249*95b482a8SLen Brown break; 250*95b482a8SLen Brown } 251*95b482a8SLen Brown 252*95b482a8SLen Brown pci_root_node = acpi_ns_get_parent_node(pci_root_node); 253*95b482a8SLen Brown } 254*95b482a8SLen Brown 255*95b482a8SLen Brown /* PCI root bridge not found, use namespace root node */ 256*95b482a8SLen Brown } else { 257*95b482a8SLen Brown pci_root_node = handler_obj->address_space.node; 258*95b482a8SLen Brown } 259*95b482a8SLen Brown 260*95b482a8SLen Brown /* 261*95b482a8SLen Brown * If this region is now initialized, we are done. 262*95b482a8SLen Brown * (install_address_space_handler could have initialized it) 263*95b482a8SLen Brown */ 264*95b482a8SLen Brown if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { 265*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 266*95b482a8SLen Brown } 267*95b482a8SLen Brown 268*95b482a8SLen Brown /* Region is still not initialized. Create a new context */ 269*95b482a8SLen Brown 270*95b482a8SLen Brown pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id)); 271*95b482a8SLen Brown if (!pci_id) { 272*95b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 273*95b482a8SLen Brown } 274*95b482a8SLen Brown 275*95b482a8SLen Brown /* 276*95b482a8SLen Brown * For PCI_Config space access, we need the segment, bus, device and 277*95b482a8SLen Brown * function numbers. Acquire them here. 278*95b482a8SLen Brown * 279*95b482a8SLen Brown * Find the parent device object. (This allows the operation region to be 280*95b482a8SLen Brown * within a subscope under the device, such as a control method.) 281*95b482a8SLen Brown */ 282*95b482a8SLen Brown pci_device_node = region_obj->region.node; 283*95b482a8SLen Brown while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) { 284*95b482a8SLen Brown pci_device_node = acpi_ns_get_parent_node(pci_device_node); 285*95b482a8SLen Brown } 286*95b482a8SLen Brown 287*95b482a8SLen Brown if (!pci_device_node) { 288*95b482a8SLen Brown ACPI_FREE(pci_id); 289*95b482a8SLen Brown return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 290*95b482a8SLen Brown } 291*95b482a8SLen Brown 292*95b482a8SLen Brown /* 293*95b482a8SLen Brown * Get the PCI device and function numbers from the _ADR object contained 294*95b482a8SLen Brown * in the parent's scope. 295*95b482a8SLen Brown */ 296*95b482a8SLen Brown status = 297*95b482a8SLen Brown acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, pci_device_node, 298*95b482a8SLen Brown &pci_value); 299*95b482a8SLen Brown 300*95b482a8SLen Brown /* 301*95b482a8SLen Brown * The default is zero, and since the allocation above zeroed the data, 302*95b482a8SLen Brown * just do nothing on failure. 303*95b482a8SLen Brown */ 304*95b482a8SLen Brown if (ACPI_SUCCESS(status)) { 305*95b482a8SLen Brown pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value)); 306*95b482a8SLen Brown pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value)); 307*95b482a8SLen Brown } 308*95b482a8SLen Brown 309*95b482a8SLen Brown /* The PCI segment number comes from the _SEG method */ 310*95b482a8SLen Brown 311*95b482a8SLen Brown status = 312*95b482a8SLen Brown acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, pci_root_node, 313*95b482a8SLen Brown &pci_value); 314*95b482a8SLen Brown if (ACPI_SUCCESS(status)) { 315*95b482a8SLen Brown pci_id->segment = ACPI_LOWORD(pci_value); 316*95b482a8SLen Brown } 317*95b482a8SLen Brown 318*95b482a8SLen Brown /* The PCI bus number comes from the _BBN method */ 319*95b482a8SLen Brown 320*95b482a8SLen Brown status = 321*95b482a8SLen Brown acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, pci_root_node, 322*95b482a8SLen Brown &pci_value); 323*95b482a8SLen Brown if (ACPI_SUCCESS(status)) { 324*95b482a8SLen Brown pci_id->bus = ACPI_LOWORD(pci_value); 325*95b482a8SLen Brown } 326*95b482a8SLen Brown 327*95b482a8SLen Brown /* Complete this device's pci_id */ 328*95b482a8SLen Brown 329*95b482a8SLen Brown acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id); 330*95b482a8SLen Brown 331*95b482a8SLen Brown *region_context = pci_id; 332*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 333*95b482a8SLen Brown } 334*95b482a8SLen Brown 335*95b482a8SLen Brown /******************************************************************************* 336*95b482a8SLen Brown * 337*95b482a8SLen Brown * FUNCTION: acpi_ev_match_pci_root_bridge 338*95b482a8SLen Brown * 339*95b482a8SLen Brown * PARAMETERS: Id - The HID/CID in string format 340*95b482a8SLen Brown * 341*95b482a8SLen Brown * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge 342*95b482a8SLen Brown * 343*95b482a8SLen Brown * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. 344*95b482a8SLen Brown * 345*95b482a8SLen Brown ******************************************************************************/ 346*95b482a8SLen Brown 347*95b482a8SLen Brown static u8 acpi_ev_match_pci_root_bridge(char *id) 348*95b482a8SLen Brown { 349*95b482a8SLen Brown 350*95b482a8SLen Brown /* 351*95b482a8SLen Brown * Check if this is a PCI root. 352*95b482a8SLen Brown * ACPI 3.0+: check for a PCI Express root also. 353*95b482a8SLen Brown */ 354*95b482a8SLen Brown if (!(ACPI_STRNCMP(id, 355*95b482a8SLen Brown PCI_ROOT_HID_STRING, 356*95b482a8SLen Brown sizeof(PCI_ROOT_HID_STRING))) || 357*95b482a8SLen Brown !(ACPI_STRNCMP(id, 358*95b482a8SLen Brown PCI_EXPRESS_ROOT_HID_STRING, 359*95b482a8SLen Brown sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) { 360*95b482a8SLen Brown return (TRUE); 361*95b482a8SLen Brown } 362*95b482a8SLen Brown 363*95b482a8SLen Brown return (FALSE); 364*95b482a8SLen Brown } 365*95b482a8SLen Brown 366*95b482a8SLen Brown /******************************************************************************* 367*95b482a8SLen Brown * 368*95b482a8SLen Brown * FUNCTION: acpi_ev_is_pci_root_bridge 369*95b482a8SLen Brown * 370*95b482a8SLen Brown * PARAMETERS: Node - Device node being examined 371*95b482a8SLen Brown * 372*95b482a8SLen Brown * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge 373*95b482a8SLen Brown * 374*95b482a8SLen Brown * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by 375*95b482a8SLen Brown * examining the _HID and _CID for the device. 376*95b482a8SLen Brown * 377*95b482a8SLen Brown ******************************************************************************/ 378*95b482a8SLen Brown 379*95b482a8SLen Brown static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) 380*95b482a8SLen Brown { 381*95b482a8SLen Brown acpi_status status; 382*95b482a8SLen Brown struct acpica_device_id hid; 383*95b482a8SLen Brown struct acpi_compatible_id_list *cid; 384*95b482a8SLen Brown u32 i; 385*95b482a8SLen Brown 386*95b482a8SLen Brown /* Get the _HID and check for a PCI Root Bridge */ 387*95b482a8SLen Brown 388*95b482a8SLen Brown status = acpi_ut_execute_HID(node, &hid); 389*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 390*95b482a8SLen Brown return (FALSE); 391*95b482a8SLen Brown } 392*95b482a8SLen Brown 393*95b482a8SLen Brown if (acpi_ev_match_pci_root_bridge(hid.value)) { 394*95b482a8SLen Brown return (TRUE); 395*95b482a8SLen Brown } 396*95b482a8SLen Brown 397*95b482a8SLen Brown /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */ 398*95b482a8SLen Brown 399*95b482a8SLen Brown status = acpi_ut_execute_CID(node, &cid); 400*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 401*95b482a8SLen Brown return (FALSE); 402*95b482a8SLen Brown } 403*95b482a8SLen Brown 404*95b482a8SLen Brown /* Check all _CIDs in the returned list */ 405*95b482a8SLen Brown 406*95b482a8SLen Brown for (i = 0; i < cid->count; i++) { 407*95b482a8SLen Brown if (acpi_ev_match_pci_root_bridge(cid->id[i].value)) { 408*95b482a8SLen Brown ACPI_FREE(cid); 409*95b482a8SLen Brown return (TRUE); 410*95b482a8SLen Brown } 411*95b482a8SLen Brown } 412*95b482a8SLen Brown 413*95b482a8SLen Brown ACPI_FREE(cid); 414*95b482a8SLen Brown return (FALSE); 415*95b482a8SLen Brown } 416*95b482a8SLen Brown 417*95b482a8SLen Brown /******************************************************************************* 418*95b482a8SLen Brown * 419*95b482a8SLen Brown * FUNCTION: acpi_ev_pci_bar_region_setup 420*95b482a8SLen Brown * 421*95b482a8SLen Brown * PARAMETERS: Handle - Region we are interested in 422*95b482a8SLen Brown * Function - Start or stop 423*95b482a8SLen Brown * handler_context - Address space handler context 424*95b482a8SLen Brown * region_context - Region specific context 425*95b482a8SLen Brown * 426*95b482a8SLen Brown * RETURN: Status 427*95b482a8SLen Brown * 428*95b482a8SLen Brown * DESCRIPTION: Setup a pci_bAR operation region 429*95b482a8SLen Brown * 430*95b482a8SLen Brown * MUTEX: Assumes namespace is not locked 431*95b482a8SLen Brown * 432*95b482a8SLen Brown ******************************************************************************/ 433*95b482a8SLen Brown 434*95b482a8SLen Brown acpi_status 435*95b482a8SLen Brown acpi_ev_pci_bar_region_setup(acpi_handle handle, 436*95b482a8SLen Brown u32 function, 437*95b482a8SLen Brown void *handler_context, void **region_context) 438*95b482a8SLen Brown { 439*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup); 440*95b482a8SLen Brown 441*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 442*95b482a8SLen Brown } 443*95b482a8SLen Brown 444*95b482a8SLen Brown /******************************************************************************* 445*95b482a8SLen Brown * 446*95b482a8SLen Brown * FUNCTION: acpi_ev_cmos_region_setup 447*95b482a8SLen Brown * 448*95b482a8SLen Brown * PARAMETERS: Handle - Region we are interested in 449*95b482a8SLen Brown * Function - Start or stop 450*95b482a8SLen Brown * handler_context - Address space handler context 451*95b482a8SLen Brown * region_context - Region specific context 452*95b482a8SLen Brown * 453*95b482a8SLen Brown * RETURN: Status 454*95b482a8SLen Brown * 455*95b482a8SLen Brown * DESCRIPTION: Setup a CMOS operation region 456*95b482a8SLen Brown * 457*95b482a8SLen Brown * MUTEX: Assumes namespace is not locked 458*95b482a8SLen Brown * 459*95b482a8SLen Brown ******************************************************************************/ 460*95b482a8SLen Brown 461*95b482a8SLen Brown acpi_status 462*95b482a8SLen Brown acpi_ev_cmos_region_setup(acpi_handle handle, 463*95b482a8SLen Brown u32 function, 464*95b482a8SLen Brown void *handler_context, void **region_context) 465*95b482a8SLen Brown { 466*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_cmos_region_setup); 467*95b482a8SLen Brown 468*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 469*95b482a8SLen Brown } 470*95b482a8SLen Brown 471*95b482a8SLen Brown /******************************************************************************* 472*95b482a8SLen Brown * 473*95b482a8SLen Brown * FUNCTION: acpi_ev_default_region_setup 474*95b482a8SLen Brown * 475*95b482a8SLen Brown * PARAMETERS: Handle - Region we are interested in 476*95b482a8SLen Brown * Function - Start or stop 477*95b482a8SLen Brown * handler_context - Address space handler context 478*95b482a8SLen Brown * region_context - Region specific context 479*95b482a8SLen Brown * 480*95b482a8SLen Brown * RETURN: Status 481*95b482a8SLen Brown * 482*95b482a8SLen Brown * DESCRIPTION: Default region initialization 483*95b482a8SLen Brown * 484*95b482a8SLen Brown ******************************************************************************/ 485*95b482a8SLen Brown 486*95b482a8SLen Brown acpi_status 487*95b482a8SLen Brown acpi_ev_default_region_setup(acpi_handle handle, 488*95b482a8SLen Brown u32 function, 489*95b482a8SLen Brown void *handler_context, void **region_context) 490*95b482a8SLen Brown { 491*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_default_region_setup); 492*95b482a8SLen Brown 493*95b482a8SLen Brown if (function == ACPI_REGION_DEACTIVATE) { 494*95b482a8SLen Brown *region_context = NULL; 495*95b482a8SLen Brown } else { 496*95b482a8SLen Brown *region_context = handler_context; 497*95b482a8SLen Brown } 498*95b482a8SLen Brown 499*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 500*95b482a8SLen Brown } 501*95b482a8SLen Brown 502*95b482a8SLen Brown /******************************************************************************* 503*95b482a8SLen Brown * 504*95b482a8SLen Brown * FUNCTION: acpi_ev_initialize_region 505*95b482a8SLen Brown * 506*95b482a8SLen Brown * PARAMETERS: region_obj - Region we are initializing 507*95b482a8SLen Brown * acpi_ns_locked - Is namespace locked? 508*95b482a8SLen Brown * 509*95b482a8SLen Brown * RETURN: Status 510*95b482a8SLen Brown * 511*95b482a8SLen Brown * DESCRIPTION: Initializes the region, finds any _REG methods and saves them 512*95b482a8SLen Brown * for execution at a later time 513*95b482a8SLen Brown * 514*95b482a8SLen Brown * Get the appropriate address space handler for a newly 515*95b482a8SLen Brown * created region. 516*95b482a8SLen Brown * 517*95b482a8SLen Brown * This also performs address space specific initialization. For 518*95b482a8SLen Brown * example, PCI regions must have an _ADR object that contains 519*95b482a8SLen Brown * a PCI address in the scope of the definition. This address is 520*95b482a8SLen Brown * required to perform an access to PCI config space. 521*95b482a8SLen Brown * 522*95b482a8SLen Brown * MUTEX: Interpreter should be unlocked, because we may run the _REG 523*95b482a8SLen Brown * method for this region. 524*95b482a8SLen Brown * 525*95b482a8SLen Brown ******************************************************************************/ 526*95b482a8SLen Brown 527*95b482a8SLen Brown acpi_status 528*95b482a8SLen Brown acpi_ev_initialize_region(union acpi_operand_object *region_obj, 529*95b482a8SLen Brown u8 acpi_ns_locked) 530*95b482a8SLen Brown { 531*95b482a8SLen Brown union acpi_operand_object *handler_obj; 532*95b482a8SLen Brown union acpi_operand_object *obj_desc; 533*95b482a8SLen Brown acpi_adr_space_type space_id; 534*95b482a8SLen Brown struct acpi_namespace_node *node; 535*95b482a8SLen Brown acpi_status status; 536*95b482a8SLen Brown struct acpi_namespace_node *method_node; 537*95b482a8SLen Brown acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG; 538*95b482a8SLen Brown union acpi_operand_object *region_obj2; 539*95b482a8SLen Brown 540*95b482a8SLen Brown ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked); 541*95b482a8SLen Brown 542*95b482a8SLen Brown if (!region_obj) { 543*95b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 544*95b482a8SLen Brown } 545*95b482a8SLen Brown 546*95b482a8SLen Brown if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) { 547*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 548*95b482a8SLen Brown } 549*95b482a8SLen Brown 550*95b482a8SLen Brown region_obj2 = acpi_ns_get_secondary_object(region_obj); 551*95b482a8SLen Brown if (!region_obj2) { 552*95b482a8SLen Brown return_ACPI_STATUS(AE_NOT_EXIST); 553*95b482a8SLen Brown } 554*95b482a8SLen Brown 555*95b482a8SLen Brown node = acpi_ns_get_parent_node(region_obj->region.node); 556*95b482a8SLen Brown space_id = region_obj->region.space_id; 557*95b482a8SLen Brown 558*95b482a8SLen Brown /* Setup defaults */ 559*95b482a8SLen Brown 560*95b482a8SLen Brown region_obj->region.handler = NULL; 561*95b482a8SLen Brown region_obj2->extra.method_REG = NULL; 562*95b482a8SLen Brown region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE); 563*95b482a8SLen Brown region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED; 564*95b482a8SLen Brown 565*95b482a8SLen Brown /* Find any "_REG" method associated with this region definition */ 566*95b482a8SLen Brown 567*95b482a8SLen Brown status = 568*95b482a8SLen Brown acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD, 569*95b482a8SLen Brown &method_node); 570*95b482a8SLen Brown if (ACPI_SUCCESS(status)) { 571*95b482a8SLen Brown /* 572*95b482a8SLen Brown * The _REG method is optional and there can be only one per region 573*95b482a8SLen Brown * definition. This will be executed when the handler is attached 574*95b482a8SLen Brown * or removed 575*95b482a8SLen Brown */ 576*95b482a8SLen Brown region_obj2->extra.method_REG = method_node; 577*95b482a8SLen Brown } 578*95b482a8SLen Brown 579*95b482a8SLen Brown /* 580*95b482a8SLen Brown * The following loop depends upon the root Node having no parent 581*95b482a8SLen Brown * ie: acpi_gbl_root_node->parent_entry being set to NULL 582*95b482a8SLen Brown */ 583*95b482a8SLen Brown while (node) { 584*95b482a8SLen Brown 585*95b482a8SLen Brown /* Check to see if a handler exists */ 586*95b482a8SLen Brown 587*95b482a8SLen Brown handler_obj = NULL; 588*95b482a8SLen Brown obj_desc = acpi_ns_get_attached_object(node); 589*95b482a8SLen Brown if (obj_desc) { 590*95b482a8SLen Brown 591*95b482a8SLen Brown /* Can only be a handler if the object exists */ 592*95b482a8SLen Brown 593*95b482a8SLen Brown switch (node->type) { 594*95b482a8SLen Brown case ACPI_TYPE_DEVICE: 595*95b482a8SLen Brown 596*95b482a8SLen Brown handler_obj = obj_desc->device.handler; 597*95b482a8SLen Brown break; 598*95b482a8SLen Brown 599*95b482a8SLen Brown case ACPI_TYPE_PROCESSOR: 600*95b482a8SLen Brown 601*95b482a8SLen Brown handler_obj = obj_desc->processor.handler; 602*95b482a8SLen Brown break; 603*95b482a8SLen Brown 604*95b482a8SLen Brown case ACPI_TYPE_THERMAL: 605*95b482a8SLen Brown 606*95b482a8SLen Brown handler_obj = obj_desc->thermal_zone.handler; 607*95b482a8SLen Brown break; 608*95b482a8SLen Brown 609*95b482a8SLen Brown default: 610*95b482a8SLen Brown /* Ignore other objects */ 611*95b482a8SLen Brown break; 612*95b482a8SLen Brown } 613*95b482a8SLen Brown 614*95b482a8SLen Brown while (handler_obj) { 615*95b482a8SLen Brown 616*95b482a8SLen Brown /* Is this handler of the correct type? */ 617*95b482a8SLen Brown 618*95b482a8SLen Brown if (handler_obj->address_space.space_id == 619*95b482a8SLen Brown space_id) { 620*95b482a8SLen Brown 621*95b482a8SLen Brown /* Found correct handler */ 622*95b482a8SLen Brown 623*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 624*95b482a8SLen Brown "Found handler %p for region %p in obj %p\n", 625*95b482a8SLen Brown handler_obj, 626*95b482a8SLen Brown region_obj, 627*95b482a8SLen Brown obj_desc)); 628*95b482a8SLen Brown 629*95b482a8SLen Brown status = 630*95b482a8SLen Brown acpi_ev_attach_region(handler_obj, 631*95b482a8SLen Brown region_obj, 632*95b482a8SLen Brown acpi_ns_locked); 633*95b482a8SLen Brown 634*95b482a8SLen Brown /* 635*95b482a8SLen Brown * Tell all users that this region is usable by running the _REG 636*95b482a8SLen Brown * method 637*95b482a8SLen Brown */ 638*95b482a8SLen Brown if (acpi_ns_locked) { 639*95b482a8SLen Brown status = 640*95b482a8SLen Brown acpi_ut_release_mutex 641*95b482a8SLen Brown (ACPI_MTX_NAMESPACE); 642*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 643*95b482a8SLen Brown return_ACPI_STATUS 644*95b482a8SLen Brown (status); 645*95b482a8SLen Brown } 646*95b482a8SLen Brown } 647*95b482a8SLen Brown 648*95b482a8SLen Brown status = 649*95b482a8SLen Brown acpi_ev_execute_reg_method 650*95b482a8SLen Brown (region_obj, 1); 651*95b482a8SLen Brown 652*95b482a8SLen Brown if (acpi_ns_locked) { 653*95b482a8SLen Brown status = 654*95b482a8SLen Brown acpi_ut_acquire_mutex 655*95b482a8SLen Brown (ACPI_MTX_NAMESPACE); 656*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 657*95b482a8SLen Brown return_ACPI_STATUS 658*95b482a8SLen Brown (status); 659*95b482a8SLen Brown } 660*95b482a8SLen Brown } 661*95b482a8SLen Brown 662*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 663*95b482a8SLen Brown } 664*95b482a8SLen Brown 665*95b482a8SLen Brown /* Try next handler in the list */ 666*95b482a8SLen Brown 667*95b482a8SLen Brown handler_obj = handler_obj->address_space.next; 668*95b482a8SLen Brown } 669*95b482a8SLen Brown } 670*95b482a8SLen Brown 671*95b482a8SLen Brown /* This node does not have the handler we need; Pop up one level */ 672*95b482a8SLen Brown 673*95b482a8SLen Brown node = acpi_ns_get_parent_node(node); 674*95b482a8SLen Brown } 675*95b482a8SLen Brown 676*95b482a8SLen Brown /* If we get here, there is no handler for this region */ 677*95b482a8SLen Brown 678*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 679*95b482a8SLen Brown "No handler for RegionType %s(%X) (RegionObj %p)\n", 680*95b482a8SLen Brown acpi_ut_get_region_name(space_id), space_id, 681*95b482a8SLen Brown region_obj)); 682*95b482a8SLen Brown 683*95b482a8SLen Brown return_ACPI_STATUS(AE_NOT_EXIST); 684*95b482a8SLen Brown } 685