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