[BACK]Return to evregion.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / external / bsd / acpica / dist / events

Annotation of src/sys/external/bsd/acpica/dist/events/evregion.c, Revision 1.1.1.20

1.1       jruoho      1: /******************************************************************************
                      2:  *
1.1.1.4   christos    3:  * Module Name: evregion - Operation Region support
1.1       jruoho      4:  *
                      5:  *****************************************************************************/
                      6:
1.1.1.2   jruoho      7: /*
1.1.1.19  christos    8:  * Copyright (C) 2000 - 2022, Intel Corp.
1.1       jruoho      9:  * All rights reserved.
                     10:  *
1.1.1.2   jruoho     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
1.1.1.17  christos   33:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1.1.1.2   jruoho     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:  */
1.1       jruoho     43:
                     44: #include "acpi.h"
                     45: #include "accommon.h"
                     46: #include "acevents.h"
                     47: #include "acnamesp.h"
                     48: #include "acinterp.h"
                     49:
                     50: #define _COMPONENT          ACPI_EVENTS
                     51:         ACPI_MODULE_NAME    ("evregion")
                     52:
                     53:
1.1.1.4   christos   54: extern UINT8        AcpiGbl_DefaultAddressSpaces[];
1.1       jruoho     55:
1.1.1.4   christos   56: /* Local prototypes */
1.1       jruoho     57:
1.1.1.3   jruoho     58: static void
1.1.1.16  christos   59: AcpiEvExecuteOrphanRegMethod (
                     60:     ACPI_NAMESPACE_NODE     *DeviceNode,
                     61:     ACPI_ADR_SPACE_TYPE     SpaceId);
                     62:
1.1.1.3   jruoho     63:
1.1       jruoho     64: static ACPI_STATUS
                     65: AcpiEvRegRun (
                     66:     ACPI_HANDLE             ObjHandle,
                     67:     UINT32                  Level,
                     68:     void                    *Context,
                     69:     void                    **ReturnValue);
                     70:
                     71:
                     72: /*******************************************************************************
                     73:  *
                     74:  * FUNCTION:    AcpiEvInitializeOpRegions
                     75:  *
                     76:  * PARAMETERS:  None
                     77:  *
                     78:  * RETURN:      Status
                     79:  *
                     80:  * DESCRIPTION: Execute _REG methods for all Operation Regions that have
                     81:  *              an installed default region handler.
                     82:  *
                     83:  ******************************************************************************/
                     84:
                     85: ACPI_STATUS
                     86: AcpiEvInitializeOpRegions (
                     87:     void)
                     88: {
                     89:     ACPI_STATUS             Status;
                     90:     UINT32                  i;
                     91:
                     92:
                     93:     ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
                     94:
                     95:
                     96:     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
                     97:     if (ACPI_FAILURE (Status))
                     98:     {
                     99:         return_ACPI_STATUS (Status);
                    100:     }
                    101:
                    102:     /* Run the _REG methods for OpRegions in each default address space */
                    103:
                    104:     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
                    105:     {
                    106:         /*
                    107:          * Make sure the installed handler is the DEFAULT handler. If not the
                    108:          * default, the _REG methods will have already been run (when the
                    109:          * handler was installed)
                    110:          */
                    111:         if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode,
                    112:                AcpiGbl_DefaultAddressSpaces[i]))
                    113:         {
1.1.1.7   christos  114:             AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
                    115:                 AcpiGbl_DefaultAddressSpaces[i], ACPI_REG_CONNECT);
