167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
467754Smsmith *                         Address Spaces.
567754Smsmith *
667754Smsmith *****************************************************************************/
767754Smsmith
8217365Sjkim/*
9217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp.
1070243Smsmith * All rights reserved.
1167754Smsmith *
12217365Sjkim * Redistribution and use in source and binary forms, with or without
13217365Sjkim * modification, are permitted provided that the following conditions
14217365Sjkim * are met:
15217365Sjkim * 1. Redistributions of source code must retain the above copyright
16217365Sjkim *    notice, this list of conditions, and the following disclaimer,
17217365Sjkim *    without modification.
18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
20217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
21217365Sjkim *    including a substantially similar Disclaimer requirement for further
22217365Sjkim *    binary redistribution.
23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
24217365Sjkim *    of any contributors may be used to endorse or promote products derived
25217365Sjkim *    from this software without specific prior written permission.
2667754Smsmith *
27217365Sjkim * Alternatively, this software may be distributed under the terms of the
28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
29217365Sjkim * Software Foundation.
3067754Smsmith *
31217365Sjkim * NO WARRANTY
32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
43217365Sjkim */
4467754Smsmith
4567754Smsmith#define __EVXFREGN_C__
4667754Smsmith
47193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
48193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
49193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
50193341Sjkim#include <contrib/dev/acpica/include/acevents.h>
5167754Smsmith
5277424Smsmith#define _COMPONENT          ACPI_EVENTS
5391116Smsmith        ACPI_MODULE_NAME    ("evxfregn")
5467754Smsmith
5567754Smsmith
5677424Smsmith/*******************************************************************************
5767754Smsmith *
5867754Smsmith * FUNCTION:    AcpiInstallAddressSpaceHandler
5967754Smsmith *
6067754Smsmith * PARAMETERS:  Device          - Handle for the device
6167754Smsmith *              SpaceId         - The address space ID
6267754Smsmith *              Handler         - Address of the handler
6367754Smsmith *              Setup           - Address of the setup function
6467754Smsmith *              Context         - Value passed to the handler on each access
6567754Smsmith *
6667754Smsmith * RETURN:      Status
6767754Smsmith *
6867754Smsmith * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
6967754Smsmith *
70213806Sjkim * NOTE: This function should only be called after AcpiEnableSubsystem has
71213806Sjkim * been called. This is because any _REG methods associated with the Space ID
72213806Sjkim * are executed here, and these methods can only be safely executed after
73213806Sjkim * the default handlers have been installed and the hardware has been
74213806Sjkim * initialized (via AcpiEnableSubsystem.)
75213806Sjkim *
7667754Smsmith ******************************************************************************/
7767754Smsmith
7867754SmsmithACPI_STATUS
7967754SmsmithAcpiInstallAddressSpaceHandler (
8067754Smsmith    ACPI_HANDLE             Device,
8177424Smsmith    ACPI_ADR_SPACE_TYPE     SpaceId,
8277424Smsmith    ACPI_ADR_SPACE_HANDLER  Handler,
8377424Smsmith    ACPI_ADR_SPACE_SETUP    Setup,
8467754Smsmith    void                    *Context)
8567754Smsmith{
8667754Smsmith    ACPI_NAMESPACE_NODE     *Node;
8791116Smsmith    ACPI_STATUS             Status;
8867754Smsmith
8967754Smsmith
90167802Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallAddressSpaceHandler);
9167754Smsmith
9277424Smsmith
9367754Smsmith    /* Parameter validation */
9467754Smsmith
9591116Smsmith    if (!Device)
9667754Smsmith    {
9767754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
9867754Smsmith    }
9967754Smsmith
10091116Smsmith    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
10191116Smsmith    if (ACPI_FAILURE (Status))
10291116Smsmith    {
10391116Smsmith        return_ACPI_STATUS (Status);
10491116Smsmith    }
10567754Smsmith
10667754Smsmith    /* Convert and validate the device handle */
10767754Smsmith
108200553Sjkim    Node = AcpiNsValidateHandle (Device);
10967754Smsmith    if (!Node)
11067754Smsmith    {
11167754Smsmith        Status = AE_BAD_PARAMETER;
11267754Smsmith        goto UnlockAndExit;
11367754Smsmith    }
11467754Smsmith
115129684Snjl    /* Install the handler for all Regions for this Space ID */
11667754Smsmith
117129684Snjl    Status = AcpiEvInstallSpaceHandler (Node, SpaceId, Handler, Setup, Context);
118129684Snjl    if (ACPI_FAILURE (Status))
11967754Smsmith    {
12067754Smsmith        goto UnlockAndExit;
12167754Smsmith    }
12267754Smsmith
123218590Sjkim    /*
124218590Sjkim     * For the default SpaceIDs, (the IDs for which there are default region handlers
125218590Sjkim     * installed) Only execute the _REG methods if the global initialization _REG
126218590Sjkim     * methods have already been run (via AcpiInitializeObjects). In other words,
127218590Sjkim     * we will defer the execution of the _REG methods for these SpaceIDs until
128218590Sjkim     * execution of AcpiInitializeObjects. This is done because we need the handlers
129218590Sjkim     * for the default spaces (mem/io/pci/table) to be installed before we can run
130218590Sjkim     * any control methods (or _REG methods). There is known BIOS code that depends
131218590Sjkim     * on this.
132218590Sjkim     *
133218590Sjkim     * For all other SpaceIDs, we can safely execute the _REG methods immediately.
134218590Sjkim     * This means that for IDs like EmbeddedController, this function should be called
135218590Sjkim     * only after AcpiEnableSubsystem has been called.
136218590Sjkim     */
137218590Sjkim    switch (SpaceId)
138218590Sjkim    {
139218590Sjkim    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
140218590Sjkim    case ACPI_ADR_SPACE_SYSTEM_IO:
141218590Sjkim    case ACPI_ADR_SPACE_PCI_CONFIG:
142218590Sjkim    case ACPI_ADR_SPACE_DATA_TABLE:
14367754Smsmith
144220663Sjkim        if (!AcpiGbl_RegMethodsExecuted)
145218590Sjkim        {
146220663Sjkim            /* We will defer execution of the _REG methods for this space */
147220663Sjkim            goto UnlockAndExit;
148218590Sjkim        }
149218590Sjkim        break;
150218590Sjkim
151218590Sjkim    default:
152218590Sjkim        break;
153218590Sjkim    }
154218590Sjkim
155220663Sjkim    /* Run all _REG methods for this address space */
156218590Sjkim
157220663Sjkim    Status = AcpiEvExecuteRegMethods (Node, SpaceId);
158220663Sjkim
159220663Sjkim
16067754SmsmithUnlockAndExit:
16191116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
16267754Smsmith    return_ACPI_STATUS (Status);
16367754Smsmith}
16467754Smsmith
165167802SjkimACPI_EXPORT_SYMBOL (AcpiInstallAddressSpaceHandler)
16667754Smsmith
167167802Sjkim
16877424Smsmith/*******************************************************************************
16967754Smsmith *
17067754Smsmith * FUNCTION:    AcpiRemoveAddressSpaceHandler
17167754Smsmith *
172117521Snjl * PARAMETERS:  Device          - Handle for the device
173117521Snjl *              SpaceId         - The address space ID
17467754Smsmith *              Handler         - Address of the handler
17567754Smsmith *
17667754Smsmith * RETURN:      Status
17767754Smsmith *
178117521Snjl * DESCRIPTION: Remove a previously installed handler.
17967754Smsmith *
18067754Smsmith ******************************************************************************/
18167754Smsmith
18267754SmsmithACPI_STATUS
18367754SmsmithAcpiRemoveAddressSpaceHandler (
18467754Smsmith    ACPI_HANDLE             Device,
18577424Smsmith    ACPI_ADR_SPACE_TYPE     SpaceId,
18677424Smsmith    ACPI_ADR_SPACE_HANDLER  Handler)
18767754Smsmith{
18867754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
18967754Smsmith    ACPI_OPERAND_OBJECT     *HandlerObj;
19067754Smsmith    ACPI_OPERAND_OBJECT     *RegionObj;
19167754Smsmith    ACPI_OPERAND_OBJECT     **LastObjPtr;
19267754Smsmith    ACPI_NAMESPACE_NODE     *Node;
19391116Smsmith    ACPI_STATUS             Status;
19467754Smsmith
19567754Smsmith
196167802Sjkim    ACPI_FUNCTION_TRACE (AcpiRemoveAddressSpaceHandler);
19767754Smsmith
19867754Smsmith
19967754Smsmith    /* Parameter validation */
20067754Smsmith
20191116Smsmith    if (!Device)
20267754Smsmith    {
20367754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
20467754Smsmith    }
20567754Smsmith
20691116Smsmith    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
20791116Smsmith    if (ACPI_FAILURE (Status))
20891116Smsmith    {
20991116Smsmith        return_ACPI_STATUS (Status);
21091116Smsmith    }
21167754Smsmith
21267754Smsmith    /* Convert and validate the device handle */
21367754Smsmith
214200553Sjkim    Node = AcpiNsValidateHandle (Device);
215167802Sjkim    if (!Node ||
216167802Sjkim        ((Node->Type != ACPI_TYPE_DEVICE)    &&
217167802Sjkim         (Node->Type != ACPI_TYPE_PROCESSOR) &&
218167802Sjkim         (Node->Type != ACPI_TYPE_THERMAL)   &&
219167802Sjkim         (Node != AcpiGbl_RootNode)))
22067754Smsmith    {
22167754Smsmith        Status = AE_BAD_PARAMETER;
22267754Smsmith        goto UnlockAndExit;
22367754Smsmith    }
22467754Smsmith
22567754Smsmith    /* Make sure the internal object exists */
22667754Smsmith
22777424Smsmith    ObjDesc = AcpiNsGetAttachedObject (Node);
22867754Smsmith    if (!ObjDesc)
22967754Smsmith    {
23067754Smsmith        Status = AE_NOT_EXIST;
23167754Smsmith        goto UnlockAndExit;
23267754Smsmith    }
23367754Smsmith
234117521Snjl    /* Find the address handler the user requested */
235117521Snjl
236123315Snjl    HandlerObj = ObjDesc->Device.Handler;
237123315Snjl    LastObjPtr = &ObjDesc->Device.Handler;
23867754Smsmith    while (HandlerObj)
23967754Smsmith    {
240117521Snjl        /* We have a handler, see if user requested this one */
241117521Snjl
242117521Snjl        if (HandlerObj->AddressSpace.SpaceId == SpaceId)
24367754Smsmith        {
244167802Sjkim            /* Handler must be the same as the installed handler */
245167802Sjkim
246167802Sjkim            if (HandlerObj->AddressSpace.Handler != Handler)
247167802Sjkim            {
248167802Sjkim                Status = AE_BAD_PARAMETER;
249167802Sjkim                goto UnlockAndExit;
250167802Sjkim            }
251167802Sjkim
252117521Snjl            /* Matched SpaceId, first dereference this in the Regions */
253117521Snjl
25482367Smsmith            ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
255193267Sjkim                "Removing address handler %p(%p) for region %s "
256193267Sjkim                "on Device %p(%p)\n",
25777424Smsmith                HandlerObj, Handler, AcpiUtGetRegionName (SpaceId),
25867754Smsmith                Node, ObjDesc));
25967754Smsmith
260117521Snjl            RegionObj = HandlerObj->AddressSpace.RegionList;
26167754Smsmith
26267754Smsmith            /* Walk the handler's region list */
26367754Smsmith
26467754Smsmith            while (RegionObj)
26567754Smsmith            {
26667754Smsmith                /*
26785756Smsmith                 * First disassociate the handler from the region.
26867754Smsmith                 *
26985756Smsmith                 * NOTE: this doesn't mean that the region goes away
27085756Smsmith                 * The region is just inaccessible as indicated to
27185756Smsmith                 * the _REG method
27267754Smsmith                 */
27399679Siwasaki                AcpiEvDetachRegion (RegionObj, TRUE);
27467754Smsmith
27567754Smsmith                /*
276117521Snjl                 * Walk the list: Just grab the head because the
277117521Snjl                 * DetachRegion removed the previous head.
27867754Smsmith                 */
279117521Snjl                RegionObj = HandlerObj->AddressSpace.RegionList;
28067754Smsmith
28167754Smsmith            }
28267754Smsmith
283117521Snjl            /* Remove this Handler object from the list */
28467754Smsmith
285117521Snjl            *LastObjPtr = HandlerObj->AddressSpace.Next;
286117521Snjl
287117521Snjl            /* Now we can delete the handler object */
288117521Snjl
28977424Smsmith            AcpiUtRemoveReference (HandlerObj);
29067754Smsmith            goto UnlockAndExit;
29167754Smsmith        }
29267754Smsmith
293117521Snjl        /* Walk the linked list of handlers */
294117521Snjl
295117521Snjl        LastObjPtr = &HandlerObj->AddressSpace.Next;
296117521Snjl        HandlerObj = HandlerObj->AddressSpace.Next;
29767754Smsmith    }
29867754Smsmith
299117521Snjl    /* The handler does not exist */
30067754Smsmith
30182367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
30282367Smsmith        "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
30377424Smsmith        Handler, AcpiUtGetRegionName (SpaceId), SpaceId, Node, ObjDesc));
30467754Smsmith
30567754Smsmith    Status = AE_NOT_EXIST;
30667754Smsmith
30767754SmsmithUnlockAndExit:
30891116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
30967754Smsmith    return_ACPI_STATUS (Status);
31067754Smsmith}
31167754Smsmith
312167802SjkimACPI_EXPORT_SYMBOL (AcpiRemoveAddressSpaceHandler)
31367754Smsmith
314