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