evhandler.c revision 244971
1244971Sjkim/******************************************************************************
2244971Sjkim *
3244971Sjkim * Module Name: evhandler - Support for Address Space handlers
4244971Sjkim *
5244971Sjkim *****************************************************************************/
6244971Sjkim
7244971Sjkim/*
8244971Sjkim * Copyright (C) 2000 - 2012, 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
44244971Sjkim
45244971Sjkim#define __EVHANDLER_C__
46244971Sjkim
47244971Sjkim#include "acpi.h"
48244971Sjkim#include "accommon.h"
49244971Sjkim#include "acevents.h"
50244971Sjkim#include "acnamesp.h"
51244971Sjkim#include "acinterp.h"
52244971Sjkim
53244971Sjkim#define _COMPONENT          ACPI_EVENTS
54244971Sjkim        ACPI_MODULE_NAME    ("evhandler")
55244971Sjkim
56244971Sjkim
57244971Sjkim/* Local prototypes */
58244971Sjkim
59244971Sjkimstatic ACPI_STATUS
60244971SjkimAcpiEvInstallHandler (
61244971Sjkim    ACPI_HANDLE             ObjHandle,
62244971Sjkim    UINT32                  Level,
63244971Sjkim    void                    *Context,
64244971Sjkim    void                    **ReturnValue);
65244971Sjkim
66244971Sjkim/* These are the address spaces that will get default handlers */
67244971Sjkim
68244971SjkimUINT8        AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
69244971Sjkim{
70244971Sjkim    ACPI_ADR_SPACE_SYSTEM_MEMORY,
71244971Sjkim    ACPI_ADR_SPACE_SYSTEM_IO,
72244971Sjkim    ACPI_ADR_SPACE_PCI_CONFIG,
73244971Sjkim    ACPI_ADR_SPACE_DATA_TABLE
74244971Sjkim};
75244971Sjkim
76244971Sjkim
77244971Sjkim/*******************************************************************************
78244971Sjkim *
79244971Sjkim * FUNCTION:    AcpiEvInstallRegionHandlers
80244971Sjkim *
81244971Sjkim * PARAMETERS:  None
82244971Sjkim *
83244971Sjkim * RETURN:      Status
84244971Sjkim *
85244971Sjkim * DESCRIPTION: Installs the core subsystem default address space handlers.
86244971Sjkim *
87244971Sjkim ******************************************************************************/
88244971Sjkim
89244971SjkimACPI_STATUS
90244971SjkimAcpiEvInstallRegionHandlers (
91244971Sjkim    void)
92244971Sjkim{
93244971Sjkim    ACPI_STATUS             Status;
94244971Sjkim    UINT32                  i;
95244971Sjkim
96244971Sjkim
97244971Sjkim    ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
98244971Sjkim
99244971Sjkim
100244971Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
101244971Sjkim    if (ACPI_FAILURE (Status))
102244971Sjkim    {
103244971Sjkim        return_ACPI_STATUS (Status);
104244971Sjkim    }
105244971Sjkim
106244971Sjkim    /*
107244971Sjkim     * All address spaces (PCI Config, EC, SMBus) are scope dependent and
108244971Sjkim     * registration must occur for a specific device.
109244971Sjkim     *
110244971Sjkim     * In the case of the system memory and IO address spaces there is
111244971Sjkim     * currently no device associated with the address space. For these we
112244971Sjkim     * use the root.
113244971Sjkim     *
114244971Sjkim     * We install the default PCI config space handler at the root so that
115244971Sjkim     * this space is immediately available even though the we have not
116244971Sjkim     * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
117244971Sjkim     * specification which states that the PCI config space must be always
118244971Sjkim     * available -- even though we are nowhere near ready to find the PCI root
119244971Sjkim     * buses at this point.
120244971Sjkim     *
121244971Sjkim     * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
122244971Sjkim     * has already been installed (via AcpiInstallAddressSpaceHandler).
123244971Sjkim     * Similar for AE_SAME_HANDLER.
124244971Sjkim     */
125244971Sjkim    for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
126244971Sjkim    {
127244971Sjkim        Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
128244971Sjkim                    AcpiGbl_DefaultAddressSpaces[i],
129244971Sjkim                    ACPI_DEFAULT_HANDLER, NULL, NULL);
130244971Sjkim        switch (Status)
131244971Sjkim        {
132244971Sjkim        case AE_OK:
133244971Sjkim        case AE_SAME_HANDLER:
134244971Sjkim        case AE_ALREADY_EXISTS:
135244971Sjkim
136244971Sjkim            /* These exceptions are all OK */
137244971Sjkim
138244971Sjkim            Status = AE_OK;
139244971Sjkim            break;
140244971Sjkim
141244971Sjkim        default:
142244971Sjkim
143244971Sjkim            goto UnlockAndExit;
144244971Sjkim        }
145244971Sjkim    }
146244971Sjkim
147244971SjkimUnlockAndExit:
148244971Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
149244971Sjkim    return_ACPI_STATUS (Status);
150244971Sjkim}
151244971Sjkim
152244971Sjkim
153244971Sjkim/*******************************************************************************
154244971Sjkim *
155244971Sjkim * FUNCTION:    AcpiEvHasDefaultHandler
156244971Sjkim *
157244971Sjkim * PARAMETERS:  Node                - Namespace node for the device
158244971Sjkim *              SpaceId             - The address space ID
159244971Sjkim *
160244971Sjkim * RETURN:      TRUE if default handler is installed, FALSE otherwise
161244971Sjkim *
162244971Sjkim * DESCRIPTION: Check if the default handler is installed for the requested
163244971Sjkim *              space ID.
164244971Sjkim *
165244971Sjkim ******************************************************************************/
166244971Sjkim
167244971SjkimBOOLEAN
168244971SjkimAcpiEvHasDefaultHandler (
169244971Sjkim    ACPI_NAMESPACE_NODE     *Node,
170244971Sjkim    ACPI_ADR_SPACE_TYPE     SpaceId)
171244971Sjkim{
172244971Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
173244971Sjkim    ACPI_OPERAND_OBJECT     *HandlerObj;
174244971Sjkim
175244971Sjkim
176244971Sjkim    /* Must have an existing internal object */
177244971Sjkim
178244971Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
179244971Sjkim    if (ObjDesc)
180244971Sjkim    {
181244971Sjkim        HandlerObj = ObjDesc->Device.Handler;
182244971Sjkim
183244971Sjkim        /* Walk the linked list of handlers for this object */
184244971Sjkim
185244971Sjkim        while (HandlerObj)
186244971Sjkim        {
187244971Sjkim            if (HandlerObj->AddressSpace.SpaceId == SpaceId)
188244971Sjkim            {
189244971Sjkim                if (HandlerObj->AddressSpace.HandlerFlags &
190244971Sjkim                        ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
191244971Sjkim                {
192244971Sjkim                    return (TRUE);
193244971Sjkim                }
194244971Sjkim            }
195244971Sjkim
196244971Sjkim            HandlerObj = HandlerObj->AddressSpace.Next;
197244971Sjkim        }
198244971Sjkim    }
199244971Sjkim
200244971Sjkim    return (FALSE);
201244971Sjkim}
202244971Sjkim
203244971Sjkim
204244971Sjkim/*******************************************************************************
205244971Sjkim *
206244971Sjkim * FUNCTION:    AcpiEvInstallHandler
207244971Sjkim *
208244971Sjkim * PARAMETERS:  WalkNamespace callback
209244971Sjkim *
210244971Sjkim * DESCRIPTION: This routine installs an address handler into objects that are
211244971Sjkim *              of type Region or Device.
212244971Sjkim *
213244971Sjkim *              If the Object is a Device, and the device has a handler of
214244971Sjkim *              the same type then the search is terminated in that branch.
215244971Sjkim *
216244971Sjkim *              This is because the existing handler is closer in proximity
217244971Sjkim *              to any more regions than the one we are trying to install.
218244971Sjkim *
219244971Sjkim ******************************************************************************/
220244971Sjkim
221244971Sjkimstatic ACPI_STATUS
222244971SjkimAcpiEvInstallHandler (
223244971Sjkim    ACPI_HANDLE             ObjHandle,
224244971Sjkim    UINT32                  Level,
225244971Sjkim    void                    *Context,
226244971Sjkim    void                    **ReturnValue)
227244971Sjkim{
228244971Sjkim    ACPI_OPERAND_OBJECT     *HandlerObj;
229244971Sjkim    ACPI_OPERAND_OBJECT     *NextHandlerObj;
230244971Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
231244971Sjkim    ACPI_NAMESPACE_NODE     *Node;
232244971Sjkim    ACPI_STATUS             Status;
233244971Sjkim
234244971Sjkim
235244971Sjkim    ACPI_FUNCTION_NAME (EvInstallHandler);
236244971Sjkim
237244971Sjkim
238244971Sjkim    HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
239244971Sjkim
240244971Sjkim    /* Parameter validation */
241244971Sjkim
242244971Sjkim    if (!HandlerObj)
243244971Sjkim    {
244244971Sjkim        return (AE_OK);
245244971Sjkim    }
246244971Sjkim
247244971Sjkim    /* Convert and validate the device handle */
248244971Sjkim
249244971Sjkim    Node = AcpiNsValidateHandle (ObjHandle);
250244971Sjkim    if (!Node)
251244971Sjkim    {
252244971Sjkim        return (AE_BAD_PARAMETER);
253244971Sjkim    }
254244971Sjkim
255244971Sjkim    /*
256244971Sjkim     * We only care about regions and objects that are allowed to have
257244971Sjkim     * address space handlers
258244971Sjkim     */
259244971Sjkim    if ((Node->Type != ACPI_TYPE_DEVICE) &&
260244971Sjkim        (Node->Type != ACPI_TYPE_REGION) &&
261244971Sjkim        (Node != AcpiGbl_RootNode))
262244971Sjkim    {
263244971Sjkim        return (AE_OK);
264244971Sjkim    }
265244971Sjkim
266244971Sjkim    /* Check for an existing internal object */
267244971Sjkim
268244971Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
269244971Sjkim    if (!ObjDesc)
270244971Sjkim    {
271244971Sjkim        /* No object, just exit */
272244971Sjkim
273244971Sjkim        return (AE_OK);
274244971Sjkim    }
275244971Sjkim
276244971Sjkim    /* Devices are handled different than regions */
277244971Sjkim
278244971Sjkim    if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
279244971Sjkim    {
280244971Sjkim        /* Check if this Device already has a handler for this address space */
281244971Sjkim
282244971Sjkim        NextHandlerObj = ObjDesc->Device.Handler;
283244971Sjkim        while (NextHandlerObj)
284244971Sjkim        {
285244971Sjkim            /* Found a handler, is it for the same address space? */
286244971Sjkim
287244971Sjkim            if (NextHandlerObj->AddressSpace.SpaceId ==
288244971Sjkim                    HandlerObj->AddressSpace.SpaceId)
289244971Sjkim            {
290244971Sjkim                ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
291244971Sjkim                    "Found handler for region [%s] in device %p(%p) "
292244971Sjkim                    "handler %p\n",
293244971Sjkim                    AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
294244971Sjkim                    ObjDesc, NextHandlerObj, HandlerObj));
295244971Sjkim
296244971Sjkim                /*
297244971Sjkim                 * Since the object we found it on was a device, then it
298244971Sjkim                 * means that someone has already installed a handler for
299244971Sjkim                 * the branch of the namespace from this device on. Just
300244971Sjkim                 * bail out telling the walk routine to not traverse this
301244971Sjkim                 * branch. This preserves the scoping rule for handlers.
302244971Sjkim                 */
303244971Sjkim                return (AE_CTRL_DEPTH);
304244971Sjkim            }
305244971Sjkim
306244971Sjkim            /* Walk the linked list of handlers attached to this device */
307244971Sjkim
308244971Sjkim            NextHandlerObj = NextHandlerObj->AddressSpace.Next;
309244971Sjkim        }
310244971Sjkim
311244971Sjkim        /*
312244971Sjkim         * As long as the device didn't have a handler for this space we
313244971Sjkim         * don't care about it. We just ignore it and proceed.
314244971Sjkim         */
315244971Sjkim        return (AE_OK);
316244971Sjkim    }
317244971Sjkim
318244971Sjkim    /* Object is a Region */
319244971Sjkim
320244971Sjkim    if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
321244971Sjkim    {
322244971Sjkim        /* This region is for a different address space, just ignore it */
323244971Sjkim
324244971Sjkim        return (AE_OK);
325244971Sjkim    }
326244971Sjkim
327244971Sjkim    /*
328244971Sjkim     * Now we have a region and it is for the handler's address space type.
329244971Sjkim     *
330244971Sjkim     * First disconnect region for any previous handler (if any)
331244971Sjkim     */
332244971Sjkim    AcpiEvDetachRegion (ObjDesc, FALSE);
333244971Sjkim
334244971Sjkim    /* Connect the region to the new handler */
335244971Sjkim
336244971Sjkim    Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
337244971Sjkim    return (Status);
338244971Sjkim}
339244971Sjkim
340244971Sjkim
341244971Sjkim/*******************************************************************************
342244971Sjkim *
343244971Sjkim * FUNCTION:    AcpiEvInstallSpaceHandler
344244971Sjkim *
345244971Sjkim * PARAMETERS:  Node            - Namespace node for the device
346244971Sjkim *              SpaceId         - The address space ID
347244971Sjkim *              Handler         - Address of the handler
348244971Sjkim *              Setup           - Address of the setup function
349244971Sjkim *              Context         - Value passed to the handler on each access
350244971Sjkim *
351244971Sjkim * RETURN:      Status
352244971Sjkim *
353244971Sjkim * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
354244971Sjkim *              Assumes namespace is locked
355244971Sjkim *
356244971Sjkim ******************************************************************************/
357244971Sjkim
358244971SjkimACPI_STATUS
359244971SjkimAcpiEvInstallSpaceHandler (
360244971Sjkim    ACPI_NAMESPACE_NODE     *Node,
361244971Sjkim    ACPI_ADR_SPACE_TYPE     SpaceId,
362244971Sjkim    ACPI_ADR_SPACE_HANDLER  Handler,
363244971Sjkim    ACPI_ADR_SPACE_SETUP    Setup,
364244971Sjkim    void                    *Context)
365244971Sjkim{
366244971Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
367244971Sjkim    ACPI_OPERAND_OBJECT     *HandlerObj;
368244971Sjkim    ACPI_STATUS             Status;
369244971Sjkim    ACPI_OBJECT_TYPE        Type;
370244971Sjkim    UINT8                  Flags = 0;
371244971Sjkim
372244971Sjkim
373244971Sjkim    ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
374244971Sjkim
375244971Sjkim
376244971Sjkim    /*
377244971Sjkim     * This registration is valid for only the types below and the root. This
378244971Sjkim     * is where the default handlers get placed.
379244971Sjkim     */
380244971Sjkim    if ((Node->Type != ACPI_TYPE_DEVICE)     &&
381244971Sjkim        (Node->Type != ACPI_TYPE_PROCESSOR)  &&
382244971Sjkim        (Node->Type != ACPI_TYPE_THERMAL)    &&
383244971Sjkim        (Node != AcpiGbl_RootNode))
384244971Sjkim    {
385244971Sjkim        Status = AE_BAD_PARAMETER;
386244971Sjkim        goto UnlockAndExit;
387244971Sjkim    }
388244971Sjkim
389244971Sjkim    if (Handler == ACPI_DEFAULT_HANDLER)
390244971Sjkim    {
391244971Sjkim        Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
392244971Sjkim
393244971Sjkim        switch (SpaceId)
394244971Sjkim        {
395244971Sjkim        case ACPI_ADR_SPACE_SYSTEM_MEMORY:
396244971Sjkim            Handler = AcpiExSystemMemorySpaceHandler;
397244971Sjkim            Setup   = AcpiEvSystemMemoryRegionSetup;
398244971Sjkim            break;
399244971Sjkim
400244971Sjkim        case ACPI_ADR_SPACE_SYSTEM_IO:
401244971Sjkim            Handler = AcpiExSystemIoSpaceHandler;
402244971Sjkim            Setup   = AcpiEvIoSpaceRegionSetup;
403244971Sjkim            break;
404244971Sjkim
405244971Sjkim        case ACPI_ADR_SPACE_PCI_CONFIG:
406244971Sjkim            Handler = AcpiExPciConfigSpaceHandler;
407244971Sjkim            Setup   = AcpiEvPciConfigRegionSetup;
408244971Sjkim            break;
409244971Sjkim
410244971Sjkim        case ACPI_ADR_SPACE_CMOS:
411244971Sjkim            Handler = AcpiExCmosSpaceHandler;
412244971Sjkim            Setup   = AcpiEvCmosRegionSetup;
413244971Sjkim            break;
414244971Sjkim
415244971Sjkim        case ACPI_ADR_SPACE_PCI_BAR_TARGET:
416244971Sjkim            Handler = AcpiExPciBarSpaceHandler;
417244971Sjkim            Setup   = AcpiEvPciBarRegionSetup;
418244971Sjkim            break;
419244971Sjkim
420244971Sjkim        case ACPI_ADR_SPACE_DATA_TABLE:
421244971Sjkim            Handler = AcpiExDataTableSpaceHandler;
422244971Sjkim            Setup   = NULL;
423244971Sjkim            break;
424244971Sjkim
425244971Sjkim        default:
426244971Sjkim            Status = AE_BAD_PARAMETER;
427244971Sjkim            goto UnlockAndExit;
428244971Sjkim        }
429244971Sjkim    }
430244971Sjkim
431244971Sjkim    /* If the caller hasn't specified a setup routine, use the default */
432244971Sjkim
433244971Sjkim    if (!Setup)
434244971Sjkim    {
435244971Sjkim        Setup = AcpiEvDefaultRegionSetup;
436244971Sjkim    }
437244971Sjkim
438244971Sjkim    /* Check for an existing internal object */
439244971Sjkim
440244971Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
441244971Sjkim    if (ObjDesc)
442244971Sjkim    {
443244971Sjkim        /*
444244971Sjkim         * The attached device object already exists. Make sure the handler
445244971Sjkim         * is not already installed.
446244971Sjkim         */
447244971Sjkim        HandlerObj = ObjDesc->Device.Handler;
448244971Sjkim
449244971Sjkim        /* Walk the handler list for this device */
450244971Sjkim
451244971Sjkim        while (HandlerObj)
452244971Sjkim        {
453244971Sjkim            /* Same SpaceId indicates a handler already installed */
454244971Sjkim
455244971Sjkim            if (HandlerObj->AddressSpace.SpaceId == SpaceId)
456244971Sjkim            {
457244971Sjkim                if (HandlerObj->AddressSpace.Handler == Handler)
458244971Sjkim                {
459244971Sjkim                    /*
460244971Sjkim                     * It is (relatively) OK to attempt to install the SAME
461244971Sjkim                     * handler twice. This can easily happen with the
462244971Sjkim                     * PCI_Config space.
463244971Sjkim                     */
464244971Sjkim                    Status = AE_SAME_HANDLER;
465244971Sjkim                    goto UnlockAndExit;
466244971Sjkim                }
467244971Sjkim                else
468244971Sjkim                {
469244971Sjkim                    /* A handler is already installed */
470244971Sjkim
471244971Sjkim                    Status = AE_ALREADY_EXISTS;
472244971Sjkim                }
473244971Sjkim                goto UnlockAndExit;
474244971Sjkim            }
475244971Sjkim
476244971Sjkim            /* Walk the linked list of handlers */
477244971Sjkim
478244971Sjkim            HandlerObj = HandlerObj->AddressSpace.Next;
479244971Sjkim        }
480244971Sjkim    }
481244971Sjkim    else
482244971Sjkim    {
483244971Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
484244971Sjkim            "Creating object on Device %p while installing handler\n", Node));
485244971Sjkim
486244971Sjkim        /* ObjDesc does not exist, create one */
487244971Sjkim
488244971Sjkim        if (Node->Type == ACPI_TYPE_ANY)
489244971Sjkim        {
490244971Sjkim            Type = ACPI_TYPE_DEVICE;
491244971Sjkim        }
492244971Sjkim        else
493244971Sjkim        {
494244971Sjkim            Type = Node->Type;
495244971Sjkim        }
496244971Sjkim
497244971Sjkim        ObjDesc = AcpiUtCreateInternalObject (Type);
498244971Sjkim        if (!ObjDesc)
499244971Sjkim        {
500244971Sjkim            Status = AE_NO_MEMORY;
501244971Sjkim            goto UnlockAndExit;
502244971Sjkim        }
503244971Sjkim
504244971Sjkim        /* Init new descriptor */
505244971Sjkim
506244971Sjkim        ObjDesc->Common.Type = (UINT8) Type;
507244971Sjkim
508244971Sjkim        /* Attach the new object to the Node */
509244971Sjkim
510244971Sjkim        Status = AcpiNsAttachObject (Node, ObjDesc, Type);
511244971Sjkim
512244971Sjkim        /* Remove local reference to the object */
513244971Sjkim
514244971Sjkim        AcpiUtRemoveReference (ObjDesc);
515244971Sjkim
516244971Sjkim        if (ACPI_FAILURE (Status))
517244971Sjkim        {
518244971Sjkim            goto UnlockAndExit;
519244971Sjkim        }
520244971Sjkim    }
521244971Sjkim
522244971Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
523244971Sjkim        "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
524244971Sjkim        AcpiUtGetRegionName (SpaceId), SpaceId,
525244971Sjkim        AcpiUtGetNodeName (Node), Node, ObjDesc));
526244971Sjkim
527244971Sjkim    /*
528244971Sjkim     * Install the handler
529244971Sjkim     *
530244971Sjkim     * At this point there is no existing handler. Just allocate the object
531244971Sjkim     * for the handler and link it into the list.
532244971Sjkim     */
533244971Sjkim    HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
534244971Sjkim    if (!HandlerObj)
535244971Sjkim    {
536244971Sjkim        Status = AE_NO_MEMORY;
537244971Sjkim        goto UnlockAndExit;
538244971Sjkim    }
539244971Sjkim
540244971Sjkim    /* Init handler obj */
541244971Sjkim
542244971Sjkim    HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
543244971Sjkim    HandlerObj->AddressSpace.HandlerFlags = Flags;
544244971Sjkim    HandlerObj->AddressSpace.RegionList = NULL;
545244971Sjkim    HandlerObj->AddressSpace.Node = Node;
546244971Sjkim    HandlerObj->AddressSpace.Handler = Handler;
547244971Sjkim    HandlerObj->AddressSpace.Context = Context;
548244971Sjkim    HandlerObj->AddressSpace.Setup  = Setup;
549244971Sjkim
550244971Sjkim    /* Install at head of Device.AddressSpace list */
551244971Sjkim
552244971Sjkim    HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
553244971Sjkim
554244971Sjkim    /*
555244971Sjkim     * The Device object is the first reference on the HandlerObj.
556244971Sjkim     * Each region that uses the handler adds a reference.
557244971Sjkim     */
558244971Sjkim    ObjDesc->Device.Handler = HandlerObj;
559244971Sjkim
560244971Sjkim    /*
561244971Sjkim     * Walk the namespace finding all of the regions this
562244971Sjkim     * handler will manage.
563244971Sjkim     *
564244971Sjkim     * Start at the device and search the branch toward
565244971Sjkim     * the leaf nodes until either the leaf is encountered or
566244971Sjkim     * a device is detected that has an address handler of the
567244971Sjkim     * same type.
568244971Sjkim     *
569244971Sjkim     * In either case, back up and search down the remainder
570244971Sjkim     * of the branch
571244971Sjkim     */
572244971Sjkim    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
573244971Sjkim                ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL,
574244971Sjkim                HandlerObj, NULL);
575244971Sjkim
576244971SjkimUnlockAndExit:
577244971Sjkim    return_ACPI_STATUS (Status);
578244971Sjkim}
579