1.1       jruoho    116:         }
                    117:     }
                    118:
                    119:     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
                    120:     return_ACPI_STATUS (Status);
                    121: }
                    122:
                    123:
                    124: /*******************************************************************************
                    125:  *
                    126:  * FUNCTION:    AcpiEvAddressSpaceDispatch
                    127:  *
                    128:  * PARAMETERS:  RegionObj           - Internal region object
1.1.1.4   christos  129:  *              FieldObj            - Corresponding field. Can be NULL.
1.1       jruoho    130:  *              Function            - Read or Write operation
                    131:  *              RegionOffset        - Where in the region to read or write
                    132:  *              BitWidth            - Field width in bits (8, 16, 32, or 64)
                    133:  *              Value               - Pointer to in or out value, must be
                    134:  *                                    a full 64-bit integer
                    135:  *
                    136:  * RETURN:      Status
                    137:  *
                    138:  * DESCRIPTION: Dispatch an address space or operation region access to
                    139:  *              a previously installed handler.
                    140:  *
1.1.1.7   christos  141:  * NOTE: During early initialization, we always install the default region
                    142:  * handlers for Memory, I/O and PCI_Config. This ensures that these operation
                    143:  * region address spaces are always available as per the ACPI specification.
                    144:  * This is especially needed in order to support the execution of
                    145:  * module-level AML code during loading of the ACPI tables.
                    146:  *
1.1       jruoho    147:  ******************************************************************************/
                    148:
                    149: ACPI_STATUS
                    150: AcpiEvAddressSpaceDispatch (
                    151:     ACPI_OPERAND_OBJECT     *RegionObj,
1.1.1.4   christos  152:     ACPI_OPERAND_OBJECT     *FieldObj,
1.1       jruoho    153:     UINT32                  Function,
                    154:     UINT32                  RegionOffset,
                    155:     UINT32                  BitWidth,
                    156:     UINT64                  *Value)
                    157: {
                    158:     ACPI_STATUS             Status;
                    159:     ACPI_ADR_SPACE_HANDLER  Handler;
                    160:     ACPI_ADR_SPACE_SETUP    RegionSetup;
                    161:     ACPI_OPERAND_OBJECT     *HandlerDesc;
                    162:     ACPI_OPERAND_OBJECT     *RegionObj2;
                    163:     void                    *RegionContext = NULL;
1.1.1.4   christos  164:     ACPI_CONNECTION_INFO    *Context;
1.1.1.17  christos  165:     ACPI_MUTEX              ContextMutex;
                    166:     BOOLEAN                 ContextLocked;
1.1.1.5   christos  167:     ACPI_PHYSICAL_ADDRESS   Address;
1.1       jruoho    168:
                    169:
                    170:     ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
                    171:
                    172:
                    173:     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
                    174:     if (!RegionObj2)
                    175:     {
                    176:         return_ACPI_STATUS (AE_NOT_EXIST);
                    177:     }
                    178:
                    179:     /* Ensure that there is a handler associated with this region */
                    180:
                    181:     HandlerDesc = RegionObj->Region.Handler;
                    182:     if (!HandlerDesc)
                    183:     {
                    184:         ACPI_ERROR ((AE_INFO,
                    185:             "No handler for Region [%4.4s] (%p) [%s]",
                    186:             AcpiUtGetNodeName (RegionObj->Region.Node),
                    187:             RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
                    188:
                    189:         return_ACPI_STATUS (AE_NOT_EXIST);
                    190:     }
                    191:
1.1.1.4   christos  192:     Context = HandlerDesc->AddressSpace.Context;
1.1.1.17  christos  193:     ContextMutex = HandlerDesc->AddressSpace.ContextMutex;
                    194:     ContextLocked = FALSE;
1.1.1.4   christos  195:
1.1       jruoho    196:     /*
                    197:      * It may be the case that the region has never been initialized.
                    198:      * Some types of regions require special init code
                    199:      */
                    200:     if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
                    201:     {
                    202:         /* This region has not been initialized yet, do it */
                    203:
                    204:         RegionSetup = HandlerDesc->AddressSpace.Setup;
                    205:         if (!RegionSetup)
                    206:         {
                    207:             /* No initialization routine, exit with error */
                    208:
                    209:             ACPI_ERROR ((AE_INFO,
                    210:                 "No init routine for region(%p) [%s]",
                    211:                 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
                    212:             return_ACPI_STATUS (AE_NOT_EXIST);
                    213:         }
                    214:
1.1.1.19  christos  215:         if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_PLATFORM_COMM)
                    216:         {
                    217:             ACPI_PCC_INFO *Ctx = HandlerDesc->AddressSpace.Context;
                    218:
                    219:             Ctx->InternalBuffer = FieldObj->Field.InternalPccBuffer;
                    220:             Ctx->Length = (UINT16) RegionObj->Region.Length;
                    221:             Ctx->SubspaceId = (UINT8) RegionObj->Region.Address;
                    222:         }
1.1.1.18  christos  223:
1.1.1.20! christos  224:         if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE)
        !           225:         {
        !           226:             ACPI_FFH_INFO *Ctx = HandlerDesc->AddressSpace.Context;
        !           227:
        !           228:             Ctx->Length = RegionObj->Region.Length;
        !           229:             Ctx->Offset = RegionObj->Region.Address;
        !           230:         }
        !           231:
1.1       jruoho    232:         /*
                    233:          * We must exit the interpreter because the region setup will
                    234:          * potentially execute control methods (for example, the _REG method
                    235:          * for this region)
                    236:          */
                    237:         AcpiExExitInterpreter ();
                    238:
                    239:         Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
1.1.1.7   christos  240:             Context, &RegionContext);
1.1       jruoho    241:
                    242:         /* Re-enter the interpreter */
                    243:
                    244:         AcpiExEnterInterpreter ();
                    245:
                    246:         /* Check for failure of the Region Setup */
                    247:
                    248:         if (ACPI_FAILURE (Status))
                    249:         {
                    250:             ACPI_EXCEPTION ((AE_INFO, Status,
                    251:                 "During region initialization: [%s]",
                    252:                 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
                    253:             return_ACPI_STATUS (Status);
                    254:         }
                    255:
                    256:         /* Region initialization may have been completed by RegionSetup */
                    257:
                    258:         if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
                    259:         {
                    260:             RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
                    261:
1.1.1.4   christos  262:             /*
                    263:              * Save the returned context for use in all accesses to
                    264:              * the handler for this particular region
                    265:              */
                    266:             if (!(RegionObj2->Extra.RegionContext))
1.1       jruoho    267:             {
                    268:                 RegionObj2->Extra.RegionContext = RegionContext;
                    269:             }
                    270:         }
                    271:     }
                    272:
                    273:     /* We have everything we need, we can invoke the address space handler */
                    274:
                    275:     Handler = HandlerDesc->AddressSpace.Handler;
1.1.1.5   christos  276:     Address = (RegionObj->Region.Address + RegionOffset);
1.1       jruoho    277:
1.1.1.17  christos  278:     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
                    279:         "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
                    280:         &RegionObj->Region.Handler->AddressSpace, Handler,
                    281:         ACPI_FORMAT_UINT64 (Address),
                    282:         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
                    283:
                    284:     if (!(HandlerDesc->AddressSpace.HandlerFlags &
                    285:         ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
                    286:     {
                    287:         /*
                    288:          * For handlers other than the default (supplied) handlers, we must
                    289:          * exit the interpreter because the handler *might* block -- we don't
                    290:          * know what it will do, so we can't hold the lock on the interpreter.
                    291:          */
                    292:         AcpiExExitInterpreter();
                    293:     }
                    294:
1.1.1.4   christos  295:     /*
                    296:      * Special handling for GenericSerialBus and GeneralPurposeIo:
                    297:      * There are three extra parameters that must be passed to the
                    298:      * handler via the context:
1.1.1.5   christos  299:      *   1) Connection buffer, a resource template from Connection() op
                    300:      *   2) Length of the above buffer
                    301:      *   3) Actual access length from the AccessAs() op
                    302:      *
1.1.1.17  christos  303:      * Since we pass these extra parameters via the context, which is
                    304:      * shared between threads, we must lock the context to avoid these
                    305:      * parameters being changed from another thread before the handler
                    306:      * has completed running.
                    307:      *
1.1.1.5   christos  308:      * In addition, for GeneralPurposeIo, the Address and BitWidth fields
                    309:      * are defined as follows:
                    310:      *   1) Address is the pin number index of the field (bit offset from
                    311:      *      the previous Connection)
                    312:      *   2) BitWidth is the actual bit length of the field (number of pins)
1.1.1.4   christos  313:      */
1.1.1.17  christos  314:     if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS ||
                    315:          RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) &&
1.1.1.4   christos  316:         Context &&
                    317:         FieldObj)
                    318:     {
                    319:
1.1.1.17  christos  320:         Status = AcpiOsAcquireMutex (ContextMutex, ACPI_WAIT_FOREVER);
                    321:         if (ACPI_FAILURE (Status))
                    322:         {
                    323:             goto ReEnterInterpreter;
                    324:         }
                    325:
                    326:         ContextLocked = TRUE;
                    327:
1.1.1.5   christos  328:         /* Get the Connection (ResourceTemplate) buffer */
                    329:
                    330:         Context->Connection = FieldObj->Field.ResourceBuffer;
                    331:         Context->Length = FieldObj->Field.ResourceLength;
                    332:         Context->AccessLength = FieldObj->Field.AccessLength;
                    333:
1.1.1.17  christos  334:         if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)
                    335:         {
                    336:             Address = FieldObj->Field.PinNumberIndex;
                    337:             BitWidth = FieldObj->Field.BitLength;
                    338:         }
1.1       jruoho    339:     }
                    340:
                    341:     /* Call the handler */
                    342:
1.1.1.5   christos  343:     Status = Handler (Function, Address, BitWidth, Value, Context,
                    344:         RegionObj2->Extra.RegionContext);
1.1       jruoho    345:
1.1.1.17  christos  346:     if (ContextLocked)
                    347:     {
                    348:         AcpiOsReleaseMutex (ContextMutex);
                    349:     }
                    350:
1.1       jruoho    351:     if (ACPI_FAILURE (Status))
                    352:     {
                    353:         ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
                    354:             AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
1.1.1.10  christos  355:
                    356:         /*
                    357:          * Special case for an EC timeout. These are seen so frequently
                    358:          * that an additional error message is helpful
                    359:          */
                    360:         if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) &&
                    361:             (Status == AE_TIME))
                    362:         {
                    363:             ACPI_ERROR ((AE_INFO,
                    364:                 "Timeout from EC hardware or EC device driver"));
                    365:         }
1.1       jruoho    366:     }
                    367:
1.1.1.17  christos  368: ReEnterInterpreter:
1.1       jruoho    369:     if (!(HandlerDesc->AddressSpace.HandlerFlags &
1.1.1.7   christos  370:         ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
1.1       jruoho    371:     {
                    372:         /*
                    373:          * We just returned from a non-default handler, we must re-enter the
                    374:          * interpreter
                    375:          */
1.1.1.7   christos  376:         AcpiExEnterInterpreter ();
1.1       jruoho    377:     }
                    378:
                    379:     return_ACPI_STATUS (Status);
                    380: }
                    381:
                    382:
                    383: /*******************************************************************************
                    384:  *
                    385:  * FUNCTION:    AcpiEvDetachRegion
                    386:  *
                    387:  * PARAMETERS:  RegionObj           - Region Object
                    388:  *              AcpiNsIsLocked      - Namespace Region Already Locked?
                    389:  *
                    390:  * RETURN:      None
                    391:  *
                    392:  * DESCRIPTION: Break the association between the handler and the region
                    393:  *              this is a two way association.
                    394:  *
                    395:  ******************************************************************************/
                    396:
                    397: void
1.1.1.7   christos  398: AcpiEvDetachRegion (
1.1       jruoho    399:     ACPI_OPERAND_OBJECT     *RegionObj,
                    400:     BOOLEAN                 AcpiNsIsLocked)
                    401: {
                    402:     ACPI_OPERAND_OBJECT     *HandlerObj;
                    403:     ACPI_OPERAND_OBJECT     *ObjDesc;
1.1.1.5   christos  404:     ACPI_OPERAND_OBJECT     *StartDesc;
1.1       jruoho    405:     ACPI_OPERAND_OBJECT     **LastObjPtr;
                    406:     ACPI_ADR_SPACE_SETUP    RegionSetup;
                    407:     void                    **RegionContext;
                    408:     ACPI_OPERAND_OBJECT     *RegionObj2;
                    409:     ACPI_STATUS             Status;
                    410:
                    411:
                    412:     ACPI_FUNCTION_TRACE (EvDetachRegion);
                    413:
                    414:
                    415:     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
                    416:     if (!RegionObj2)
                    417:     {
                    418:         return_VOID;
                    419:     }
                    420:     RegionContext = &RegionObj2->Extra.RegionContext;
                    421:
                    422:     /* Get the address handler from the region object */
                    423:
                    424:     HandlerObj = RegionObj->Region.Handler;
                    425:     if (!HandlerObj)
                    426:     {
                    427:         /* This region has no handler, all done */
                    428:
                    429:         return_VOID;
                    430:     }
                    431:
                    432:     /* Find this region in the handler's list */
                    433:
                    434:     ObjDesc = HandlerObj->AddressSpace.RegionList;
1.1.1.5   christos  435:     StartDesc = ObjDesc;
1.1       jruoho    436:     LastObjPtr = &HandlerObj->AddressSpace.RegionList;
                    437:
                    438:     while (ObjDesc)
                    439:     {
                    440:         /* Is this the correct Region? */
                    441:
                    442:         if (ObjDesc == RegionObj)
                    443:         {
                    444:             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
                    445:                 "Removing Region %p from address handler %p\n",
                    446:                 RegionObj, HandlerObj));
                    447:
                    448:             /* This is it, remove it from the handler's list */
                    449:
                    450:             *LastObjPtr = ObjDesc->Region.Next;
                    451:             ObjDesc->Region.Next = NULL;        /* Must clear field */
                    452:
                    453:             if (AcpiNsIsLocked)
                    454:             {
                    455:                 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
                    456:                 if (ACPI_FAILURE (Status))
                    457:                 {
                    458:                     return_VOID;
                    459:                 }
                    460:             }
                    461:
                    462:             /* Now stop region accesses by executing the _REG method */
                    463:
1.1.1.3   jruoho    464:             Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT);
1.1       jruoho    465:             if (ACPI_FAILURE (Status))
                    466:             {
                    467:                 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
                    468:                     AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
                    469:             }
                    470:
                    471:             if (AcpiNsIsLocked)
                    472:             {
                    473:                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
                    474:                 if (ACPI_FAILURE (Status))
                    475:                 {
                    476:                     return_VOID;
                    477:                 }
                    478:             }
                    479:
                    480:             /*
                    481:              * If the region has been activated, call the setup handler with
                    482:              * the deactivate notification
                    483:              */
                    484:             if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
                    485:             {
                    486:                 RegionSetup = HandlerObj->AddressSpace.Setup;
                    487:                 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
                    488:                     HandlerObj->AddressSpace.Context, RegionContext);
                    489:
1.1.1.4   christos  490:                 /*
                    491:                  * RegionContext should have been released by the deactivate
                    492:                  * operation. We don't need access to it anymore here.
                    493:                  */
                    494:                 if (RegionContext)
                    495:                 {
                    496:                     *RegionContext = NULL;
                    497:                 }
                    498:
1.1       jruoho    499:                 /* Init routine may fail, Just ignore errors */
                    500:
                    501:                 if (ACPI_FAILURE (Status))
                    502:                 {
                    503:                     ACPI_EXCEPTION ((AE_INFO, Status,
                    504:                         "from region handler - deactivate, [%s]",
                    505:                         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
                    506:                 }
                    507:
                    508:                 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
                    509:             }
                    510:
                    511:             /*
                    512:              * Remove handler reference in the region
                    513:              *
                    514:              * NOTE: this doesn't mean that the region goes away, the region
                    515:              * is just inaccessible as indicated to the _REG method
                    516:              *
                    517:              * If the region is on the handler's list, this must be the
                    518:              * region's handler
                    519:              */
                    520:             RegionObj->Region.Handler = NULL;
                    521:             AcpiUtRemoveReference (HandlerObj);
                    522:
                    523:             return_VOID;
                    524:         }
                    525:
                    526:         /* Walk the linked list of handlers */
                    527:
                    528:         LastObjPtr = &ObjDesc->Region.Next;
                    529:         ObjDesc = ObjDesc->Region.Next;
1.1.1.5   christos  530:
                    531:         /* Prevent infinite loop if list is corrupted */
                    532:
                    533:         if (ObjDesc == StartDesc)
                    534:         {
                    535:             ACPI_ERROR ((AE_INFO,
                    536:                 "Circular handler list in region object %p",
                    537:                 RegionObj));
                    538:             return_VOID;
                    539:         }
1.1       jruoho    540:     }
                    541:
                    542:     /* If we get here, the region was not in the handler's region list */
                    543:
                    544:     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
                    545:         "Cannot remove region %p from address handler %p\n",
                    546:         RegionObj, HandlerObj));
                    547:
                    548:     return_VOID;
                    549: }
                    550:
                    551:
                    552: /*******************************************************************************
                    553:  *
                    554:  * FUNCTION:    AcpiEvAttachRegion
                    555:  *
                    556:  * PARAMETERS:  HandlerObj          - Handler Object
                    557:  *              RegionObj           - Region Object
                    558:  *              AcpiNsIsLocked      - Namespace Region Already Locked?
                    559:  *
                    560:  * RETURN:      None
                    561:  *
                    562:  * DESCRIPTION: Create the association between the handler and the region
                    563:  *              this is a two way association.
                    564:  *
                    565:  ******************************************************************************/
                    566:
                    567: ACPI_STATUS
                    568: AcpiEvAttachRegion (
                    569:     ACPI_OPERAND_OBJECT     *HandlerObj,
                    570:     ACPI_OPERAND_OBJECT     *RegionObj,
                    571:     BOOLEAN                 AcpiNsIsLocked)
                    572: {
                    573:
                    574:     ACPI_FUNCTION_TRACE (EvAttachRegion);
                    575:
                    576:
1.1.1.7   christos  577:     /* Install the region's handler */
                    578:
                    579:     if (RegionObj->Region.Handler)
                    580:     {
                    581:         return_ACPI_STATUS (AE_ALREADY_EXISTS);
                    582:     }
                    583:
1.1       jruoho    584:     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
                    585:         "Adding Region [%4.4s] %p to address handler %p [%s]\n",
                    586:         AcpiUtGetNodeName (RegionObj->Region.Node),
                    587:         RegionObj, HandlerObj,
                    588:         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
                    589:
                    590:     /* Link this region to the front of the handler's list */
                    591:
                    592:     RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
                    593:     HandlerObj->AddressSpace.RegionList = RegionObj;
1.1.1.7   christos  594:     RegionObj->Region.Handler = HandlerObj;
                    595:     AcpiUtAddReference (HandlerObj);
1.1       jruoho    596:
1.1.1.7   christos  597:     return_ACPI_STATUS (AE_OK);
                    598: }
