1 /****************************************************************************** 2 * 3 * Module Name: evhandler - Support for Address Space handlers 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 59 static ACPI_STATUS 60 AcpiEvInstallHandler ( 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 68 UINT8 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 89 ACPI_STATUS 90 AcpiEvInstallRegionHandlers ( 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 147 UnlockAndExit: 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 167 BOOLEAN 168 AcpiEvHasDefaultHandler ( 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 221 static ACPI_STATUS 222 AcpiEvInstallHandler ( 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 358 ACPI_STATUS 359 AcpiEvInstallSpaceHandler ( 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 397 Handler = AcpiExSystemMemorySpaceHandler; 398 Setup = AcpiEvSystemMemoryRegionSetup; 399 break; 400 401 case ACPI_ADR_SPACE_SYSTEM_IO: 402 403 Handler = AcpiExSystemIoSpaceHandler; 404 Setup = AcpiEvIoSpaceRegionSetup; 405 break; 406 407 case ACPI_ADR_SPACE_PCI_CONFIG: 408 409 Handler = AcpiExPciConfigSpaceHandler; 410 Setup = AcpiEvPciConfigRegionSetup; 411 break; 412 413 case ACPI_ADR_SPACE_CMOS: 414 415 Handler = AcpiExCmosSpaceHandler; 416 Setup = AcpiEvCmosRegionSetup; 417 break; 418 419 case ACPI_ADR_SPACE_PCI_BAR_TARGET: 420 421 Handler = AcpiExPciBarSpaceHandler; 422 Setup = AcpiEvPciBarRegionSetup; 423 break; 424 425 case ACPI_ADR_SPACE_DATA_TABLE: 426 427 Handler = AcpiExDataTableSpaceHandler; 428 Setup = NULL; 429 break; 430 431 default: 432 433 Status = AE_BAD_PARAMETER; 434 goto UnlockAndExit; 435 } 436 } 437 438 /* If the caller hasn't specified a setup routine, use the default */ 439 440 if (!Setup) 441 { 442 Setup = AcpiEvDefaultRegionSetup; 443 } 444 445 /* Check for an existing internal object */ 446 447 ObjDesc = AcpiNsGetAttachedObject (Node); 448 if (ObjDesc) 449 { 450 /* 451 * The attached device object already exists. Make sure the handler 452 * is not already installed. 453 */ 454 HandlerObj = ObjDesc->Device.Handler; 455 456 /* Walk the handler list for this device */ 457 458 while (HandlerObj) 459 { 460 /* Same SpaceId indicates a handler already installed */ 461 462 if (HandlerObj->AddressSpace.SpaceId == SpaceId) 463 { 464 if (HandlerObj->AddressSpace.Handler == Handler) 465 { 466 /* 467 * It is (relatively) OK to attempt to install the SAME 468 * handler twice. This can easily happen with the 469 * PCI_Config space. 470 */ 471 Status = AE_SAME_HANDLER; 472 goto UnlockAndExit; 473 } 474 else 475 { 476 /* A handler is already installed */ 477 478 Status = AE_ALREADY_EXISTS; 479 } 480 goto UnlockAndExit; 481 } 482 483 /* Walk the linked list of handlers */ 484 485 HandlerObj = HandlerObj->AddressSpace.Next; 486 } 487 } 488 else 489 { 490 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 491 "Creating object on Device %p while installing handler\n", Node)); 492 493 /* ObjDesc does not exist, create one */ 494 495 if (Node->Type == ACPI_TYPE_ANY) 496 { 497 Type = ACPI_TYPE_DEVICE; 498 } 499 else 500 { 501 Type = Node->Type; 502 } 503 504 ObjDesc = AcpiUtCreateInternalObject (Type); 505 if (!ObjDesc) 506 { 507 Status = AE_NO_MEMORY; 508 goto UnlockAndExit; 509 } 510 511 /* Init new descriptor */ 512 513 ObjDesc->Common.Type = (UINT8) Type; 514 515 /* Attach the new object to the Node */ 516 517 Status = AcpiNsAttachObject (Node, ObjDesc, Type); 518 519 /* Remove local reference to the object */ 520 521 AcpiUtRemoveReference (ObjDesc); 522 523 if (ACPI_FAILURE (Status)) 524 { 525 goto UnlockAndExit; 526 } 527 } 528 529 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 530 "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", 531 AcpiUtGetRegionName (SpaceId), SpaceId, 532 AcpiUtGetNodeName (Node), Node, ObjDesc)); 533 534 /* 535 * Install the handler 536 * 537 * At this point there is no existing handler. Just allocate the object 538 * for the handler and link it into the list. 539 */ 540 HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER); 541 if (!HandlerObj) 542 { 543 Status = AE_NO_MEMORY; 544 goto UnlockAndExit; 545 } 546 547 /* Init handler obj */ 548 549 HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId; 550 HandlerObj->AddressSpace.HandlerFlags = Flags; 551 HandlerObj->AddressSpace.RegionList = NULL; 552 HandlerObj->AddressSpace.Node = Node; 553 HandlerObj->AddressSpace.Handler = Handler; 554 HandlerObj->AddressSpace.Context = Context; 555 HandlerObj->AddressSpace.Setup = Setup; 556 557 /* Install at head of Device.AddressSpace list */ 558 559 HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler; 560 561 /* 562 * The Device object is the first reference on the HandlerObj. 563 * Each region that uses the handler adds a reference. 564 */ 565 ObjDesc->Device.Handler = HandlerObj; 566 567 /* 568 * Walk the namespace finding all of the regions this 569 * handler will manage. 570 * 571 * Start at the device and search the branch toward 572 * the leaf nodes until either the leaf is encountered or 573 * a device is detected that has an address handler of the 574 * same type. 575 * 576 * In either case, back up and search down the remainder 577 * of the branch 578 */ 579 Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, 580 ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL, 581 HandlerObj, NULL); 582 583 UnlockAndExit: 584 return_ACPI_STATUS (Status); 585 }