evhandler.c revision 244971
1/******************************************************************************
2 *
3 * Module Name: evhandler - Support for Address Space handlers
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2012, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#define __EVHANDLER_C__
46
47#include "acpi.h"
48#include "accommon.h"
49#include "acevents.h"
50#include "acnamesp.h"
51#include "acinterp.h"
52
53#define _COMPONENT          ACPI_EVENTS
54        ACPI_MODULE_NAME    ("evhandler")
55
56
57/* Local prototypes */
58
59static ACPI_STATUS
60AcpiEvInstallHandler (
61    ACPI_HANDLE             ObjHandle,
62    UINT32                  Level,
63    void                    *Context,
64    void                    **ReturnValue);
65
66/* These are the address spaces that will get default handlers */
67
68UINT8        AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
69{
70    ACPI_ADR_SPACE_SYSTEM_MEMORY,
71    ACPI_ADR_SPACE_SYSTEM_IO,
72    ACPI_ADR_SPACE_PCI_CONFIG,
73    ACPI_ADR_SPACE_DATA_TABLE
74};
75
76
77/*******************************************************************************
78 *
79 * FUNCTION:    AcpiEvInstallRegionHandlers
80 *
81 * PARAMETERS:  None
82 *
83 * RETURN:      Status
84 *
85 * DESCRIPTION: Installs the core subsystem default address space handlers.
86 *
87 ******************************************************************************/
88
89ACPI_STATUS
90AcpiEvInstallRegionHandlers (
91    void)
92{
93    ACPI_STATUS             Status;
94    UINT32                  i;
95
96
97    ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
98
99
100    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
101    if (ACPI_FAILURE (Status))
102    {
103        return_ACPI_STATUS (Status);
104    }
105
106    /*
107     * All address spaces (PCI Config, EC, SMBus) are scope dependent and
108     * registration must occur for a specific device.
109     *
110     * In the case of the system memory and IO address spaces there is
111     * currently no device associated with the address space. For these we
112     * use the root.
113     *
114     * We install the default PCI config space handler at the root so that
115     * this space is immediately available even though the we have not
116     * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
117     * specification which states that the PCI config space must be always
118     * available -- even though we are nowhere near ready to find the PCI root
119     * buses at this point.
120     *
121     * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
122     * has already been installed (via AcpiInstallAddressSpaceHandler).
123     * Similar for AE_SAME_HANDLER.
124     */
125    for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
126    {
127        Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
128                    AcpiGbl_DefaultAddressSpaces[i],
129                    ACPI_DEFAULT_HANDLER, NULL, NULL);
130        switch (Status)
131        {
132        case AE_OK:
133        case AE_SAME_HANDLER:
134        case AE_ALREADY_EXISTS:
135
136            /* These exceptions are all OK */
137
138            Status = AE_OK;
139            break;
140
141        default:
142
143            goto UnlockAndExit;
144        }
145    }
146
147UnlockAndExit:
148    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
149    return_ACPI_STATUS (Status);
150}
151
152
153/*******************************************************************************
154 *
155 * FUNCTION:    AcpiEvHasDefaultHandler
156 *
157 * PARAMETERS:  Node                - Namespace node for the device
158 *              SpaceId             - The address space ID
159 *
160 * RETURN:      TRUE if default handler is installed, FALSE otherwise
161 *
162 * DESCRIPTION: Check if the default handler is installed for the requested
163 *              space ID.
164 *
165 ******************************************************************************/
166
167BOOLEAN
168AcpiEvHasDefaultHandler (
169    ACPI_NAMESPACE_NODE     *Node,
170    ACPI_ADR_SPACE_TYPE     SpaceId)
171{
172    ACPI_OPERAND_OBJECT     *ObjDesc;
173    ACPI_OPERAND_OBJECT     *HandlerObj;
174
175
176    /* Must have an existing internal object */
177
178    ObjDesc = AcpiNsGetAttachedObject (Node);
179    if (ObjDesc)
180    {
181        HandlerObj = ObjDesc->Device.Handler;
182
183        /* Walk the linked list of handlers for this object */
184
185        while (HandlerObj)
186        {
187            if (HandlerObj->AddressSpace.SpaceId == SpaceId)
188            {
189                if (HandlerObj->AddressSpace.HandlerFlags &
190                        ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
191                {
192                    return (TRUE);
193                }
194            }
195
196            HandlerObj = HandlerObj->AddressSpace.Next;
197        }
198    }
199
200    return (FALSE);
201}
202
203
204/*******************************************************************************
205 *
206 * FUNCTION:    AcpiEvInstallHandler
207 *
208 * PARAMETERS:  WalkNamespace callback
209 *
210 * DESCRIPTION: This routine installs an address handler into objects that are
211 *              of type Region or Device.
212 *
213 *              If the Object is a Device, and the device has a handler of
214 *              the same type then the search is terminated in that branch.
215 *
216 *              This is because the existing handler is closer in proximity
217 *              to any more regions than the one we are trying to install.
218 *
219 ******************************************************************************/
220
221static ACPI_STATUS
222AcpiEvInstallHandler (
223    ACPI_HANDLE             ObjHandle,
224    UINT32                  Level,
225    void                    *Context,
226    void                    **ReturnValue)
227{
228    ACPI_OPERAND_OBJECT     *HandlerObj;
229    ACPI_OPERAND_OBJECT     *NextHandlerObj;
230    ACPI_OPERAND_OBJECT     *ObjDesc;
231    ACPI_NAMESPACE_NODE     *Node;
232    ACPI_STATUS             Status;
233
234
235    ACPI_FUNCTION_NAME (EvInstallHandler);
236
237
238    HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
239
240    /* Parameter validation */
241
242    if (!HandlerObj)
243    {
244        return (AE_OK);
245    }
246
247    /* Convert and validate the device handle */
248
249    Node = AcpiNsValidateHandle (ObjHandle);
250    if (!Node)
251    {
252        return (AE_BAD_PARAMETER);
253    }
254
255    /*
256     * We only care about regions and objects that are allowed to have
257     * address space handlers
258     */
259    if ((Node->Type != ACPI_TYPE_DEVICE) &&
260        (Node->Type != ACPI_TYPE_REGION) &&
261        (Node != AcpiGbl_RootNode))
262    {
263        return (AE_OK);
264    }
265
266    /* Check for an existing internal object */
267
268    ObjDesc = AcpiNsGetAttachedObject (Node);
269    if (!ObjDesc)
270    {
271        /* No object, just exit */
272
273        return (AE_OK);
274    }
275
276    /* Devices are handled different than regions */
277
278    if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
279    {
280        /* Check if this Device already has a handler for this address space */
281
282        NextHandlerObj = ObjDesc->Device.Handler;
283        while (NextHandlerObj)
284        {
285            /* Found a handler, is it for the same address space? */
286
287            if (NextHandlerObj->AddressSpace.SpaceId ==
288                    HandlerObj->AddressSpace.SpaceId)
289            {
290                ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
291                    "Found handler for region [%s] in device %p(%p) "
292                    "handler %p\n",
293                    AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
294                    ObjDesc, NextHandlerObj, HandlerObj));
295
296                /*
297                 * Since the object we found it on was a device, then it
298                 * means that someone has already installed a handler for
299                 * the branch of the namespace from this device on. Just
300                 * bail out telling the walk routine to not traverse this
301                 * branch. This preserves the scoping rule for handlers.
302                 */
303                return (AE_CTRL_DEPTH);
304            }
305
306            /* Walk the linked list of handlers attached to this device */
307
308            NextHandlerObj = NextHandlerObj->AddressSpace.Next;
309        }
310
311        /*
312         * As long as the device didn't have a handler for this space we
313         * don't care about it. We just ignore it and proceed.
314         */
315        return (AE_OK);
316    }
317
318    /* Object is a Region */
319
320    if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
321    {
322        /* This region is for a different address space, just ignore it */
323
324        return (AE_OK);
325    }
326
327    /*
328     * Now we have a region and it is for the handler's address space type.
329     *
330     * First disconnect region for any previous handler (if any)
331     */
332    AcpiEvDetachRegion (ObjDesc, FALSE);
333
334    /* Connect the region to the new handler */
335
336    Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
337    return (Status);
338}
339
340
341/*******************************************************************************
342 *
343 * FUNCTION:    AcpiEvInstallSpaceHandler
344 *
345 * PARAMETERS:  Node            - Namespace node for the device
346 *              SpaceId         - The address space ID
347 *              Handler         - Address of the handler
348 *              Setup           - Address of the setup function
349 *              Context         - Value passed to the handler on each access
350 *
351 * RETURN:      Status
352 *
353 * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
354 *              Assumes namespace is locked
355 *
356 ******************************************************************************/
357
358ACPI_STATUS
359AcpiEvInstallSpaceHandler (
360    ACPI_NAMESPACE_NODE     *Node,
361    ACPI_ADR_SPACE_TYPE     SpaceId,
362    ACPI_ADR_SPACE_HANDLER  Handler,
363    ACPI_ADR_SPACE_SETUP    Setup,
364    void                    *Context)
365{
366    ACPI_OPERAND_OBJECT     *ObjDesc;
367    ACPI_OPERAND_OBJECT     *HandlerObj;
368    ACPI_STATUS             Status;
369    ACPI_OBJECT_TYPE        Type;
370    UINT8                  Flags = 0;
371
372
373    ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
374
375
376    /*
377     * This registration is valid for only the types below and the root. This
378     * is where the default handlers get placed.
379     */
380    if ((Node->Type != ACPI_TYPE_DEVICE)     &&
381        (Node->Type != ACPI_TYPE_PROCESSOR)  &&
382        (Node->Type != ACPI_TYPE_THERMAL)    &&
383        (Node != AcpiGbl_RootNode))
384    {
385        Status = AE_BAD_PARAMETER;
386        goto UnlockAndExit;
387    }
388
389    if (Handler == ACPI_DEFAULT_HANDLER)
390    {
391        Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
392
393        switch (SpaceId)
394        {
395        case ACPI_ADR_SPACE_SYSTEM_MEMORY:
396            Handler = AcpiExSystemMemorySpaceHandler;
397            Setup   = AcpiEvSystemMemoryRegionSetup;
398            break;
399
400        case ACPI_ADR_SPACE_SYSTEM_IO:
401            Handler = AcpiExSystemIoSpaceHandler;
402            Setup   = AcpiEvIoSpaceRegionSetup;
403            break;
404
405        case ACPI_ADR_SPACE_PCI_CONFIG:
406            Handler = AcpiExPciConfigSpaceHandler;
407            Setup   = AcpiEvPciConfigRegionSetup;
408            break;
409
410        case ACPI_ADR_SPACE_CMOS:
411            Handler = AcpiExCmosSpaceHandler;
412            Setup   = AcpiEvCmosRegionSetup;
413            break;
414
415        case ACPI_ADR_SPACE_PCI_BAR_TARGET:
416            Handler = AcpiExPciBarSpaceHandler;
417            Setup   = AcpiEvPciBarRegionSetup;
418            break;
419
420        case ACPI_ADR_SPACE_DATA_TABLE:
421            Handler = AcpiExDataTableSpaceHandler;
422            Setup   = NULL;
423            break;
424
425        default:
426            Status = AE_BAD_PARAMETER;
427            goto UnlockAndExit;
428        }
429    }
430
431    /* If the caller hasn't specified a setup routine, use the default */
432
433    if (!Setup)
434    {
435        Setup = AcpiEvDefaultRegionSetup;
436    }
437
438    /* Check for an existing internal object */
439
440    ObjDesc = AcpiNsGetAttachedObject (Node);
441    if (ObjDesc)
442    {
443        /*
444         * The attached device object already exists. Make sure the handler
445         * is not already installed.
446         */
447        HandlerObj = ObjDesc->Device.Handler;
448
449        /* Walk the handler list for this device */
450
451        while (HandlerObj)
452        {
453            /* Same SpaceId indicates a handler already installed */
454
455            if (HandlerObj->AddressSpace.SpaceId == SpaceId)
456            {
457                if (HandlerObj->AddressSpace.Handler == Handler)
458                {
459                    /*
460                     * It is (relatively) OK to attempt to install the SAME
461                     * handler twice. This can easily happen with the
462                     * PCI_Config space.
463                     */
464                    Status = AE_SAME_HANDLER;
465                    goto UnlockAndExit;
466                }
467                else
468                {
469                    /* A handler is already installed */
470
471                    Status = AE_ALREADY_EXISTS;
472                }
473                goto UnlockAndExit;
474            }
475
476            /* Walk the linked list of handlers */
477
478            HandlerObj = HandlerObj->AddressSpace.Next;
479        }
480    }
481    else
482    {
483        ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
484            "Creating object on Device %p while installing handler\n", Node));
485
486        /* ObjDesc does not exist, create one */
487
488        if (Node->Type == ACPI_TYPE_ANY)
489        {
490            Type = ACPI_TYPE_DEVICE;
491        }
492        else
493        {
494            Type = Node->Type;
495        }
496
497        ObjDesc = AcpiUtCreateInternalObject (Type);
498        if (!ObjDesc)
499        {
500            Status = AE_NO_MEMORY;
501            goto UnlockAndExit;
502        }
503
504        /* Init new descriptor */
505
506        ObjDesc->Common.Type = (UINT8) Type;
507
508        /* Attach the new object to the Node */
509
510        Status = AcpiNsAttachObject (Node, ObjDesc, Type);
511
512        /* Remove local reference to the object */
513
514        AcpiUtRemoveReference (ObjDesc);
515
516        if (ACPI_FAILURE (Status))
517        {
518            goto UnlockAndExit;
519        }
520    }
521
522    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
523        "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
524        AcpiUtGetRegionName (SpaceId), SpaceId,
525        AcpiUtGetNodeName (Node), Node, ObjDesc));
526
527    /*
528     * Install the handler
529     *
530     * At this point there is no existing handler. Just allocate the object
531     * for the handler and link it into the list.
532     */
533    HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
534    if (!HandlerObj)
535    {
536        Status = AE_NO_MEMORY;
537        goto UnlockAndExit;
538    }
539
540    /* Init handler obj */
541
542    HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
543    HandlerObj->AddressSpace.HandlerFlags = Flags;
544    HandlerObj->AddressSpace.RegionList = NULL;
545    HandlerObj->AddressSpace.Node = Node;
546    HandlerObj->AddressSpace.Handler = Handler;
547    HandlerObj->AddressSpace.Context = Context;
548    HandlerObj->AddressSpace.Setup  = Setup;
549
550    /* Install at head of Device.AddressSpace list */
551
552    HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
553
554    /*
555     * The Device object is the first reference on the HandlerObj.
556     * Each region that uses the handler adds a reference.
557     */
558    ObjDesc->Device.Handler = HandlerObj;
559
560    /*
561     * Walk the namespace finding all of the regions this
562     * handler will manage.
563     *
564     * Start at the device and search the branch toward
565     * the leaf nodes until either the leaf is encountered or
566     * a device is detected that has an address handler of the
567     * same type.
568     *
569     * In either case, back up and search down the remainder
570     * of the branch
571     */
572    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
573                ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL,
574                HandlerObj, NULL);
575
576UnlockAndExit:
577    return_ACPI_STATUS (Status);
578}
579