Home | History | Annotate | Line # | Download | only in events
evhandler.c revision 1.1.1.1
      1 /******************************************************************************
      2  *
      3  * Module Name: evhandler - Support for Address Space handlers
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2013, 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 }
    586