evhandler.c revision 244971
1/****************************************************************************** 2 * 3 * Module Name: evhandler - Support for Address Space handlers 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2012, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 45#define __EVHANDLER_C__ 46 47#include "acpi.h" 48#include "accommon.h" 49#include "acevents.h" 50#include "acnamesp.h" 51#include "acinterp.h" 52 53#define _COMPONENT ACPI_EVENTS 54 ACPI_MODULE_NAME ("evhandler") 55 56 57/* Local prototypes */ 58 59static ACPI_STATUS 60AcpiEvInstallHandler ( 61 ACPI_HANDLE ObjHandle, 62 UINT32 Level, 63 void *Context, 64 void **ReturnValue); 65 66/* These are the address spaces that will get default handlers */ 67 68UINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] = 69{ 70 ACPI_ADR_SPACE_SYSTEM_MEMORY, 71 ACPI_ADR_SPACE_SYSTEM_IO, 72 ACPI_ADR_SPACE_PCI_CONFIG, 73 ACPI_ADR_SPACE_DATA_TABLE 74}; 75 76 77/******************************************************************************* 78 * 79 * FUNCTION: AcpiEvInstallRegionHandlers 80 * 81 * PARAMETERS: None 82 * 83 * RETURN: Status 84 * 85 * DESCRIPTION: Installs the core subsystem default address space handlers. 86 * 87 ******************************************************************************/ 88 89ACPI_STATUS 90AcpiEvInstallRegionHandlers ( 91 void) 92{ 93 ACPI_STATUS Status; 94 UINT32 i; 95 96 97 ACPI_FUNCTION_TRACE (EvInstallRegionHandlers); 98 99 100 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 101 if (ACPI_FAILURE (Status)) 102 { 103 return_ACPI_STATUS (Status); 104 } 105 106 /* 107 * All address spaces (PCI Config, EC, SMBus) are scope dependent and 108 * registration must occur for a specific device. 109 * 110 * In the case of the system memory and IO address spaces there is 111 * currently no device associated with the address space. For these we 112 * use the root. 113 * 114 * We install the default PCI config space handler at the root so that 115 * this space is immediately available even though the we have not 116 * enumerated all the PCI Root Buses yet. This is to conform to the ACPI 117 * specification which states that the PCI config space must be always 118 * available -- even though we are nowhere near ready to find the PCI root 119 * buses at this point. 120 * 121 * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler 122 * has already been installed (via AcpiInstallAddressSpaceHandler). 123 * Similar for AE_SAME_HANDLER. 124 */ 125 for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) 126 { 127 Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode, 128 AcpiGbl_DefaultAddressSpaces[i], 129 ACPI_DEFAULT_HANDLER, NULL, NULL); 130 switch (Status) 131 { 132 case AE_OK: 133 case AE_SAME_HANDLER: 134 case AE_ALREADY_EXISTS: 135 136 /* These exceptions are all OK */ 137 138 Status = AE_OK; 139 break; 140 141 default: 142 143 goto UnlockAndExit; 144 } 145 } 146 147UnlockAndExit: 148 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 149 return_ACPI_STATUS (Status); 150} 151 152 153/******************************************************************************* 154 * 155 * FUNCTION: AcpiEvHasDefaultHandler 156 * 157 * PARAMETERS: Node - Namespace node for the device 158 * SpaceId - The address space ID 159 * 160 * RETURN: TRUE if default handler is installed, FALSE otherwise 161 * 162 * DESCRIPTION: Check if the default handler is installed for the requested 163 * space ID. 164 * 165 ******************************************************************************/ 166 167BOOLEAN 168AcpiEvHasDefaultHandler ( 169 ACPI_NAMESPACE_NODE *Node, 170 ACPI_ADR_SPACE_TYPE SpaceId) 171{ 172 ACPI_OPERAND_OBJECT *ObjDesc; 173 ACPI_OPERAND_OBJECT *HandlerObj; 174 175 176 /* Must have an existing internal object */ 177 178 ObjDesc = AcpiNsGetAttachedObject (Node); 179 if (ObjDesc) 180 { 181 HandlerObj = ObjDesc->Device.Handler; 182 183 /* Walk the linked list of handlers for this object */ 184 185 while (HandlerObj) 186 { 187 if (HandlerObj->AddressSpace.SpaceId == SpaceId) 188 { 189 if (HandlerObj->AddressSpace.HandlerFlags & 190 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) 191 { 192 return (TRUE); 193 } 194 } 195 196 HandlerObj = HandlerObj->AddressSpace.Next; 197 } 198 } 199 200 return (FALSE); 201} 202 203 204/******************************************************************************* 205 * 206 * FUNCTION: AcpiEvInstallHandler 207 * 208 * PARAMETERS: WalkNamespace callback 209 * 210 * DESCRIPTION: This routine installs an address handler into objects that are 211 * of type Region or Device. 212 * 213 * If the Object is a Device, and the device has a handler of 214 * the same type then the search is terminated in that branch. 215 * 216 * This is because the existing handler is closer in proximity 217 * to any more regions than the one we are trying to install. 218 * 219 ******************************************************************************/ 220 221static ACPI_STATUS 222AcpiEvInstallHandler ( 223 ACPI_HANDLE ObjHandle, 224 UINT32 Level, 225 void *Context, 226 void **ReturnValue) 227{ 228 ACPI_OPERAND_OBJECT *HandlerObj; 229 ACPI_OPERAND_OBJECT *NextHandlerObj; 230 ACPI_OPERAND_OBJECT *ObjDesc; 231 ACPI_NAMESPACE_NODE *Node; 232 ACPI_STATUS Status; 233 234 235 ACPI_FUNCTION_NAME (EvInstallHandler); 236 237 238 HandlerObj = (ACPI_OPERAND_OBJECT *) Context; 239 240 /* Parameter validation */ 241 242 if (!HandlerObj) 243 { 244 return (AE_OK); 245 } 246 247 /* Convert and validate the device handle */ 248 249 Node = AcpiNsValidateHandle (ObjHandle); 250 if (!Node) 251 { 252 return (AE_BAD_PARAMETER); 253 } 254 255 /* 256 * We only care about regions and objects that are allowed to have 257 * address space handlers 258 */ 259 if ((Node->Type != ACPI_TYPE_DEVICE) && 260 (Node->Type != ACPI_TYPE_REGION) && 261 (Node != AcpiGbl_RootNode)) 262 { 263 return (AE_OK); 264 } 265 266 /* Check for an existing internal object */ 267 268 ObjDesc = AcpiNsGetAttachedObject (Node); 269 if (!ObjDesc) 270 { 271 /* No object, just exit */ 272 273 return (AE_OK); 274 } 275 276 /* Devices are handled different than regions */ 277 278 if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE) 279 { 280 /* Check if this Device already has a handler for this address space */ 281 282 NextHandlerObj = ObjDesc->Device.Handler; 283 while (NextHandlerObj) 284 { 285 /* Found a handler, is it for the same address space? */ 286 287 if (NextHandlerObj->AddressSpace.SpaceId == 288 HandlerObj->AddressSpace.SpaceId) 289 { 290 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 291 "Found handler for region [%s] in device %p(%p) " 292 "handler %p\n", 293 AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId), 294 ObjDesc, NextHandlerObj, HandlerObj)); 295 296 /* 297 * Since the object we found it on was a device, then it 298 * means that someone has already installed a handler for 299 * the branch of the namespace from this device on. Just 300 * bail out telling the walk routine to not traverse this 301 * branch. This preserves the scoping rule for handlers. 302 */ 303 return (AE_CTRL_DEPTH); 304 } 305 306 /* Walk the linked list of handlers attached to this device */ 307 308 NextHandlerObj = NextHandlerObj->AddressSpace.Next; 309 } 310 311 /* 312 * As long as the device didn't have a handler for this space we 313 * don't care about it. We just ignore it and proceed. 314 */ 315 return (AE_OK); 316 } 317 318 /* Object is a Region */ 319 320 if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId) 321 { 322 /* This region is for a different address space, just ignore it */ 323 324 return (AE_OK); 325 } 326 327 /* 328 * Now we have a region and it is for the handler's address space type. 329 * 330 * First disconnect region for any previous handler (if any) 331 */ 332 AcpiEvDetachRegion (ObjDesc, FALSE); 333 334 /* Connect the region to the new handler */ 335 336 Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE); 337 return (Status); 338} 339 340 341/******************************************************************************* 342 * 343 * FUNCTION: AcpiEvInstallSpaceHandler 344 * 345 * PARAMETERS: Node - Namespace node for the device 346 * SpaceId - The address space ID 347 * Handler - Address of the handler 348 * Setup - Address of the setup function 349 * Context - Value passed to the handler on each access 350 * 351 * RETURN: Status 352 * 353 * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId. 354 * Assumes namespace is locked 355 * 356 ******************************************************************************/ 357 358ACPI_STATUS 359AcpiEvInstallSpaceHandler ( 360 ACPI_NAMESPACE_NODE *Node, 361 ACPI_ADR_SPACE_TYPE SpaceId, 362 ACPI_ADR_SPACE_HANDLER Handler, 363 ACPI_ADR_SPACE_SETUP Setup, 364 void *Context) 365{ 366 ACPI_OPERAND_OBJECT *ObjDesc; 367 ACPI_OPERAND_OBJECT *HandlerObj; 368 ACPI_STATUS Status; 369 ACPI_OBJECT_TYPE Type; 370 UINT8 Flags = 0; 371 372 373 ACPI_FUNCTION_TRACE (EvInstallSpaceHandler); 374 375 376 /* 377 * This registration is valid for only the types below and the root. This 378 * is where the default handlers get placed. 379 */ 380 if ((Node->Type != ACPI_TYPE_DEVICE) && 381 (Node->Type != ACPI_TYPE_PROCESSOR) && 382 (Node->Type != ACPI_TYPE_THERMAL) && 383 (Node != AcpiGbl_RootNode)) 384 { 385 Status = AE_BAD_PARAMETER; 386 goto UnlockAndExit; 387 } 388 389 if (Handler == ACPI_DEFAULT_HANDLER) 390 { 391 Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; 392 393 switch (SpaceId) 394 { 395 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 396 Handler = AcpiExSystemMemorySpaceHandler; 397 Setup = AcpiEvSystemMemoryRegionSetup; 398 break; 399 400 case ACPI_ADR_SPACE_SYSTEM_IO: 401 Handler = AcpiExSystemIoSpaceHandler; 402 Setup = AcpiEvIoSpaceRegionSetup; 403 break; 404 405 case ACPI_ADR_SPACE_PCI_CONFIG: 406 Handler = AcpiExPciConfigSpaceHandler; 407 Setup = AcpiEvPciConfigRegionSetup; 408 break; 409 410 case ACPI_ADR_SPACE_CMOS: 411 Handler = AcpiExCmosSpaceHandler; 412 Setup = AcpiEvCmosRegionSetup; 413 break; 414 415 case ACPI_ADR_SPACE_PCI_BAR_TARGET: 416 Handler = AcpiExPciBarSpaceHandler; 417 Setup = AcpiEvPciBarRegionSetup; 418 break; 419 420 case ACPI_ADR_SPACE_DATA_TABLE: 421 Handler = AcpiExDataTableSpaceHandler; 422 Setup = NULL; 423 break; 424 425 default: 426 Status = AE_BAD_PARAMETER; 427 goto UnlockAndExit; 428 } 429 } 430 431 /* If the caller hasn't specified a setup routine, use the default */ 432 433 if (!Setup) 434 { 435 Setup = AcpiEvDefaultRegionSetup; 436 } 437 438 /* Check for an existing internal object */ 439 440 ObjDesc = AcpiNsGetAttachedObject (Node); 441 if (ObjDesc) 442 { 443 /* 444 * The attached device object already exists. Make sure the handler 445 * is not already installed. 446 */ 447 HandlerObj = ObjDesc->Device.Handler; 448 449 /* Walk the handler list for this device */ 450 451 while (HandlerObj) 452 { 453 /* Same SpaceId indicates a handler already installed */ 454 455 if (HandlerObj->AddressSpace.SpaceId == SpaceId) 456 { 457 if (HandlerObj->AddressSpace.Handler == Handler) 458 { 459 /* 460 * It is (relatively) OK to attempt to install the SAME 461 * handler twice. This can easily happen with the 462 * PCI_Config space. 463 */ 464 Status = AE_SAME_HANDLER; 465 goto UnlockAndExit; 466 } 467 else 468 { 469 /* A handler is already installed */ 470 471 Status = AE_ALREADY_EXISTS; 472 } 473 goto UnlockAndExit; 474 } 475 476 /* Walk the linked list of handlers */ 477 478 HandlerObj = HandlerObj->AddressSpace.Next; 479 } 480 } 481 else 482 { 483 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 484 "Creating object on Device %p while installing handler\n", Node)); 485 486 /* ObjDesc does not exist, create one */ 487 488 if (Node->Type == ACPI_TYPE_ANY) 489 { 490 Type = ACPI_TYPE_DEVICE; 491 } 492 else 493 { 494 Type = Node->Type; 495 } 496 497 ObjDesc = AcpiUtCreateInternalObject (Type); 498 if (!ObjDesc) 499 { 500 Status = AE_NO_MEMORY; 501 goto UnlockAndExit; 502 } 503 504 /* Init new descriptor */ 505 506 ObjDesc->Common.Type = (UINT8) Type; 507 508 /* Attach the new object to the Node */ 509 510 Status = AcpiNsAttachObject (Node, ObjDesc, Type); 511 512 /* Remove local reference to the object */ 513 514 AcpiUtRemoveReference (ObjDesc); 515 516 if (ACPI_FAILURE (Status)) 517 { 518 goto UnlockAndExit; 519 } 520 } 521 522 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 523 "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", 524 AcpiUtGetRegionName (SpaceId), SpaceId, 525 AcpiUtGetNodeName (Node), Node, ObjDesc)); 526 527 /* 528 * Install the handler 529 * 530 * At this point there is no existing handler. Just allocate the object 531 * for the handler and link it into the list. 532 */ 533 HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER); 534 if (!HandlerObj) 535 { 536 Status = AE_NO_MEMORY; 537 goto UnlockAndExit; 538 } 539 540 /* Init handler obj */ 541 542 HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId; 543 HandlerObj->AddressSpace.HandlerFlags = Flags; 544 HandlerObj->AddressSpace.RegionList = NULL; 545 HandlerObj->AddressSpace.Node = Node; 546 HandlerObj->AddressSpace.Handler = Handler; 547 HandlerObj->AddressSpace.Context = Context; 548 HandlerObj->AddressSpace.Setup = Setup; 549 550 /* Install at head of Device.AddressSpace list */ 551 552 HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler; 553 554 /* 555 * The Device object is the first reference on the HandlerObj. 556 * Each region that uses the handler adds a reference. 557 */ 558 ObjDesc->Device.Handler = HandlerObj; 559 560 /* 561 * Walk the namespace finding all of the regions this 562 * handler will manage. 563 * 564 * Start at the device and search the branch toward 565 * the leaf nodes until either the leaf is encountered or 566 * a device is detected that has an address handler of the 567 * same type. 568 * 569 * In either case, back up and search down the remainder 570 * of the branch 571 */ 572 Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, 573 ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL, 574 HandlerObj, NULL); 575 576UnlockAndExit: 577 return_ACPI_STATUS (Status); 578} 579