1.1       jruoho    599:
1.1.1.7   christos  600:
                    601: /*******************************************************************************
                    602:  *
1.1.1.4   christos  603:  * FUNCTION:    AcpiEvExecuteRegMethod
1.1       jruoho    604:  *
1.1.1.4   christos  605:  * PARAMETERS:  RegionObj           - Region object
                    606:  *              Function            - Passed to _REG: On (1) or Off (0)
1.1       jruoho    607:  *
                    608:  * RETURN:      Status
                    609:  *
1.1.1.4   christos  610:  * DESCRIPTION: Execute _REG method for a region
1.1       jruoho    611:  *
                    612:  ******************************************************************************/
                    613:
                    614: ACPI_STATUS
1.1.1.4   christos  615: AcpiEvExecuteRegMethod (
                    616:     ACPI_OPERAND_OBJECT     *RegionObj,
                    617:     UINT32                  Function)
1.1       jruoho    618: {
1.1.1.4   christos  619:     ACPI_EVALUATE_INFO      *Info;
                    620:     ACPI_OPERAND_OBJECT     *Args[3];
                    621:     ACPI_OPERAND_OBJECT     *RegionObj2;
1.1.1.8   christos  622:     const ACPI_NAME         *RegNamePtr = ACPI_CAST_PTR (ACPI_NAME, METHOD_NAME__REG);
                    623:     ACPI_NAMESPACE_NODE     *MethodNode;
                    624:     ACPI_NAMESPACE_NODE     *Node;
1.1       jruoho    625:     ACPI_STATUS             Status;
                    626:
                    627:
1.1.1.4   christos  628:     ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
1.1       jruoho    629:
                    630:
1.1.1.8   christos  631:     if (!AcpiGbl_NamespaceInitialized ||
                    632:         RegionObj->Region.Handler == NULL)
                    633:     {
                    634:         return_ACPI_STATUS (AE_OK);
                    635:     }
                    636:
1.1.1.4   christos  637:     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
                    638:     if (!RegionObj2)
1.1       jruoho    639:     {
1.1.1.4   christos  640:         return_ACPI_STATUS (AE_NOT_EXIST);
1.1       jruoho    641:     }
                    642:
1.1.1.8   christos  643:     /*
                    644:      * Find any "_REG" method associated with this region definition.
                    645:      * The method should always be updated as this function may be
                    646:      * invoked after a namespace change.
                    647:      */
                    648:     Node = RegionObj->Region.Node->Parent;
                    649:     Status = AcpiNsSearchOneScope (
                    650:         *RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode);
                    651:     if (ACPI_SUCCESS (Status))
                    652:     {
                    653:         /*
                    654:          * The _REG method is optional and there can be only one per
                    655:          * region definition. This will be executed when the handler is
                    656:          * attached or removed.
                    657:          */
                    658:         RegionObj2->Extra.Method_REG = MethodNode;
                    659:     }
                    660:     if (RegionObj2->Extra.Method_REG == NULL)
1.1.1.7   christos  661:     {
                    662:         return_ACPI_STATUS (AE_OK);
                    663:     }
                    664:
                    665:     /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */
                    666:
                    667:     if ((Function == ACPI_REG_CONNECT &&
                    668:         RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED) ||
                    669:         (Function == ACPI_REG_DISCONNECT &&
                    670:          !(RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED)))
1.1       jruoho    671:     {
1.1.1.4   christos  672:         return_ACPI_STATUS (AE_OK);
1.1       jruoho    673:     }
                    674:
1.1.1.4   christos  675:     /* Allocate and initialize the evaluation information block */
1.1       jruoho    676:
1.1.1.4   christos  677:     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
                    678:     if (!Info)
1.1       jruoho    679:     {
1.1.1.4   christos  680:         return_ACPI_STATUS (AE_NO_MEMORY);
1.1       jruoho    681:     }
                    682:
1.1.1.4   christos  683:     Info->PrefixNode = RegionObj2->Extra.Method_REG;
                    684:     Info->RelativePathname = NULL;
                    685:     Info->Parameters = Args;
                    686:     Info->Flags = ACPI_IGNORE_RETURN_VALUE;
1.1       jruoho    687:
                    688:     /*
1.1.1.4   christos  689:      * The _REG method has two arguments:
                    690:      *
                    691:      * Arg0 - Integer:
                    692:      *  Operation region space ID Same value as RegionObj->Region.SpaceId
1.1       jruoho    693:      *
1.1.1.4   christos  694:      * Arg1 - Integer:
                    695:      *  connection status 1 for connecting the handler, 0 for disconnecting
                    696:      *  the handler (Passed as a parameter)
1.1       jruoho    697:      */
1.1.1.4   christos  698:     Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
                    699:     if (!Args[0])
1.1       jruoho    700:     {
                    701:         Status = AE_NO_MEMORY;
1.1.1.4   christos  702:         goto Cleanup1;
1.1       jruoho    703:     }
                    704:
1.1.1.4   christos  705:     Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
                    706:     if (!Args[1])
                    707:     {
                    708:         Status = AE_NO_MEMORY;
                    709:         goto Cleanup2;
                    710:     }
1.1       jruoho    711:
1.1.1.4   christos  712:     Args[2] = NULL; /* Terminate list */
1.1       jruoho    713:
1.1.1.4   christos  714:     /* Execute the method, no return value */
1.1       jruoho    715:
1.1.1.4   christos  716:     ACPI_DEBUG_EXEC (
                    717:         AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
1.1       jruoho    718:
1.1.1.4   christos  719:     Status = AcpiNsEvaluate (Info);
                    720:     AcpiUtRemoveReference (Args[1]);
1.1       jruoho    721:
1.1.1.7   christos  722:     if (ACPI_FAILURE (Status))
                    723:     {
                    724:         goto Cleanup2;
                    725:     }
                    726:
                    727:     if (Function == ACPI_REG_CONNECT)
                    728:     {
                    729:         RegionObj->Common.Flags |= AOPOBJ_REG_CONNECTED;
                    730:     }
                    731:     else
                    732:     {
                    733:         RegionObj->Common.Flags &= ~AOPOBJ_REG_CONNECTED;
                    734:     }
                    735:
1.1.1.4   christos  736: Cleanup2:
                    737:     AcpiUtRemoveReference (Args[0]);
1.1       jruoho    738:
1.1.1.4   christos  739: Cleanup1:
                    740:     ACPI_FREE (Info);
1.1       jruoho    741:     return_ACPI_STATUS (Status);
                    742: }
                    743:
                    744:
                    745: /*******************************************************************************
                    746:  *
                    747:  * FUNCTION:    AcpiEvExecuteRegMethods
                    748:  *
                    749:  * PARAMETERS:  Node            - Namespace node for the device
                    750:  *              SpaceId         - The address space ID
1.1.1.7   christos  751:  *              Function        - Passed to _REG: On (1) or Off (0)
1.1       jruoho    752:  *
1.1.1.7   christos  753:  * RETURN:      None
1.1       jruoho    754:  *
                    755:  * DESCRIPTION: Run all _REG methods for the input Space ID;
                    756:  *              Note: assumes namespace is locked, or system init time.
                    757:  *
                    758:  ******************************************************************************/
                    759:
1.1.1.7   christos  760: void
1.1       jruoho    761: AcpiEvExecuteRegMethods (
                    762:     ACPI_NAMESPACE_NODE     *Node,
1.1.1.7   christos  763:     ACPI_ADR_SPACE_TYPE     SpaceId,
                    764:     UINT32                  Function)
1.1       jruoho    765: {
1.1.1.7   christos  766:     ACPI_REG_WALK_INFO      Info;
1.1       jruoho    767:
                    768:
                    769:     ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
                    770:
1.1.1.12  christos  771:     /*
                    772:      * These address spaces do not need a call to _REG, since the ACPI
                    773:      * specification defines them as: "must always be accessible". Since
                    774:      * they never change state (never become unavailable), no need to ever
                    775:      * call _REG on them. Also, a DataTable is not a "real" address space,
                    776:      * so do not call _REG. September 2018.
                    777:      */
                    778:     if ((SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||
                    779:         (SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) ||
                    780:         (SpaceId == ACPI_ADR_SPACE_DATA_TABLE))
                    781:     {
                    782:         return_VOID;
                    783:     }
                    784:
1.1.1.7   christos  785:     Info.SpaceId = SpaceId;
                    786:     Info.Function = Function;
                    787:     Info.RegRunCount = 0;
                    788:
                    789:     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES,
                    790:         "    Running _REG methods for SpaceId %s\n",
                    791:         AcpiUtGetRegionName (Info.SpaceId)));
1.1       jruoho    792:
                    793:     /*
                    794:      * Run all _REG methods for all Operation Regions for this space ID. This
                    795:      * is a separate walk in order to handle any interdependencies between
                    796:      * regions and _REG methods. (i.e. handlers must be installed for all
                    797:      * regions of this Space ID before we can run any _REG methods)
                    798:      */
1.1.1.7   christos  799:     (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
                    800:         ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, &Info, NULL);
1.1       jruoho    801:
1.1.1.16  christos  802:     /*
                    803:      * Special case for EC and GPIO: handle "orphan" _REG methods with
                    804:      * no region.
                    805:      */
                    806:     if (SpaceId == ACPI_ADR_SPACE_EC || SpaceId == ACPI_ADR_SPACE_GPIO)
1.1.1.3   jruoho    807:     {
1.1.1.16  christos  808:         AcpiEvExecuteOrphanRegMethod (Node, SpaceId);
1.1.1.3   jruoho    809:     }
                    810:
1.1.1.7   christos  811:     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES,
                    812:         "    Executed %u _REG methods for SpaceId %s\n",
                    813:         Info.RegRunCount, AcpiUtGetRegionName (Info.SpaceId)));
                    814:
                    815:     return_VOID;
