1244971Sjkim/******************************************************************************
2244971Sjkim *
3244971Sjkim * Module Name: evhandler - Support for Address Space handlers
4244971Sjkim *
5244971Sjkim *****************************************************************************/
6244971Sjkim
7244971Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9244971Sjkim * All rights reserved.
10244971Sjkim *
11244971Sjkim * Redistribution and use in source and binary forms, with or without
12244971Sjkim * modification, are permitted provided that the following conditions
13244971Sjkim * are met:
14244971Sjkim * 1. Redistributions of source code must retain the above copyright
15244971Sjkim *    notice, this list of conditions, and the following disclaimer,
16244971Sjkim *    without modification.
17244971Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18244971Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19244971Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20244971Sjkim *    including a substantially similar Disclaimer requirement for further
21244971Sjkim *    binary redistribution.
22244971Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23244971Sjkim *    of any contributors may be used to endorse or promote products derived
24244971Sjkim *    from this software without specific prior written permission.
25244971Sjkim *
26244971Sjkim * Alternatively, this software may be distributed under the terms of the
27244971Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28244971Sjkim * Software Foundation.
29244971Sjkim *
30244971Sjkim * NO WARRANTY
31244971Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32244971Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33244971Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34244971Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35244971Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36244971Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37244971Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38244971Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39244971Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40244971Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41244971Sjkim * POSSIBILITY OF SUCH DAMAGES.
42244971Sjkim */
43244971Sjkim
44245582Sjkim#include <contrib/dev/acpica/include/acpi.h>
45245582Sjkim#include <contrib/dev/acpica/include/accommon.h>
46245582Sjkim#include <contrib/dev/acpica/include/acevents.h>
47245582Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
48245582Sjkim#include <contrib/dev/acpica/include/acinterp.h>
49244971Sjkim
50244971Sjkim#define _COMPONENT          ACPI_EVENTS
51244971Sjkim        ACPI_MODULE_NAME    ("evhandler")
52244971Sjkim
53244971Sjkim
54244971Sjkim/* Local prototypes */
55244971Sjkim
56244971Sjkimstatic ACPI_STATUS
57244971SjkimAcpiEvInstallHandler (
58244971Sjkim    ACPI_HANDLE             ObjHandle,
59244971Sjkim    UINT32                  Level,
60244971Sjkim    void                    *Context,
61244971Sjkim    void                    **ReturnValue);
62244971Sjkim
63306536Sjkim
64244971Sjkim/* These are the address spaces that will get default handlers */
65244971Sjkim
66244971SjkimUINT8        AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
67244971Sjkim{
68244971Sjkim    ACPI_ADR_SPACE_SYSTEM_MEMORY,
69244971Sjkim    ACPI_ADR_SPACE_SYSTEM_IO,
70244971Sjkim    ACPI_ADR_SPACE_PCI_CONFIG,
71244971Sjkim    ACPI_ADR_SPACE_DATA_TABLE
72244971Sjkim};
73244971Sjkim
74244971Sjkim
75244971Sjkim/*******************************************************************************
76244971Sjkim *
77244971Sjkim * FUNCTION:    AcpiEvInstallRegionHandlers
78244971Sjkim *
79244971Sjkim * PARAMETERS:  None
80244971Sjkim *
81244971Sjkim * RETURN:      Status
82244971Sjkim *
83244971Sjkim * DESCRIPTION: Installs the core subsystem default address space handlers.
84244971Sjkim *
85244971Sjkim ******************************************************************************/
86244971Sjkim
87244971SjkimACPI_STATUS
88244971SjkimAcpiEvInstallRegionHandlers (
89244971Sjkim    void)
90244971Sjkim{
91244971Sjkim    ACPI_STATUS             Status;
92244971Sjkim    UINT32                  i;
93244971Sjkim
94244971Sjkim
95244971Sjkim    ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
96244971Sjkim
97244971Sjkim
98244971Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
99244971Sjkim    if (ACPI_FAILURE (Status))
100244971Sjkim    {
101244971Sjkim        return_ACPI_STATUS (Status);
102244971Sjkim    }
103244971Sjkim
104244971Sjkim    /*
105244971Sjkim     * All address spaces (PCI Config, EC, SMBus) are scope dependent and
106244971Sjkim     * registration must occur for a specific device.
107244971Sjkim     *
108244971Sjkim     * In the case of the system memory and IO address spaces there is
109244971Sjkim     * currently no device associated with the address space. For these we
110244971Sjkim     * use the root.
111244971Sjkim     *
112244971Sjkim     * We install the default PCI config space handler at the root so that
113244971Sjkim     * this space is immediately available even though the we have not
114244971Sjkim     * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
115244971Sjkim     * specification which states that the PCI config space must be always
116244971Sjkim     * available -- even though we are nowhere near ready to find the PCI root
117244971Sjkim     * buses at this point.
118244971Sjkim     *
119244971Sjkim     * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
120244971Sjkim     * has already been installed (via AcpiInstallAddressSpaceHandler).
121244971Sjkim     * Similar for AE_SAME_HANDLER.
122244971Sjkim     */
123244971Sjkim    for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
124244971Sjkim    {
125244971Sjkim        Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
126306536Sjkim            AcpiGbl_DefaultAddressSpaces[i],
127306536Sjkim            ACPI_DEFAULT_HANDLER, NULL, NULL);
128244971Sjkim        switch (Status)
129244971Sjkim        {
130244971Sjkim        case AE_OK:
131244971Sjkim        case AE_SAME_HANDLER:
132244971Sjkim        case AE_ALREADY_EXISTS:
133244971Sjkim
134244971Sjkim            /* These exceptions are all OK */
135244971Sjkim
136244971Sjkim            Status = AE_OK;
137244971Sjkim            break;
138244971Sjkim
139244971Sjkim        default:
140244971Sjkim
141244971Sjkim            goto UnlockAndExit;
142244971Sjkim        }
143244971Sjkim    }
144244971Sjkim
145244971SjkimUnlockAndExit:
146244971Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
147244971Sjkim    return_ACPI_STATUS (Status);
148244971Sjkim}
149244971Sjkim
150244971Sjkim
151244971Sjkim/*******************************************************************************
152244971Sjkim *
153244971Sjkim * FUNCTION:    AcpiEvHasDefaultHandler
154244971Sjkim *
155244971Sjkim * PARAMETERS:  Node                - Namespace node for the device
156244971Sjkim *              SpaceId             - The address space ID
157244971Sjkim *
158244971Sjkim * RETURN:      TRUE if default handler is installed, FALSE otherwise
159244971Sjkim *
160244971Sjkim * DESCRIPTION: Check if the default handler is installed for the requested
161244971Sjkim *              space ID.
162244971Sjkim *
163244971Sjkim ******************************************************************************/
164244971Sjkim
165244971SjkimBOOLEAN
166244971SjkimAcpiEvHasDefaultHandler (
167244971Sjkim    ACPI_NAMESPACE_NODE     *Node,
168244971Sjkim    ACPI_ADR_SPACE_TYPE     SpaceId)
169244971Sjkim{
170244971Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
171244971Sjkim    ACPI_OPERAND_OBJECT     *HandlerObj;
172244971Sjkim
173244971Sjkim
174244971Sjkim    /* Must have an existing internal object */
175244971Sjkim
176244971Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
177244971Sjkim    if (ObjDesc)
178244971Sjkim    {
179306536Sjkim        HandlerObj = ObjDesc->CommonNotify.Handler;
180244971Sjkim
181244971Sjkim        /* Walk the linked list of handlers for this object */
182244971Sjkim
183244971Sjkim        while (HandlerObj)
184244971Sjkim        {
185244971Sjkim            if (HandlerObj->AddressSpace.SpaceId == SpaceId)
186244971Sjkim            {
187244971Sjkim                if (HandlerObj->AddressSpace.HandlerFlags &
188306536Sjkim                    ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
189244971Sjkim                {
190244971Sjkim                    return (TRUE);
191244971Sjkim                }
192244971Sjkim            }
193244971Sjkim
194244971Sjkim            HandlerObj = HandlerObj->AddressSpace.Next;
195244971Sjkim        }
196244971Sjkim    }
197244971Sjkim
198244971Sjkim    return (FALSE);
199244971Sjkim}
200244971Sjkim
201244971Sjkim
202244971Sjkim/*******************************************************************************
203244971Sjkim *
204244971Sjkim * FUNCTION:    AcpiEvInstallHandler
205244971Sjkim *
206244971Sjkim * PARAMETERS:  WalkNamespace callback
207244971Sjkim *
208244971Sjkim * DESCRIPTION: This routine installs an address handler into objects that are
209244971Sjkim *              of type Region or Device.
210244971Sjkim *
211244971Sjkim *              If the Object is a Device, and the device has a handler of
212244971Sjkim *              the same type then the search is terminated in that branch.
213244971Sjkim *
214244971Sjkim *              This is because the existing handler is closer in proximity
215244971Sjkim *              to any more regions than the one we are trying to install.
216244971Sjkim *
217244971Sjkim ******************************************************************************/
218244971Sjkim
219244971Sjkimstatic ACPI_STATUS
220244971SjkimAcpiEvInstallHandler (
221244971Sjkim    ACPI_HANDLE             ObjHandle,
222244971Sjkim    UINT32                  Level,
223244971Sjkim    void                    *Context,
224244971Sjkim    void                    **ReturnValue)
225244971Sjkim{
226244971Sjkim    ACPI_OPERAND_OBJECT     *HandlerObj;
227244971Sjkim    ACPI_OPERAND_OBJECT     *NextHandlerObj;
228244971Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
229244971Sjkim    ACPI_NAMESPACE_NODE     *Node;
230244971Sjkim    ACPI_STATUS             Status;
231244971Sjkim
232244971Sjkim
233244971Sjkim    ACPI_FUNCTION_NAME (EvInstallHandler);
234244971Sjkim
235244971Sjkim
236244971Sjkim    HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
237244971Sjkim
238244971Sjkim    /* Parameter validation */
239244971Sjkim
240244971Sjkim    if (!HandlerObj)
241244971Sjkim    {
242244971Sjkim        return (AE_OK);
243244971Sjkim    }
244244971Sjkim
245244971Sjkim    /* Convert and validate the device handle */
246244971Sjkim
247244971Sjkim    Node = AcpiNsValidateHandle (ObjHandle);
248244971Sjkim    if (!Node)
249244971Sjkim    {
250244971Sjkim        return (AE_BAD_PARAMETER);
251244971Sjkim    }
252244971Sjkim
253244971Sjkim    /*
254244971Sjkim     * We only care about regions and objects that are allowed to have
255244971Sjkim     * address space handlers
256244971Sjkim     */
257244971Sjkim    if ((Node->Type != ACPI_TYPE_DEVICE) &&
258244971Sjkim        (Node->Type != ACPI_TYPE_REGION) &&
259244971Sjkim        (Node != AcpiGbl_RootNode))
260244971Sjkim    {
261244971Sjkim        return (AE_OK);
262244971Sjkim    }
263244971Sjkim
264244971Sjkim    /* Check for an existing internal object */
265244971Sjkim
266244971Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
267244971Sjkim    if (!ObjDesc)
268244971Sjkim    {
269244971Sjkim        /* No object, just exit */
270244971Sjkim
271244971Sjkim        return (AE_OK);
272244971Sjkim    }
273244971Sjkim
274244971Sjkim    /* Devices are handled different than regions */
275244971Sjkim
276244971Sjkim    if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
277244971Sjkim    {
278244971Sjkim        /* Check if this Device already has a handler for this address space */
279244971Sjkim
280306536Sjkim        NextHandlerObj = AcpiEvFindRegionHandler (
281306536Sjkim            HandlerObj->AddressSpace.SpaceId, ObjDesc->CommonNotify.Handler);
282306536Sjkim        if (NextHandlerObj)
283244971Sjkim        {
284244971Sjkim            /* Found a handler, is it for the same address space? */
285244971Sjkim
286306536Sjkim            ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
287306536Sjkim                "Found handler for region [%s] in device %p(%p) handler %p\n",
288306536Sjkim                AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
289306536Sjkim                ObjDesc, NextHandlerObj, HandlerObj));
290244971Sjkim
291306536Sjkim            /*
292306536Sjkim             * Since the object we found it on was a device, then it means
293306536Sjkim             * that someone has already installed a handler for the branch
294306536Sjkim             * of the namespace from this device on. Just bail out telling
295306536Sjkim             * the walk routine to not traverse this branch. This preserves
296306536Sjkim             * the scoping rule for handlers.
297306536Sjkim             */
298306536Sjkim            return (AE_CTRL_DEPTH);
299244971Sjkim        }
300244971Sjkim
301244971Sjkim        /*
302244971Sjkim         * As long as the device didn't have a handler for this space we
303244971Sjkim         * don't care about it. We just ignore it and proceed.
304244971Sjkim         */
305244971Sjkim        return (AE_OK);
306244971Sjkim    }
307244971Sjkim
308244971Sjkim    /* Object is a Region */
309244971Sjkim
310244971Sjkim    if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
311244971Sjkim    {
312244971Sjkim        /* This region is for a different address space, just ignore it */
313244971Sjkim
314244971Sjkim        return (AE_OK);
315244971Sjkim    }
316244971Sjkim
317244971Sjkim    /*
318244971Sjkim     * Now we have a region and it is for the handler's address space type.
319244971Sjkim     *
320244971Sjkim     * First disconnect region for any previous handler (if any)
321244971Sjkim     */
322244971Sjkim    AcpiEvDetachRegion (ObjDesc, FALSE);
323244971Sjkim
324244971Sjkim    /* Connect the region to the new handler */
325244971Sjkim
326244971Sjkim    Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
327244971Sjkim    return (Status);
328244971Sjkim}
329244971Sjkim
330244971Sjkim
331244971Sjkim/*******************************************************************************
332244971Sjkim *
333306536Sjkim * FUNCTION:    AcpiEvFindRegionHandler
334306536Sjkim *
335306536Sjkim * PARAMETERS:  SpaceId         - The address space ID
336306536Sjkim *              HandlerObj      - Head of the handler object list
337306536Sjkim *
338306536Sjkim * RETURN:      Matching handler object. NULL if space ID not matched
339306536Sjkim *
340306536Sjkim * DESCRIPTION: Search a handler object list for a match on the address
341306536Sjkim *              space ID.
342306536Sjkim *
343306536Sjkim ******************************************************************************/
344306536Sjkim
345306536SjkimACPI_OPERAND_OBJECT *
346306536SjkimAcpiEvFindRegionHandler (
347306536Sjkim    ACPI_ADR_SPACE_TYPE     SpaceId,
348306536Sjkim    ACPI_OPERAND_OBJECT     *HandlerObj)
349306536Sjkim{
350306536Sjkim
351306536Sjkim    /* Walk the handler list for this device */
352306536Sjkim
353306536Sjkim    while (HandlerObj)
354306536Sjkim    {
355306536Sjkim        /* Same SpaceId indicates a handler is installed */
356306536Sjkim
357306536Sjkim        if (HandlerObj->AddressSpace.SpaceId == SpaceId)
358306536Sjkim        {
359306536Sjkim            return (HandlerObj);
360306536Sjkim        }
361306536Sjkim
362306536Sjkim        /* Next handler object */
363306536Sjkim
364306536Sjkim        HandlerObj = HandlerObj->AddressSpace.Next;
365306536Sjkim    }
366306536Sjkim
367306536Sjkim    return (NULL);
368306536Sjkim}
369306536Sjkim
370306536Sjkim
371306536Sjkim/*******************************************************************************
372306536Sjkim *
373244971Sjkim * FUNCTION:    AcpiEvInstallSpaceHandler
374244971Sjkim *
375244971Sjkim * PARAMETERS:  Node            - Namespace node for the device
376244971Sjkim *              SpaceId         - The address space ID
377244971Sjkim *              Handler         - Address of the handler
378244971Sjkim *              Setup           - Address of the setup function
379244971Sjkim *              Context         - Value passed to the handler on each access
380244971Sjkim *
381244971Sjkim * RETURN:      Status
382244971Sjkim *
383244971Sjkim * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
384244971Sjkim *              Assumes namespace is locked
385244971Sjkim *
386244971Sjkim ******************************************************************************/
387244971Sjkim
388244971SjkimACPI_STATUS
389244971SjkimAcpiEvInstallSpaceHandler (
390244971Sjkim    ACPI_NAMESPACE_NODE     *Node,
391244971Sjkim    ACPI_ADR_SPACE_TYPE     SpaceId,
392244971Sjkim    ACPI_ADR_SPACE_HANDLER  Handler,
393244971Sjkim    ACPI_ADR_SPACE_SETUP    Setup,
394244971Sjkim    void                    *Context)
395244971Sjkim{
396244971Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
397244971Sjkim    ACPI_OPERAND_OBJECT     *HandlerObj;
398306536Sjkim    ACPI_STATUS             Status = AE_OK;
399244971Sjkim    ACPI_OBJECT_TYPE        Type;
400306536Sjkim    UINT8                   Flags = 0;
401244971Sjkim
402244971Sjkim
403244971Sjkim    ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
404244971Sjkim
405244971Sjkim
406244971Sjkim    /*
407306536Sjkim     * This registration is valid for only the types below and the root.
408306536Sjkim     * The root node is where the default handlers get installed.
409244971Sjkim     */
410244971Sjkim    if ((Node->Type != ACPI_TYPE_DEVICE)     &&
411244971Sjkim        (Node->Type != ACPI_TYPE_PROCESSOR)  &&
412244971Sjkim        (Node->Type != ACPI_TYPE_THERMAL)    &&
413244971Sjkim        (Node != AcpiGbl_RootNode))
414244971Sjkim    {
415244971Sjkim        Status = AE_BAD_PARAMETER;
416244971Sjkim        goto UnlockAndExit;
417244971Sjkim    }
418244971Sjkim
419244971Sjkim    if (Handler == ACPI_DEFAULT_HANDLER)
420244971Sjkim    {
421244971Sjkim        Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
422244971Sjkim
423244971Sjkim        switch (SpaceId)
424244971Sjkim        {
425244971Sjkim        case ACPI_ADR_SPACE_SYSTEM_MEMORY:
426250838Sjkim
427244971Sjkim            Handler = AcpiExSystemMemorySpaceHandler;
428244971Sjkim            Setup   = AcpiEvSystemMemoryRegionSetup;
429244971Sjkim            break;
430244971Sjkim
431244971Sjkim        case ACPI_ADR_SPACE_SYSTEM_IO:
432250838Sjkim
433244971Sjkim            Handler = AcpiExSystemIoSpaceHandler;
434244971Sjkim            Setup   = AcpiEvIoSpaceRegionSetup;
435244971Sjkim            break;
436244971Sjkim
437244971Sjkim        case ACPI_ADR_SPACE_PCI_CONFIG:
438250838Sjkim
439244971Sjkim            Handler = AcpiExPciConfigSpaceHandler;
440244971Sjkim            Setup   = AcpiEvPciConfigRegionSetup;
441244971Sjkim            break;
442244971Sjkim
443244971Sjkim        case ACPI_ADR_SPACE_CMOS:
444250838Sjkim
445244971Sjkim            Handler = AcpiExCmosSpaceHandler;
446244971Sjkim            Setup   = AcpiEvCmosRegionSetup;
447244971Sjkim            break;
448244971Sjkim
449244971Sjkim        case ACPI_ADR_SPACE_PCI_BAR_TARGET:
450250838Sjkim
451244971Sjkim            Handler = AcpiExPciBarSpaceHandler;
452244971Sjkim            Setup   = AcpiEvPciBarRegionSetup;
453244971Sjkim            break;
454244971Sjkim
455244971Sjkim        case ACPI_ADR_SPACE_DATA_TABLE:
456250838Sjkim
457244971Sjkim            Handler = AcpiExDataTableSpaceHandler;
458244971Sjkim            Setup   = NULL;
459244971Sjkim            break;
460244971Sjkim
461244971Sjkim        default:
462250838Sjkim
463244971Sjkim            Status = AE_BAD_PARAMETER;
464244971Sjkim            goto UnlockAndExit;
465244971Sjkim        }
466244971Sjkim    }
467244971Sjkim
468244971Sjkim    /* If the caller hasn't specified a setup routine, use the default */
469244971Sjkim
470244971Sjkim    if (!Setup)
471244971Sjkim    {
472244971Sjkim        Setup = AcpiEvDefaultRegionSetup;
473244971Sjkim    }
474244971Sjkim
475244971Sjkim    /* Check for an existing internal object */
476244971Sjkim
477244971Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
478244971Sjkim    if (ObjDesc)
479244971Sjkim    {
480244971Sjkim        /*
481306536Sjkim         * The attached device object already exists. Now make sure
482306536Sjkim         * the handler is not already installed.
483244971Sjkim         */
484306536Sjkim        HandlerObj = AcpiEvFindRegionHandler (SpaceId,
485306536Sjkim            ObjDesc->CommonNotify.Handler);
486244971Sjkim
487306536Sjkim        if (HandlerObj)
488244971Sjkim        {
489306536Sjkim            if (HandlerObj->AddressSpace.Handler == Handler)
490244971Sjkim            {
491306536Sjkim                /*
492306536Sjkim                 * It is (relatively) OK to attempt to install the SAME
493306536Sjkim                 * handler twice. This can easily happen with the
494306536Sjkim                 * PCI_Config space.
495306536Sjkim                 */
496306536Sjkim                Status = AE_SAME_HANDLER;
497244971Sjkim                goto UnlockAndExit;
498244971Sjkim            }
499306536Sjkim            else
500306536Sjkim            {
501306536Sjkim                /* A handler is already installed */
502244971Sjkim
503306536Sjkim                Status = AE_ALREADY_EXISTS;
504306536Sjkim            }
505244971Sjkim
506306536Sjkim            goto UnlockAndExit;
507244971Sjkim        }
508244971Sjkim    }
509244971Sjkim    else
510244971Sjkim    {
511244971Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
512306536Sjkim            "Creating object on Device %p while installing handler\n",
513306536Sjkim            Node));
514244971Sjkim
515244971Sjkim        /* ObjDesc does not exist, create one */
516244971Sjkim
517244971Sjkim        if (Node->Type == ACPI_TYPE_ANY)
518244971Sjkim        {
519244971Sjkim            Type = ACPI_TYPE_DEVICE;
520244971Sjkim        }
521244971Sjkim        else
522244971Sjkim        {
523244971Sjkim            Type = Node->Type;
524244971Sjkim        }
525244971Sjkim
526244971Sjkim        ObjDesc = AcpiUtCreateInternalObject (Type);
527244971Sjkim        if (!ObjDesc)
528244971Sjkim        {
529244971Sjkim            Status = AE_NO_MEMORY;
530244971Sjkim            goto UnlockAndExit;
531244971Sjkim        }
532244971Sjkim
533244971Sjkim        /* Init new descriptor */
534244971Sjkim
535244971Sjkim        ObjDesc->Common.Type = (UINT8) Type;
536244971Sjkim
537244971Sjkim        /* Attach the new object to the Node */
538244971Sjkim
539244971Sjkim        Status = AcpiNsAttachObject (Node, ObjDesc, Type);
540244971Sjkim
541244971Sjkim        /* Remove local reference to the object */
542244971Sjkim
543244971Sjkim        AcpiUtRemoveReference (ObjDesc);
544244971Sjkim
545244971Sjkim        if (ACPI_FAILURE (Status))
546244971Sjkim        {
547244971Sjkim            goto UnlockAndExit;
548244971Sjkim        }
549244971Sjkim    }
550244971Sjkim
551244971Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
552306536Sjkim        "Installing address handler for region %s(%X) "
553306536Sjkim        "on Device %4.4s %p(%p)\n",
554244971Sjkim        AcpiUtGetRegionName (SpaceId), SpaceId,
555244971Sjkim        AcpiUtGetNodeName (Node), Node, ObjDesc));
556244971Sjkim
557244971Sjkim    /*
558244971Sjkim     * Install the handler
559244971Sjkim     *
560244971Sjkim     * At this point there is no existing handler. Just allocate the object
561244971Sjkim     * for the handler and link it into the list.
562244971Sjkim     */
563244971Sjkim    HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
564244971Sjkim    if (!HandlerObj)
565244971Sjkim    {
566244971Sjkim        Status = AE_NO_MEMORY;
567244971Sjkim        goto UnlockAndExit;
568244971Sjkim    }
569244971Sjkim
570244971Sjkim    /* Init handler obj */
571244971Sjkim
572244971Sjkim    HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
573244971Sjkim    HandlerObj->AddressSpace.HandlerFlags = Flags;
574244971Sjkim    HandlerObj->AddressSpace.RegionList = NULL;
575244971Sjkim    HandlerObj->AddressSpace.Node = Node;
576244971Sjkim    HandlerObj->AddressSpace.Handler = Handler;
577244971Sjkim    HandlerObj->AddressSpace.Context = Context;
578306536Sjkim    HandlerObj->AddressSpace.Setup = Setup;
579244971Sjkim
580244971Sjkim    /* Install at head of Device.AddressSpace list */
581244971Sjkim
582306536Sjkim    HandlerObj->AddressSpace.Next = ObjDesc->CommonNotify.Handler;
583244971Sjkim
584244971Sjkim    /*
585244971Sjkim     * The Device object is the first reference on the HandlerObj.
586244971Sjkim     * Each region that uses the handler adds a reference.
587244971Sjkim     */
588306536Sjkim    ObjDesc->CommonNotify.Handler = HandlerObj;
589244971Sjkim
590244971Sjkim    /*
591306536Sjkim     * Walk the namespace finding all of the regions this handler will
592306536Sjkim     * manage.
593244971Sjkim     *
594306536Sjkim     * Start at the device and search the branch toward the leaf nodes
595306536Sjkim     * until either the leaf is encountered or a device is detected that
596306536Sjkim     * has an address handler of the same type.
597244971Sjkim     *
598306536Sjkim     * In either case, back up and search down the remainder of the branch
599244971Sjkim     */
600306536Sjkim    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node,
601306536Sjkim        ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
602306536Sjkim        AcpiEvInstallHandler, NULL, HandlerObj, NULL);
603244971Sjkim
604244971SjkimUnlockAndExit:
605244971Sjkim    return_ACPI_STATUS (Status);
606244971Sjkim}
607