xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/events/evhandler.c (revision a3e794ae459fec76826407f8ba8c94cd3535f128)
1 /******************************************************************************
2  *
3  * Module Name: evhandler - Support for Address Space handlers
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2016, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115 
116 #include "acpi.h"
117 #include "accommon.h"
118 #include "acevents.h"
119 #include "acnamesp.h"
120 #include "acinterp.h"
121 
122 #define _COMPONENT          ACPI_EVENTS
123         ACPI_MODULE_NAME    ("evhandler")
124 
125 
126 /* Local prototypes */
127 
128 static ACPI_STATUS
129 AcpiEvInstallHandler (
130     ACPI_HANDLE             ObjHandle,
131     UINT32                  Level,
132     void                    *Context,
133     void                    **ReturnValue);
134 
135 
136 /* These are the address spaces that will get default handlers */
137 
138 UINT8        AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
139 {
140     ACPI_ADR_SPACE_SYSTEM_MEMORY,
141     ACPI_ADR_SPACE_SYSTEM_IO,
142     ACPI_ADR_SPACE_PCI_CONFIG,
143     ACPI_ADR_SPACE_DATA_TABLE
144 };
145 
146 
147 /*******************************************************************************
148  *
149  * FUNCTION:    AcpiEvInstallRegionHandlers
150  *
151  * PARAMETERS:  None
152  *
153  * RETURN:      Status
154  *
155  * DESCRIPTION: Installs the core subsystem default address space handlers.
156  *
157  ******************************************************************************/
158 
159 ACPI_STATUS
160 AcpiEvInstallRegionHandlers (
161     void)
162 {
163     ACPI_STATUS             Status;
164     UINT32                  i;
165 
166 
167     ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
168 
169 
170     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
171     if (ACPI_FAILURE (Status))
172     {
173         return_ACPI_STATUS (Status);
174     }
175 
176     /*
177      * All address spaces (PCI Config, EC, SMBus) are scope dependent and
178      * registration must occur for a specific device.
179      *
180      * In the case of the system memory and IO address spaces there is
181      * currently no device associated with the address space. For these we
182      * use the root.
183      *
184      * We install the default PCI config space handler at the root so that
185      * this space is immediately available even though the we have not
186      * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
187      * specification which states that the PCI config space must be always
188      * available -- even though we are nowhere near ready to find the PCI root
189      * buses at this point.
190      *
191      * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
192      * has already been installed (via AcpiInstallAddressSpaceHandler).
193      * Similar for AE_SAME_HANDLER.
194      */
195     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
196     {
197         Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
198             AcpiGbl_DefaultAddressSpaces[i],
199             ACPI_DEFAULT_HANDLER, NULL, NULL);
200         switch (Status)
201         {
202         case AE_OK:
203         case AE_SAME_HANDLER:
204         case AE_ALREADY_EXISTS:
205 
206             /* These exceptions are all OK */
207 
208             Status = AE_OK;
209             break;
210 
211         default:
212 
213             goto UnlockAndExit;
214         }
215     }
216 
217 UnlockAndExit:
218     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
219     return_ACPI_STATUS (Status);
220 }
221 
222 
223 /*******************************************************************************
224  *
225  * FUNCTION:    AcpiEvHasDefaultHandler
226  *
227  * PARAMETERS:  Node                - Namespace node for the device
228  *              SpaceId             - The address space ID
229  *
230  * RETURN:      TRUE if default handler is installed, FALSE otherwise
231  *
232  * DESCRIPTION: Check if the default handler is installed for the requested
233  *              space ID.
234  *
235  ******************************************************************************/
236 
237 BOOLEAN
238 AcpiEvHasDefaultHandler (
239     ACPI_NAMESPACE_NODE     *Node,
240     ACPI_ADR_SPACE_TYPE     SpaceId)
241 {
242     ACPI_OPERAND_OBJECT     *ObjDesc;
243     ACPI_OPERAND_OBJECT     *HandlerObj;
244 
245 
246     /* Must have an existing internal object */
247 
248     ObjDesc = AcpiNsGetAttachedObject (Node);
249     if (ObjDesc)
250     {
251         HandlerObj = ObjDesc->CommonNotify.Handler;
252 
253         /* Walk the linked list of handlers for this object */
254 
255         while (HandlerObj)
256         {
257             if (HandlerObj->AddressSpace.SpaceId == SpaceId)
258             {
259                 if (HandlerObj->AddressSpace.HandlerFlags &
260                     ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
261                 {
262                     return (TRUE);
263                 }
264             }
265 
266             HandlerObj = HandlerObj->AddressSpace.Next;
267         }
268     }
269 
270     return (FALSE);
271 }
272 
273 
274 /*******************************************************************************
275  *
276  * FUNCTION:    AcpiEvInstallHandler
277  *
278  * PARAMETERS:  WalkNamespace callback
279  *
280  * DESCRIPTION: This routine installs an address handler into objects that are
281  *              of type Region or Device.
282  *
283  *              If the Object is a Device, and the device has a handler of
284  *              the same type then the search is terminated in that branch.
285  *
286  *              This is because the existing handler is closer in proximity
287  *              to any more regions than the one we are trying to install.
288  *
289  ******************************************************************************/
290 
291 static ACPI_STATUS
292 AcpiEvInstallHandler (
293     ACPI_HANDLE             ObjHandle,
294     UINT32                  Level,
295     void                    *Context,
296     void                    **ReturnValue)
297 {
298     ACPI_OPERAND_OBJECT     *HandlerObj;
299     ACPI_OPERAND_OBJECT     *NextHandlerObj;
300     ACPI_OPERAND_OBJECT     *ObjDesc;
301     ACPI_NAMESPACE_NODE     *Node;
302     ACPI_STATUS             Status;
303 
304 
305     ACPI_FUNCTION_NAME (EvInstallHandler);
306 
307 
308     HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
309 
310     /* Parameter validation */
311 
312     if (!HandlerObj)
313     {
314         return (AE_OK);
315     }
316 
317     /* Convert and validate the device handle */
318 
319     Node = AcpiNsValidateHandle (ObjHandle);
320     if (!Node)
321     {
322         return (AE_BAD_PARAMETER);
323     }
324 
325     /*
326      * We only care about regions and objects that are allowed to have
327      * address space handlers
328      */
329     if ((Node->Type != ACPI_TYPE_DEVICE) &&
330         (Node->Type != ACPI_TYPE_REGION) &&
331         (Node != AcpiGbl_RootNode))
332     {
333         return (AE_OK);
334     }
335 
336     /* Check for an existing internal object */
337 
338     ObjDesc = AcpiNsGetAttachedObject (Node);
339     if (!ObjDesc)
340     {
341         /* No object, just exit */
342 
343         return (AE_OK);
344     }
345 
346     /* Devices are handled different than regions */
347 
348     if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
349     {
350         /* Check if this Device already has a handler for this address space */
351 
352         NextHandlerObj = AcpiEvFindRegionHandler (
353             HandlerObj->AddressSpace.SpaceId, ObjDesc->CommonNotify.Handler);
354         if (NextHandlerObj)
355         {
356             /* Found a handler, is it for the same address space? */
357 
358             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
359                 "Found handler for region [%s] in device %p(%p) handler %p\n",
360                 AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
361                 ObjDesc, NextHandlerObj, HandlerObj));
362 
363             /*
364              * Since the object we found it on was a device, then it means
365              * that someone has already installed a handler for the branch
366              * of the namespace from this device on. Just bail out telling
367              * the walk routine to not traverse this branch. This preserves
368              * the scoping rule for handlers.
369              */
370             return (AE_CTRL_DEPTH);
371         }
372 
373         /*
374          * As long as the device didn't have a handler for this space we
375          * don't care about it. We just ignore it and proceed.
376          */
377         return (AE_OK);
378     }
379 
380     /* Object is a Region */
381 
382     if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
383     {
384         /* This region is for a different address space, just ignore it */
385 
386         return (AE_OK);
387     }
388 
389     /*
390      * Now we have a region and it is for the handler's address space type.
391      *
392      * First disconnect region for any previous handler (if any)
393      */
394     AcpiEvDetachRegion (ObjDesc, FALSE);
395 
396     /* Connect the region to the new handler */
397 
398     Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
399     return (Status);
400 }
401 
402 
403 /*******************************************************************************
404  *
405  * FUNCTION:    AcpiEvFindRegionHandler
406  *
407  * PARAMETERS:  SpaceId         - The address space ID
408  *              HandlerObj      - Head of the handler object list
409  *
410  * RETURN:      Matching handler object. NULL if space ID not matched
411  *
412  * DESCRIPTION: Search a handler object list for a match on the address
413  *              space ID.
414  *
415  ******************************************************************************/
416 
417 ACPI_OPERAND_OBJECT *
418 AcpiEvFindRegionHandler (
419     ACPI_ADR_SPACE_TYPE     SpaceId,
420     ACPI_OPERAND_OBJECT     *HandlerObj)
421 {
422 
423     /* Walk the handler list for this device */
424 
425     while (HandlerObj)
426     {
427         /* Same SpaceId indicates a handler is installed */
428 
429         if (HandlerObj->AddressSpace.SpaceId == SpaceId)
430         {
431             return (HandlerObj);
432         }
433 
434         /* Next handler object */
435 
436         HandlerObj = HandlerObj->AddressSpace.Next;
437     }
438 
439     return (NULL);
440 }
441 
442 
443 /*******************************************************************************
444  *
445  * FUNCTION:    AcpiEvInstallSpaceHandler
446  *
447  * PARAMETERS:  Node            - Namespace node for the device
448  *              SpaceId         - The address space ID
449  *              Handler         - Address of the handler
450  *              Setup           - Address of the setup function
451  *              Context         - Value passed to the handler on each access
452  *
453  * RETURN:      Status
454  *
455  * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
456  *              Assumes namespace is locked
457  *
458  ******************************************************************************/
459 
460 ACPI_STATUS
461 AcpiEvInstallSpaceHandler (
462     ACPI_NAMESPACE_NODE     *Node,
463     ACPI_ADR_SPACE_TYPE     SpaceId,
464     ACPI_ADR_SPACE_HANDLER  Handler,
465     ACPI_ADR_SPACE_SETUP    Setup,
466     void                    *Context)
467 {
468     ACPI_OPERAND_OBJECT     *ObjDesc;
469     ACPI_OPERAND_OBJECT     *HandlerObj;
470     ACPI_STATUS             Status = AE_OK;
471     ACPI_OBJECT_TYPE        Type;
472     UINT8                   Flags = 0;
473 
474 
475     ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
476 
477 
478     /*
479      * This registration is valid for only the types below and the root.
480      * The root node is where the default handlers get installed.
481      */
482     if ((Node->Type != ACPI_TYPE_DEVICE)     &&
483         (Node->Type != ACPI_TYPE_PROCESSOR)  &&
484         (Node->Type != ACPI_TYPE_THERMAL)    &&
485         (Node != AcpiGbl_RootNode))
486     {
487         Status = AE_BAD_PARAMETER;
488         goto UnlockAndExit;
489     }
490 
491     if (Handler == ACPI_DEFAULT_HANDLER)
492     {
493         Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
494 
495         switch (SpaceId)
496         {
497         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
498 
499             Handler = AcpiExSystemMemorySpaceHandler;
500             Setup   = AcpiEvSystemMemoryRegionSetup;
501             break;
502 
503         case ACPI_ADR_SPACE_SYSTEM_IO:
504 
505             Handler = AcpiExSystemIoSpaceHandler;
506             Setup   = AcpiEvIoSpaceRegionSetup;
507             break;
508 
509         case ACPI_ADR_SPACE_PCI_CONFIG:
510 
511             Handler = AcpiExPciConfigSpaceHandler;
512             Setup   = AcpiEvPciConfigRegionSetup;
513             break;
514 
515         case ACPI_ADR_SPACE_CMOS:
516 
517             Handler = AcpiExCmosSpaceHandler;
518             Setup   = AcpiEvCmosRegionSetup;
519             break;
520 
521         case ACPI_ADR_SPACE_PCI_BAR_TARGET:
522 
523             Handler = AcpiExPciBarSpaceHandler;
524             Setup   = AcpiEvPciBarRegionSetup;
525             break;
526 
527         case ACPI_ADR_SPACE_DATA_TABLE:
528 
529             Handler = AcpiExDataTableSpaceHandler;
530             Setup   = NULL;
531             break;
532 
533         default:
534 
535             Status = AE_BAD_PARAMETER;
536             goto UnlockAndExit;
537         }
538     }
539 
540     /* If the caller hasn't specified a setup routine, use the default */
541 
542     if (!Setup)
543     {
544         Setup = AcpiEvDefaultRegionSetup;
545     }
546 
547     /* Check for an existing internal object */
548 
549     ObjDesc = AcpiNsGetAttachedObject (Node);
550     if (ObjDesc)
551     {
552         /*
553          * The attached device object already exists. Now make sure
554          * the handler is not already installed.
555          */
556         HandlerObj = AcpiEvFindRegionHandler (SpaceId,
557             ObjDesc->CommonNotify.Handler);
558 
559         if (HandlerObj)
560         {
561             if (HandlerObj->AddressSpace.Handler == Handler)
562             {
563                 /*
564                  * It is (relatively) OK to attempt to install the SAME
565                  * handler twice. This can easily happen with the
566                  * PCI_Config space.
567                  */
568                 Status = AE_SAME_HANDLER;
569                 goto UnlockAndExit;
570             }
571             else
572             {
573                 /* A handler is already installed */
574 
575                 Status = AE_ALREADY_EXISTS;
576             }
577 
578             goto UnlockAndExit;
579         }
580     }
581     else
582     {
583         ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
584             "Creating object on Device %p while installing handler\n",
585             Node));
586 
587         /* ObjDesc does not exist, create one */
588 
589         if (Node->Type == ACPI_TYPE_ANY)
590         {
591             Type = ACPI_TYPE_DEVICE;
592         }
593         else
594         {
595             Type = Node->Type;
596         }
597 
598         ObjDesc = AcpiUtCreateInternalObject (Type);
599         if (!ObjDesc)
600         {
601             Status = AE_NO_MEMORY;
602             goto UnlockAndExit;
603         }
604 
605         /* Init new descriptor */
606 
607         ObjDesc->Common.Type = (UINT8) Type;
608 
609         /* Attach the new object to the Node */
610 
611         Status = AcpiNsAttachObject (Node, ObjDesc, Type);
612 
613         /* Remove local reference to the object */
614 
615         AcpiUtRemoveReference (ObjDesc);
616 
617         if (ACPI_FAILURE (Status))
618         {
619             goto UnlockAndExit;
620         }
621     }
622 
623     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
624         "Installing address handler for region %s(%X) "
625         "on Device %4.4s %p(%p)\n",
626         AcpiUtGetRegionName (SpaceId), SpaceId,
627         AcpiUtGetNodeName (Node), Node, ObjDesc));
628 
629     /*
630      * Install the handler
631      *
632      * At this point there is no existing handler. Just allocate the object
633      * for the handler and link it into the list.
634      */
635     HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
636     if (!HandlerObj)
637     {
638         Status = AE_NO_MEMORY;
639         goto UnlockAndExit;
640     }
641 
642     /* Init handler obj */
643 
644     HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
645     HandlerObj->AddressSpace.HandlerFlags = Flags;
646     HandlerObj->AddressSpace.RegionList = NULL;
647     HandlerObj->AddressSpace.Node = Node;
648     HandlerObj->AddressSpace.Handler = Handler;
649     HandlerObj->AddressSpace.Context = Context;
650     HandlerObj->AddressSpace.Setup = Setup;
651 
652     /* Install at head of Device.AddressSpace list */
653 
654     HandlerObj->AddressSpace.Next = ObjDesc->CommonNotify.Handler;
655 
656     /*
657      * The Device object is the first reference on the HandlerObj.
658      * Each region that uses the handler adds a reference.
659      */
660     ObjDesc->CommonNotify.Handler = HandlerObj;
661 
662     /*
663      * Walk the namespace finding all of the regions this handler will
664      * manage.
665      *
666      * Start at the device and search the branch toward the leaf nodes
667      * until either the leaf is encountered or a device is detected that
668      * has an address handler of the same type.
669      *
670      * In either case, back up and search down the remainder of the branch
671      */
672     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node,
673         ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
674         AcpiEvInstallHandler, NULL, HandlerObj, NULL);
675 
676 UnlockAndExit:
677     return_ACPI_STATUS (Status);
678 }
679