1.1       jruoho    816: }
                    817:
                    818:
                    819: /*******************************************************************************
                    820:  *
                    821:  * FUNCTION:    AcpiEvRegRun
                    822:  *
                    823:  * PARAMETERS:  WalkNamespace callback
                    824:  *
                    825:  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
                    826:  *
                    827:  ******************************************************************************/
                    828:
                    829: static ACPI_STATUS
                    830: AcpiEvRegRun (
                    831:     ACPI_HANDLE             ObjHandle,
                    832:     UINT32                  Level,
                    833:     void                    *Context,
                    834:     void                    **ReturnValue)
                    835: {
                    836:     ACPI_OPERAND_OBJECT     *ObjDesc;
                    837:     ACPI_NAMESPACE_NODE     *Node;
                    838:     ACPI_STATUS             Status;
1.1.1.7   christos  839:     ACPI_REG_WALK_INFO      *Info;
1.1       jruoho    840:
                    841:
1.1.1.7   christos  842:     Info = ACPI_CAST_PTR (ACPI_REG_WALK_INFO, Context);
1.1       jruoho    843:
                    844:     /* Convert and validate the device handle */
                    845:
                    846:     Node = AcpiNsValidateHandle (ObjHandle);
                    847:     if (!Node)
                    848:     {
                    849:         return (AE_BAD_PARAMETER);
                    850:     }
                    851:
                    852:     /*
1.1.1.12  christos  853:      * We only care about regions and objects that are allowed to have
                    854:      * address space handlers
1.1       jruoho    855:      */
                    856:     if ((Node->Type != ACPI_TYPE_REGION) &&
                    857:         (Node != AcpiGbl_RootNode))
                    858:     {
                    859:         return (AE_OK);
                    860:     }
                    861:
                    862:     /* Check for an existing internal object */
                    863:
                    864:     ObjDesc = AcpiNsGetAttachedObject (Node);
                    865:     if (!ObjDesc)
                    866:     {
                    867:         /* No object, just exit */
                    868:
                    869:         return (AE_OK);
                    870:     }
                    871:
                    872:     /* Object is a Region */
                    873:
1.1.1.7   christos  874:     if (ObjDesc->Region.SpaceId != Info->SpaceId)
1.1       jruoho    875:     {
                    876:         /* This region is for a different address space, just ignore it */
                    877:
                    878:         return (AE_OK);
                    879:     }
                    880:
1.1.1.7   christos  881:     Info->RegRunCount++;
                    882:     Status = AcpiEvExecuteRegMethod (ObjDesc, Info->Function);
1.1       jruoho    883:     return (Status);
                    884: }
                    885:
