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 }