1.1.1.3   jruoho    886:
                    887: /*******************************************************************************
                    888:  *
1.1.1.16  christos  889:  * FUNCTION:    AcpiEvExecuteOrphanRegMethod
1.1.1.3   jruoho    890:  *
1.1.1.16  christos  891:  * PARAMETERS:  DeviceNode          - Namespace node for an ACPI device
                    892:  *              SpaceId             - The address space ID
1.1.1.3   jruoho    893:  *
                    894:  * RETURN:      None
                    895:  *
1.1.1.16  christos  896:  * DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI
1.1.1.3   jruoho    897:  *              device. This is a _REG method that has no corresponding region
1.1.1.16  christos  898:  *              within the device's scope. ACPI tables depending on these
                    899:  *              "orphan" _REG methods have been seen for both EC and GPIO
                    900:  *              Operation Regions. Presumably the Windows ACPI implementation
                    901:  *              always calls the _REG method independent of the presence of
                    902:  *              an actual Operation Region with the correct address space ID.
1.1.1.4   christos  903:  *
                    904:  *  MUTEX:      Assumes the namespace is locked
1.1.1.3   jruoho    905:  *
                    906:  ******************************************************************************/
                    907:
                    908: static void
1.1.1.16  christos  909: AcpiEvExecuteOrphanRegMethod (
                    910:     ACPI_NAMESPACE_NODE     *DeviceNode,
                    911:     ACPI_ADR_SPACE_TYPE     SpaceId)
1.1.1.3   jruoho    912: {
1.1.1.4   christos  913:     ACPI_HANDLE             RegMethod;
                    914:     ACPI_NAMESPACE_NODE     *NextNode;
1.1.1.3   jruoho    915:     ACPI_STATUS             Status;
                    916:     ACPI_OBJECT_LIST        Args;
                    917:     ACPI_OBJECT             Objects[2];
                    918:
                    919:
1.1.1.16  christos  920:     ACPI_FUNCTION_TRACE (EvExecuteOrphanRegMethod);
1.1.1.3   jruoho    921:
                    922:
1.1.1.16  christos  923:     if (!DeviceNode)
1.1.1.3   jruoho    924:     {
                    925:         return_VOID;
                    926:     }
                    927:
                    928:     /* Namespace is currently locked, must release */
                    929:
                    930:     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
                    931:
                    932:     /* Get a handle to a _REG method immediately under the EC device */
                    933:
1.1.1.16  christos  934:     Status = AcpiGetHandle (DeviceNode, METHOD_NAME__REG, &RegMethod);
1.1.1.3   jruoho    935:     if (ACPI_FAILURE (Status))
                    936:     {
1.1.1.4   christos  937:         goto Exit; /* There is no _REG method present */
1.1.1.3   jruoho    938:     }
                    939:
                    940:     /*
                    941:      * Execute the _REG method only if there is no Operation Region in
                    942:      * this scope with the Embedded Controller space ID. Otherwise, it
                    943:      * will already have been executed. Note, this allows for Regions
                    944:      * with other space IDs to be present; but the code below will then
1.1.1.4   christos  945:      * execute the _REG method with the EmbeddedControl SpaceID argument.
1.1.1.3   jruoho    946:      */
1.1.1.16  christos  947:     NextNode = AcpiNsGetNextNode (DeviceNode, NULL);
1.1.1.3   jruoho    948:     while (NextNode)
                    949:     {
                    950:         if ((NextNode->Type == ACPI_TYPE_REGION) &&
                    951:             (NextNode->Object) &&
1.1.1.16  christos  952:             (NextNode->Object->Region.SpaceId == SpaceId))
1.1.1.3   jruoho    953:         {
1.1.1.4   christos  954:             goto Exit; /* Do not execute the _REG */
1.1.1.3   jruoho    955:         }
1.1.1.4   christos  956:
1.1.1.16  christos  957:         NextNode = AcpiNsGetNextNode (DeviceNode, NextNode);
1.1.1.3   jruoho    958:     }
                    959:
1.1.1.16  christos  960:     /* Evaluate the _REG(SpaceId,Connect) method */
1.1.1.3   jruoho    961:
                    962:     Args.Count = 2;
                    963:     Args.Pointer = Objects;
                    964:     Objects[0].Type = ACPI_TYPE_INTEGER;
1.1.1.16  christos  965:     Objects[0].Integer.Value = SpaceId;
1.1.1.3   jruoho    966:     Objects[1].Type = ACPI_TYPE_INTEGER;
                    967:     Objects[1].Integer.Value = ACPI_REG_CONNECT;
                    968:
1.1.1.14  christos  969:     (void) AcpiEvaluateObject (RegMethod, NULL, &Args, NULL);
1.1.1.3   jruoho    970:
                    971: Exit:
                    972:     /* We ignore all errors from above, don't care */
                    973:
1.1.1.14  christos  974:     (void) AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1.1.1.3   jruoho    975:     return_VOID;
                    976: }

CVSweb <webmaster@jp.NetBSD.org>